vike
Version:
The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.
81 lines (80 loc) • 4.15 kB
JavaScript
export { renderPageAlreadyRouted };
export { prerenderPage };
import { getErrorPageId } from '../../../shared/error-page.js';
import { getHtmlString } from '../html/renderHtml.js';
import { assert, assertUsage, augmentType, hasProp, objectAssign } from '../utils.js';
import { getPageContextClientSerialized } from '../html/serializeContext.js';
import { createHttpResponsePage, createHttpResponsePageContextJson } from './createHttpResponse.js';
import { loadPageConfigsLazyServerSideAndExecHook, } from './loadPageConfigsLazyServerSide.js';
import { execHookOnRenderHtml } from './execHookOnRenderHtml.js';
import { execHookDataAndOnBeforeRender } from './execHookDataAndOnBeforeRender.js';
import { logRuntimeError } from '../loggerRuntime.js';
import { isNewError } from './isNewError.js';
import { preparePageContextForPublicUsageServer } from './preparePageContextForPublicUsageServer.js';
import { execHookGuard } from '../../../shared/route/execHookGuard.js';
import pc from '@brillout/picocolors';
import { isServerSideError } from '../../../shared/misc/isServerSideError.js';
async function renderPageAlreadyRouted(pageContext) {
// pageContext.pageId can either be the:
// - ID of the page matching the routing, or the
// - ID of the error page `_error.page.js`.
assert(hasProp(pageContext, 'pageId', 'string'));
const isError = pageContext.is404 || !!pageContext.errorWhileRendering;
assert(isError ===
(pageContext.pageId ===
getErrorPageId(pageContext._globalContext._pageFilesAll, pageContext._globalContext._pageConfigs)));
augmentType(pageContext, await loadPageConfigsLazyServerSideAndExecHook(pageContext));
if (!isError) {
await execHookGuard(pageContext, (pageContext) => preparePageContextForPublicUsageServer(pageContext));
}
if (!isError) {
await execHookDataAndOnBeforeRender(pageContext);
}
else {
try {
await execHookDataAndOnBeforeRender(pageContext);
}
catch (err) {
if (isNewError(err, pageContext.errorWhileRendering)) {
logRuntimeError(err, pageContext._httpRequestId);
}
}
}
if (pageContext.isClientSideNavigation) {
if (isError) {
objectAssign(pageContext, { [isServerSideError]: true });
}
const pageContextSerialized = getPageContextClientSerialized(pageContext);
const httpResponse = await createHttpResponsePageContextJson(pageContextSerialized);
objectAssign(pageContext, { httpResponse });
return pageContext;
}
const renderHookResult = await execHookOnRenderHtml(pageContext);
const { htmlRender, renderHook } = renderHookResult;
const httpResponse = await createHttpResponsePage(htmlRender, renderHook, pageContext);
objectAssign(pageContext, { httpResponse });
return pageContext;
}
async function prerenderPage(pageContext) {
objectAssign(pageContext, {
isClientSideNavigation: false,
_urlHandler: null,
});
/* Should we execute the guard() hook upon pre-rendering? Is there a use case for this?
* - It isn't trivial to implement, as it requires to duplicate / factor out the isAbortError() handling
await execHookGuard(pageContext, (pageContext) => preparePageContextForPublicUsageServer(pageContext))
*/
await execHookDataAndOnBeforeRender(pageContext);
const { htmlRender, renderHook } = await execHookOnRenderHtml(pageContext);
assertUsage(htmlRender !== null, `Cannot pre-render ${pc.cyan(pageContext.urlOriginal)} because the ${renderHook.hookName}() hook defined by ${renderHook.hookFilePath} didn't return an HTML string.`);
assert(pageContext.isClientSideNavigation === false);
const documentHtml = await getHtmlString(htmlRender);
assert(typeof documentHtml === 'string');
if (!pageContext._usesClientRouter) {
return { documentHtml, pageContextSerialized: null, pageContext };
}
else {
const pageContextSerialized = getPageContextClientSerialized(pageContext);
return { documentHtml, pageContextSerialized, pageContext };
}
}