vike 0.4.227-commit-e36b916 → 0.4.227-commit-25aa0f8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/node/plugin/plugins/commonConfig.js +2 -1
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +1 -0
- package/dist/cjs/node/plugin/shared/resolveClientEntriesDev.js +2 -1
- package/dist/cjs/node/prerender/runPrerender.js +168 -150
- package/dist/cjs/node/prerender/utils.js +1 -1
- package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +0 -23
- package/dist/cjs/shared/route/index.js +13 -11
- package/dist/cjs/utils/PROJECT_VERSION.js +1 -1
- package/dist/cjs/utils/preservePropertyGetters.js +30 -0
- package/dist/esm/node/plugin/plugins/commonConfig.js +2 -1
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +1 -0
- package/dist/esm/node/plugin/shared/resolveClientEntriesDev.js +2 -1
- package/dist/esm/node/prerender/runPrerender.d.ts +2 -0
- package/dist/esm/node/prerender/runPrerender.js +171 -153
- package/dist/esm/node/prerender/utils.d.ts +1 -1
- package/dist/esm/node/prerender/utils.js +1 -1
- package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.d.ts +0 -182
- package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +0 -23
- package/dist/esm/shared/route/index.d.ts +1 -1
- package/dist/esm/shared/route/index.js +13 -11
- package/dist/esm/utils/PROJECT_VERSION.d.ts +1 -1
- package/dist/esm/utils/PROJECT_VERSION.js +1 -1
- package/dist/esm/utils/preservePropertyGetters.d.ts +2 -0
- package/dist/esm/utils/preservePropertyGetters.js +28 -0
- package/package.json +1 -1
|
@@ -568,6 +568,7 @@ function getConfigValueSource(configName, plusFile, configDef, userRootDir) {
|
|
|
568
568
|
// Defined over pointer import
|
|
569
569
|
assert(confVal.valueIsLoaded);
|
|
570
570
|
const pointerImport = resolvePointerImport(confVal.value, plusFile.filePath, userRootDir, configName);
|
|
571
|
+
console.log('pointerImport', pointerImport);
|
|
571
572
|
const configDefinedAt = getConfigDefinedAt('Config', configName, definedAtFilePath_);
|
|
572
573
|
assertUsage(pointerImport, `${configDefinedAt} should be an import`);
|
|
573
574
|
valueFilePath = pointerImport.fileExportPath.filePathAbsoluteVite;
|
|
@@ -3,7 +3,6 @@ import { assert, assertPosixPath, toPosixPath, pathJoin, assertIsNpmPackageImpor
|
|
|
3
3
|
import { createRequire } from 'module';
|
|
4
4
|
// @ts-ignore import.meta.url is shimmed at dist/cjs by dist-cjs-fixup.js.
|
|
5
5
|
const importMetaUrl = import.meta.url;
|
|
6
|
-
const require_ = createRequire(importMetaUrl);
|
|
7
6
|
assertIsNotProductionRuntime();
|
|
8
7
|
async function resolveClientEntriesDev(clientEntry, viteDevServer) {
|
|
9
8
|
let root = viteDevServer.config.root;
|
|
@@ -26,6 +25,7 @@ async function resolveClientEntriesDev(clientEntry, viteDevServer) {
|
|
|
26
25
|
}
|
|
27
26
|
else {
|
|
28
27
|
if (clientEntry.startsWith('@@vike/')) {
|
|
28
|
+
const require_ = createRequire(importMetaUrl);
|
|
29
29
|
assert(clientEntry.endsWith('.js'));
|
|
30
30
|
try {
|
|
31
31
|
// For Vitest (which doesn't resolve vike to its dist but to its source files)
|
|
@@ -39,6 +39,7 @@ async function resolveClientEntriesDev(clientEntry, viteDevServer) {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
else {
|
|
42
|
+
const require_ = createRequire(root);
|
|
42
43
|
assertIsNpmPackageImport(clientEntry);
|
|
43
44
|
filePath = require_.resolve(clientEntry);
|
|
44
45
|
}
|
|
@@ -14,6 +14,7 @@ type ProvidedByHook = null | {
|
|
|
14
14
|
type PageContextPrerendered = {
|
|
15
15
|
urlOriginal: string;
|
|
16
16
|
_providedByHook?: ProvidedByHook;
|
|
17
|
+
pageId: string;
|
|
17
18
|
};
|
|
18
19
|
type Output<PageContext = PageContextPrerendered> = {
|
|
19
20
|
filePath: string;
|
|
@@ -53,4 +54,5 @@ declare function runPrerender_forceExit(): void;
|
|
|
53
54
|
type PrerenderContextPublic = {
|
|
54
55
|
output: Output<PageContextServer>;
|
|
55
56
|
pageContexts: PageContextServer[];
|
|
57
|
+
pageContexts404: PageContextServer;
|
|
56
58
|
};
|
|
@@ -4,8 +4,8 @@ export { runPrerenderFromAutoRun };
|
|
|
4
4
|
export { runPrerender_forceExit };
|
|
5
5
|
import path from 'path';
|
|
6
6
|
import { route } from '../../shared/route/index.js';
|
|
7
|
-
import { assert, assertUsage, assertWarning, hasProp, objectAssign, isObjectWithKeys, isCallable, isPropertyGetter, assertPosixPath, urlToFile, isPlainObject, pLimit, isArray,
|
|
8
|
-
import { prerenderPage,
|
|
7
|
+
import { assert, assertUsage, assertWarning, hasProp, objectAssign, isObjectWithKeys, isCallable, isPropertyGetter, assertPosixPath, urlToFile, isPlainObject, pLimit, isArray, onSetupPrerender, isObject, makePublicCopy, PROJECT_VERSION, preservePropertyGetters } from './utils.js';
|
|
8
|
+
import { prerenderPage, getPageContextInitEnhanced } from '../runtime/renderPage/renderPageAlreadyRouted.js';
|
|
9
9
|
import pc from '@brillout/picocolors';
|
|
10
10
|
import { cpus } from 'os';
|
|
11
11
|
import { getGlobalContextInternal, initGlobalContext_runPrerender, setGlobalContext_isPrerendering } from '../runtime/globalContext.js';
|
|
@@ -15,8 +15,7 @@ import { getPageContextRequestUrl } from '../../shared/getPageContextRequestUrl.
|
|
|
15
15
|
import { getUrlFromRouteString } from '../../shared/route/resolveRouteString.js';
|
|
16
16
|
import { getConfigValueRuntime } from '../../shared/page-configs/getConfigValueRuntime.js';
|
|
17
17
|
import { loadConfigValues } from '../../shared/page-configs/loadConfigValues.js';
|
|
18
|
-
import { isErrorPage } from '../../shared/error-page.js';
|
|
19
|
-
import { getPageContextUrlComputed } from '../../shared/getPageContextUrlComputed.js';
|
|
18
|
+
import { getErrorPageId, isErrorPage } from '../../shared/error-page.js';
|
|
20
19
|
import { isAbortError } from '../../shared/route/abort.js';
|
|
21
20
|
import { loadUserFilesServerSide } from '../runtime/renderPage/loadUserFilesServerSide.js';
|
|
22
21
|
import { getHookFromPageConfig, getHookFromPageConfigGlobal, getHookTimeoutDefault, getHook_setIsPrerenderering } from '../../shared/hooks/getHook.js';
|
|
@@ -86,8 +85,7 @@ async function runPrerender(options = {}, standaloneTrigger) {
|
|
|
86
85
|
const { partial, noExtraDir, parallel, defaultLocalValue, isPrerenderingEnabled } = prerenderConfigGlobal;
|
|
87
86
|
if (!isPrerenderingEnabled) {
|
|
88
87
|
assert(standaloneTrigger);
|
|
89
|
-
|
|
90
|
-
assertWarning(false, `You're executing ${pc.cyan(standaloneTrigger)} but you didn't enable pre-rendering. Use the ${pc.cyan('prerender')} setting (${pc.underline('https://vike.dev/prerender')}) to enable pre-rendering for at least one page.`, { onlyOnce: true });
|
|
88
|
+
assertUsage(false, `You're executing ${pc.cyan(standaloneTrigger)} but you didn't enable pre-rendering. Use the ${pc.cyan('prerender')} setting (${pc.underline('https://vike.dev/prerender')}) to enable pre-rendering for at least one page.`);
|
|
91
89
|
}
|
|
92
90
|
const concurrencyLimit = pLimit(parallel === false || parallel === 0 ? 1 : parallel === true || parallel === undefined ? cpus().length : parallel);
|
|
93
91
|
await initGlobalContext_runPrerender();
|
|
@@ -96,27 +94,37 @@ async function runPrerender(options = {}, standaloneTrigger) {
|
|
|
96
94
|
const prerenderContext = {
|
|
97
95
|
noExtraDir: noExtraDir ?? false,
|
|
98
96
|
pageContexts: [],
|
|
97
|
+
pageContexts404: [],
|
|
99
98
|
pageContextInit: options.pageContextInit ?? null,
|
|
100
99
|
prerenderedPageContexts: {},
|
|
101
100
|
output: []
|
|
102
101
|
};
|
|
103
102
|
const doNotPrerenderList = [];
|
|
104
103
|
await collectDoNoPrerenderList(vikeConfig.pageConfigs, doNotPrerenderList, defaultLocalValue, concurrencyLimit, globalContext);
|
|
104
|
+
// Allow user to create `pageContext` for parameterized routes and/or bulk data fetching
|
|
105
|
+
// https://vike.dev/onBeforePrerenderStart
|
|
105
106
|
await callOnBeforePrerenderStartHooks(prerenderContext, globalContext, concurrencyLimit, doNotPrerenderList);
|
|
106
|
-
|
|
107
|
-
|
|
107
|
+
// Create `pageContext` for each page with a static route
|
|
108
|
+
const urlList = getUrlListFromPagesWithStaticRoute(globalContext, doNotPrerenderList);
|
|
109
|
+
await createPageContextsForOnPrerenderStartHook(urlList, prerenderContext, globalContext, concurrencyLimit, false);
|
|
110
|
+
// Create `pageContext` for 404 page
|
|
111
|
+
const urlList404 = getUrlList404(globalContext);
|
|
112
|
+
await createPageContextsForOnPrerenderStartHook(urlList404, prerenderContext, globalContext, concurrencyLimit, true);
|
|
113
|
+
// Allow user to duplicate the list of `pageContext` for i18n
|
|
114
|
+
// https://vike.dev/onPrerenderStart
|
|
115
|
+
await callOnPrerenderStartHook(prerenderContext, globalContext, concurrencyLimit);
|
|
108
116
|
let prerenderedCount = 0;
|
|
109
117
|
// Write files as soon as pages finish rendering (instead of writing all files at once only after all pages have rendered).
|
|
110
118
|
const onComplete = async (htmlFile) => {
|
|
111
119
|
prerenderedCount++;
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
120
|
+
const { pageId } = htmlFile.pageContext;
|
|
121
|
+
assert(pageId);
|
|
122
|
+
prerenderContext.prerenderedPageContexts[pageId] = htmlFile.pageContext;
|
|
115
123
|
await writeFiles(htmlFile, root, outDirClient, options.onPagePrerender, prerenderContext.output, logLevel);
|
|
116
124
|
};
|
|
117
|
-
await
|
|
125
|
+
await prerenderPages(prerenderContext, concurrencyLimit, onComplete);
|
|
118
126
|
warnContradictoryNoPrerenderList(prerenderContext.prerenderedPageContexts, doNotPrerenderList);
|
|
119
|
-
await
|
|
127
|
+
await prerenderPages404(prerenderContext, onComplete, concurrencyLimit);
|
|
120
128
|
if (logLevel === 'info') {
|
|
121
129
|
console.log(`${pc.green(`✓`)} ${prerenderedCount} HTML documents pre-rendered.`);
|
|
122
130
|
}
|
|
@@ -228,12 +236,13 @@ async function callOnBeforePrerenderStartHooks(prerenderContext, globalContext,
|
|
|
228
236
|
});
|
|
229
237
|
})));
|
|
230
238
|
await Promise.all(onBeforePrerenderStartHooks.map(({ hookFn, hookName, hookFilePath, pageId, hookTimeout }) => concurrencyLimit(async () => {
|
|
231
|
-
if (doNotPrerenderList.find((p) => p.pageId === pageId))
|
|
239
|
+
if (doNotPrerenderList.find((p) => p.pageId === pageId))
|
|
232
240
|
return;
|
|
233
|
-
}
|
|
234
241
|
const prerenderResult = await executeHook(() => hookFn(), { hookName, hookFilePath, hookTimeout }, null);
|
|
235
242
|
const result = normalizeOnPrerenderHookResult(prerenderResult, hookFilePath, hookName);
|
|
243
|
+
// Handle result
|
|
236
244
|
await Promise.all(result.map(async ({ url, pageContext }) => {
|
|
245
|
+
// Assert no duplication
|
|
237
246
|
{
|
|
238
247
|
const pageContextFound = prerenderContext.pageContexts.find((pageContext) => isSameUrl(pageContext.urlOriginal, url));
|
|
239
248
|
if (pageContextFound) {
|
|
@@ -244,30 +253,23 @@ async function callOnBeforePrerenderStartHooks(prerenderContext, globalContext,
|
|
|
244
253
|
assertUsage(false, `URL ${pc.cyan(url)} provided ${providedTwice}. Make sure to provide the URL only once instead.`);
|
|
245
254
|
}
|
|
246
255
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
hookFilePath,
|
|
251
|
-
hookName
|
|
252
|
-
}
|
|
253
|
-
});
|
|
256
|
+
// Add result
|
|
257
|
+
const providedByHook = { hookFilePath, hookName };
|
|
258
|
+
const pageContextNew = await createPageContext(url, prerenderContext, globalContext, false, undefined, providedByHook);
|
|
254
259
|
prerenderContext.pageContexts.push(pageContextNew);
|
|
255
260
|
if (pageContext) {
|
|
256
|
-
objectAssign(pageContextNew, {
|
|
257
|
-
_pageContextAlreadyProvidedByOnPrerenderHook: true
|
|
258
|
-
});
|
|
261
|
+
objectAssign(pageContextNew, { _pageContextAlreadyProvidedByOnPrerenderHook: true });
|
|
259
262
|
objectAssign(pageContextNew, pageContext);
|
|
260
263
|
}
|
|
261
264
|
}));
|
|
262
265
|
})));
|
|
263
266
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
+
function getUrlListFromPagesWithStaticRoute(globalContext, doNotPrerenderList) {
|
|
268
|
+
const urlList = [];
|
|
269
|
+
globalContext.pageRoutes.map((pageRoute) => {
|
|
267
270
|
const { pageId } = pageRoute;
|
|
268
|
-
if (doNotPrerenderList.find((p) => p.pageId === pageId))
|
|
271
|
+
if (doNotPrerenderList.find((p) => p.pageId === pageId))
|
|
269
272
|
return;
|
|
270
|
-
}
|
|
271
273
|
let urlOriginal;
|
|
272
274
|
if (!('routeString' in pageRoute)) {
|
|
273
275
|
// Abort since the page's route is a Route Function
|
|
@@ -283,43 +285,116 @@ async function handlePagesWithStaticRoutes(prerenderContext, globalContext, doNo
|
|
|
283
285
|
urlOriginal = url;
|
|
284
286
|
}
|
|
285
287
|
assert(urlOriginal.startsWith('/'));
|
|
288
|
+
urlList.push({ urlOriginal, pageId });
|
|
289
|
+
});
|
|
290
|
+
return urlList;
|
|
291
|
+
}
|
|
292
|
+
function getUrlList404(globalContext) {
|
|
293
|
+
const urlList = [];
|
|
294
|
+
const errorPageId = getErrorPageId(globalContext.pageFilesAll, globalContext.pageConfigs);
|
|
295
|
+
if (errorPageId) {
|
|
296
|
+
urlList.push({
|
|
297
|
+
// A URL is required for `viteDevServer.transformIndexHtml(url,html)`
|
|
298
|
+
urlOriginal: '/404',
|
|
299
|
+
pageId: errorPageId
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
return urlList;
|
|
303
|
+
}
|
|
304
|
+
async function createPageContextsForOnPrerenderStartHook(urlList, prerenderContext, globalContext, concurrencyLimit, is404) {
|
|
305
|
+
await Promise.all(urlList.map(({ urlOriginal, pageId }) => concurrencyLimit(async () => {
|
|
286
306
|
// Already included in a onBeforePrerenderStart() hook
|
|
287
|
-
if (prerenderContext.pageContexts.find((pageContext) => isSameUrl(pageContext.urlOriginal, urlOriginal))) {
|
|
307
|
+
if ([...prerenderContext.pageContexts, ...prerenderContext.pageContexts404].find((pageContext) => isSameUrl(pageContext.urlOriginal, urlOriginal))) {
|
|
288
308
|
return;
|
|
289
309
|
}
|
|
290
|
-
const
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
{
|
|
298
|
-
pageId,
|
|
299
|
-
routeType: pageRoute.routeType,
|
|
300
|
-
routeString: urlOriginal,
|
|
301
|
-
routeParams
|
|
302
|
-
}
|
|
303
|
-
]
|
|
304
|
-
});
|
|
305
|
-
objectAssign(pageContext, await loadUserFilesServerSide(pageContext));
|
|
306
|
-
prerenderContext.pageContexts.push(pageContext);
|
|
310
|
+
const pageContext = await createPageContext(urlOriginal, prerenderContext, globalContext, is404, pageId, null);
|
|
311
|
+
if (is404) {
|
|
312
|
+
prerenderContext.pageContexts404.push(pageContext);
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
prerenderContext.pageContexts.push(pageContext);
|
|
316
|
+
}
|
|
307
317
|
})));
|
|
308
318
|
}
|
|
309
|
-
async function createPageContext(urlOriginal, prerenderContext, globalContext) {
|
|
310
|
-
const pageContextInit = {
|
|
311
|
-
|
|
312
|
-
|
|
319
|
+
async function createPageContext(urlOriginal, prerenderContext, globalContext, is404, pageId, providedByHook) {
|
|
320
|
+
const pageContextInit = {
|
|
321
|
+
urlOriginal,
|
|
322
|
+
...prerenderContext.pageContextInit
|
|
323
|
+
};
|
|
324
|
+
const pageContext = await getPageContextInitEnhanced(pageContextInit, globalContext, true);
|
|
313
325
|
assert(pageContext.isPrerendering === true);
|
|
314
326
|
objectAssign(pageContext, {
|
|
315
327
|
_urlHandler: null,
|
|
328
|
+
_httpRequestId: null,
|
|
316
329
|
_urlRewrite: null,
|
|
317
330
|
_noExtraDir: prerenderContext.noExtraDir,
|
|
318
|
-
_prerenderContext: prerenderContext
|
|
331
|
+
_prerenderContext: prerenderContext,
|
|
332
|
+
_providedByHook: providedByHook,
|
|
333
|
+
_urlOriginalModifiedByHook: null,
|
|
334
|
+
is404
|
|
319
335
|
});
|
|
336
|
+
if (!is404) {
|
|
337
|
+
const pageContextFromRoute = await route(pageContext);
|
|
338
|
+
assert(hasProp(pageContextFromRoute, 'pageId', 'null') || hasProp(pageContextFromRoute, 'pageId', 'string')); // Help TS
|
|
339
|
+
assertRouteMatch(pageContextFromRoute, pageContext);
|
|
340
|
+
assert(pageContextFromRoute.pageId);
|
|
341
|
+
objectAssign(pageContext, pageContextFromRoute);
|
|
342
|
+
}
|
|
343
|
+
else {
|
|
344
|
+
assert(pageId);
|
|
345
|
+
objectAssign(pageContext, {
|
|
346
|
+
pageId,
|
|
347
|
+
_debugRouteMatches: [],
|
|
348
|
+
routeParams: {}
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
objectAssign(pageContext, await loadUserFilesServerSide(pageContext));
|
|
352
|
+
let usesClientRouter;
|
|
353
|
+
{
|
|
354
|
+
const { pageId } = pageContext;
|
|
355
|
+
assert(pageId);
|
|
356
|
+
assert(globalContext.isPrerendering);
|
|
357
|
+
if (globalContext.pageConfigs.length > 0) {
|
|
358
|
+
const pageConfig = globalContext.pageConfigs.find((p) => p.pageId === pageId);
|
|
359
|
+
assert(pageConfig);
|
|
360
|
+
usesClientRouter = getConfigValueRuntime(pageConfig, 'clientRouting', 'boolean')?.value ?? false;
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
usesClientRouter = globalContext.usesClientRouter;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
objectAssign(pageContext, { _usesClientRouter: usesClientRouter });
|
|
320
367
|
return pageContext;
|
|
321
368
|
}
|
|
322
|
-
|
|
369
|
+
function assertRouteMatch(pageContextFromRoute, pageContext) {
|
|
370
|
+
if (pageContextFromRoute.pageId !== null) {
|
|
371
|
+
assert(pageContextFromRoute.pageId);
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
let hookName;
|
|
375
|
+
let hookFilePath;
|
|
376
|
+
if (pageContext._urlOriginalModifiedByHook) {
|
|
377
|
+
hookName = pageContext._urlOriginalModifiedByHook.hookName;
|
|
378
|
+
hookFilePath = pageContext._urlOriginalModifiedByHook.hookFilePath;
|
|
379
|
+
}
|
|
380
|
+
else if (pageContext._providedByHook) {
|
|
381
|
+
hookName = pageContext._providedByHook.hookName;
|
|
382
|
+
hookFilePath = pageContext._providedByHook.hookFilePath;
|
|
383
|
+
}
|
|
384
|
+
if (hookName) {
|
|
385
|
+
assert(hookFilePath);
|
|
386
|
+
const { urlOriginal } = pageContext;
|
|
387
|
+
assert(urlOriginal);
|
|
388
|
+
assertUsage(false, `The ${hookName}() hook defined by ${hookFilePath} returns a URL ${pc.cyan(urlOriginal)} that ${noRouteMatch}. Make sure that the URLs returned by ${hookName}() always match the route of a page.`);
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
// `prerenderHookFile` is `null` when the URL was deduced by the Filesytem Routing of `.page.js` files. The `onBeforeRoute()` can override Filesystem Routing; it is therefore expected that the deduced URL may not match any page.
|
|
392
|
+
assert(pageContextFromRoute._routingProvidedByOnBeforeRouteHook);
|
|
393
|
+
// Abort since the URL doesn't correspond to any page
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
async function callOnPrerenderStartHook(prerenderContext, globalContext, concurrencyLimit) {
|
|
323
398
|
let onPrerenderStartHook;
|
|
324
399
|
// V1 design
|
|
325
400
|
if (globalContext.pageConfigs.length > 0) {
|
|
@@ -389,8 +464,11 @@ async function callOnPrerenderStartHook(prerenderContext, globalContext) {
|
|
|
389
464
|
pageContext._urlOriginalBeforeHook = pageContext.urlOriginal;
|
|
390
465
|
});
|
|
391
466
|
const docLink = 'https://vike.dev/i18n#pre-rendering';
|
|
392
|
-
|
|
393
|
-
|
|
467
|
+
prerenderContext.pageContexts.forEach((pageContext) => {
|
|
468
|
+
// Preserve URL computed properties when the user is copying pageContext is his onPrerenderStart() hook, e.g. /examples/i18n/
|
|
469
|
+
// https://vike.dev/i18n#pre-rendering
|
|
470
|
+
preservePropertyGetters(pageContext);
|
|
471
|
+
});
|
|
394
472
|
let result = await executeHook(() => {
|
|
395
473
|
const prerenderContextPublic = makePublic(prerenderContext);
|
|
396
474
|
// TODO/v1-release: remove warning
|
|
@@ -405,7 +483,11 @@ async function callOnPrerenderStartHook(prerenderContext, globalContext) {
|
|
|
405
483
|
});
|
|
406
484
|
return hookFn(prerenderContextPublic);
|
|
407
485
|
}, onPrerenderStartHook, null);
|
|
408
|
-
|
|
486
|
+
// Before applying result
|
|
487
|
+
prerenderContext.pageContexts.forEach((pageContext) => {
|
|
488
|
+
;
|
|
489
|
+
pageContext._restorePropertyGetters?.();
|
|
490
|
+
});
|
|
409
491
|
if (result === null || result === undefined) {
|
|
410
492
|
return;
|
|
411
493
|
}
|
|
@@ -436,82 +518,41 @@ async function callOnPrerenderStartHook(prerenderContext, globalContext) {
|
|
|
436
518
|
}
|
|
437
519
|
delete pageContext.url;
|
|
438
520
|
});
|
|
521
|
+
// After applying result
|
|
439
522
|
prerenderContext.pageContexts.forEach((pageContext) => {
|
|
523
|
+
;
|
|
524
|
+
pageContext._restorePropertyGetters?.();
|
|
525
|
+
});
|
|
526
|
+
// Assert URL modified by user
|
|
527
|
+
await Promise.all(prerenderContext.pageContexts.map((pageContext) => concurrencyLimit(async () => {
|
|
440
528
|
if (pageContext.urlOriginal !== pageContext._urlOriginalBeforeHook) {
|
|
441
529
|
pageContext._urlOriginalModifiedByHook = {
|
|
442
530
|
hookFilePath,
|
|
443
531
|
hookName
|
|
444
532
|
};
|
|
533
|
+
const pageContextFromRoute = await route(pageContext,
|
|
534
|
+
// Avoid calling onBeforeRoute() twice, otherwise user's onBeforeRoute() will wrongfully believe URL doesn't have locale when onBeforeRoute() removes the local from the URL
|
|
535
|
+
true);
|
|
536
|
+
assertRouteMatch(pageContextFromRoute, pageContext);
|
|
445
537
|
}
|
|
446
|
-
});
|
|
447
|
-
addPageContextComputedUrl(prerenderContext.pageContexts);
|
|
538
|
+
})));
|
|
448
539
|
}
|
|
449
|
-
async function
|
|
450
|
-
|
|
451
|
-
// Route all URLs
|
|
452
|
-
await Promise.all(prerenderContext.pageContexts.map((pageContext) => concurrencyLimit(async () => {
|
|
453
|
-
const { urlOriginal } = pageContext;
|
|
454
|
-
assert(urlOriginal);
|
|
455
|
-
const pageContextFromRoute = await route(pageContext);
|
|
456
|
-
assert(hasProp(pageContextFromRoute, 'pageId', 'null') || hasProp(pageContextFromRoute, 'pageId', 'string'));
|
|
457
|
-
if (pageContextFromRoute.pageId === null) {
|
|
458
|
-
let hookName;
|
|
459
|
-
let hookFilePath;
|
|
460
|
-
if (pageContext._providedByHook) {
|
|
461
|
-
hookName = pageContext._providedByHook.hookName;
|
|
462
|
-
hookFilePath = pageContext._providedByHook.hookFilePath;
|
|
463
|
-
}
|
|
464
|
-
else if (pageContext._urlOriginalModifiedByHook) {
|
|
465
|
-
hookName = pageContext._urlOriginalModifiedByHook.hookName;
|
|
466
|
-
hookFilePath = pageContext._urlOriginalModifiedByHook.hookFilePath;
|
|
467
|
-
}
|
|
468
|
-
if (hookName) {
|
|
469
|
-
assert(hookFilePath);
|
|
470
|
-
assertUsage(false, `The ${hookName}() hook defined by ${hookFilePath} returns a URL ${pc.cyan(urlOriginal)} that ${noRouteMatch}. Make sure that the URLs returned by ${hookName}() always match the route of a page.`);
|
|
471
|
-
}
|
|
472
|
-
else {
|
|
473
|
-
// `prerenderHookFile` is `null` when the URL was deduced by the Filesytem Routing of `.page.js` files. The `onBeforeRoute()` can override Filesystem Routing; it is therefore expected that the deduced URL may not match any page.
|
|
474
|
-
assert(pageContextFromRoute._routingProvidedByOnBeforeRouteHook);
|
|
475
|
-
// Abort since the URL doesn't correspond to any page
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
assert(pageContextFromRoute.pageId);
|
|
480
|
-
objectAssign(pageContext, pageContextFromRoute);
|
|
481
|
-
const { pageId: pageId } = pageContext;
|
|
482
|
-
objectAssign(pageContext, await loadUserFilesServerSide(pageContext));
|
|
483
|
-
let usesClientRouter;
|
|
484
|
-
{
|
|
485
|
-
if (pageContext._pageConfigs.length > 0) {
|
|
486
|
-
const pageConfig = pageContext._pageConfigs.find((p) => p.pageId === pageId);
|
|
487
|
-
assert(pageConfig);
|
|
488
|
-
usesClientRouter = getConfigValueRuntime(pageConfig, 'clientRouting', 'boolean')?.value ?? false;
|
|
489
|
-
}
|
|
490
|
-
else {
|
|
491
|
-
usesClientRouter = globalContext.usesClientRouter;
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
objectAssign(pageContext, {
|
|
495
|
-
is404: null,
|
|
496
|
-
_httpRequestId: null,
|
|
497
|
-
_usesClientRouter: usesClientRouter
|
|
498
|
-
});
|
|
540
|
+
async function prerenderPages(prerenderContext, concurrencyLimit, onComplete) {
|
|
541
|
+
await Promise.all(prerenderContext.pageContexts.map((pageContextBeforeRender) => concurrencyLimit(async () => {
|
|
499
542
|
let res;
|
|
500
543
|
try {
|
|
501
|
-
res = await prerenderPage(
|
|
544
|
+
res = await prerenderPage(pageContextBeforeRender);
|
|
502
545
|
}
|
|
503
546
|
catch (err) {
|
|
504
|
-
assertIsNotAbort(err, pc.cyan(
|
|
547
|
+
assertIsNotAbort(err, pc.cyan(pageContextBeforeRender.urlOriginal));
|
|
505
548
|
throw err;
|
|
506
549
|
}
|
|
507
|
-
const { documentHtml, pageContextSerialized } = res;
|
|
550
|
+
const { documentHtml, pageContextSerialized, pageContext } = res;
|
|
508
551
|
await onComplete({
|
|
509
|
-
urlOriginal,
|
|
510
552
|
pageContext,
|
|
511
553
|
htmlString: documentHtml,
|
|
512
554
|
pageContextSerialized,
|
|
513
|
-
doNotCreateExtraDirectory: prerenderContext.noExtraDir
|
|
514
|
-
pageId
|
|
555
|
+
doNotCreateExtraDirectory: prerenderContext.noExtraDir
|
|
515
556
|
});
|
|
516
557
|
})));
|
|
517
558
|
}
|
|
@@ -543,31 +584,27 @@ async function warnMissingPages(prerenderedPageContexts, globalContext, doNotPre
|
|
|
543
584
|
assertWarning(partial, `Cannot pre-render page ${pageAt} because it has a non-static route, while no ${hookName}() hook returned any URL matching the page's route. You need to use a ${hookName}() hook (https://vike.dev/${hookName}) providing a list of URLs for ${pageAt} that should be pre-rendered. If you don't want to pre-render ${pageAt} then use the option prerender.partial (https://vike.dev/prerender#partial) to suppress this warning.`, { onlyOnce: true });
|
|
544
585
|
});
|
|
545
586
|
}
|
|
546
|
-
async function
|
|
547
|
-
|
|
587
|
+
async function prerenderPages404(prerenderContext, onComplete, concurrencyLimit) {
|
|
588
|
+
await Promise.all(prerenderContext.pageContexts404.map((pageContextBeforeRender) => concurrencyLimit(async () => {
|
|
548
589
|
let result;
|
|
549
590
|
try {
|
|
550
|
-
result = await
|
|
591
|
+
result = await prerenderPage(pageContextBeforeRender);
|
|
551
592
|
}
|
|
552
593
|
catch (err) {
|
|
553
594
|
assertIsNotAbort(err, 'the 404 page');
|
|
554
595
|
throw err;
|
|
555
596
|
}
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
doNotCreateExtraDirectory: true,
|
|
565
|
-
pageId: null
|
|
566
|
-
});
|
|
567
|
-
}
|
|
568
|
-
}
|
|
597
|
+
const { documentHtml, pageContext } = result;
|
|
598
|
+
await onComplete({
|
|
599
|
+
pageContext,
|
|
600
|
+
htmlString: documentHtml,
|
|
601
|
+
pageContextSerialized: null,
|
|
602
|
+
doNotCreateExtraDirectory: true
|
|
603
|
+
});
|
|
604
|
+
})));
|
|
569
605
|
}
|
|
570
|
-
async function writeFiles({
|
|
606
|
+
async function writeFiles({ pageContext, htmlString, pageContextSerialized, doNotCreateExtraDirectory }, root, outDirClient, onPagePrerender, output, logLevel) {
|
|
607
|
+
const { urlOriginal } = pageContext;
|
|
571
608
|
assert(urlOriginal.startsWith('/'));
|
|
572
609
|
const writeJobs = [
|
|
573
610
|
write(urlOriginal, pageContext, 'HTML', htmlString, root, outDirClient, doNotCreateExtraDirectory, onPagePrerender, output, logLevel)
|
|
@@ -712,26 +749,6 @@ function assertIsNotAbort(err, urlOr404) {
|
|
|
712
749
|
assert(abortCall);
|
|
713
750
|
assertUsage(false, `${pc.cyan(abortCall)} thrown${thrownBy} while pre-rendering ${urlOr404} but ${pc.cyan(abortCaller)} isn't supported for pre-rendered pages`);
|
|
714
751
|
}
|
|
715
|
-
function makePageContextComputedUrlNonEnumerable(pageContexts) {
|
|
716
|
-
change(false);
|
|
717
|
-
return { restoreEnumerable, addPageContextComputedUrl };
|
|
718
|
-
function restoreEnumerable() {
|
|
719
|
-
change(true);
|
|
720
|
-
}
|
|
721
|
-
function addPageContextComputedUrl(pageContexts) {
|
|
722
|
-
// Add URL computed props to the user-generated pageContext copies
|
|
723
|
-
pageContexts.forEach((pageContext) => {
|
|
724
|
-
const pageContextUrlComputed = getPageContextUrlComputed(pageContext);
|
|
725
|
-
objectAssign(pageContext, pageContextUrlComputed);
|
|
726
|
-
});
|
|
727
|
-
}
|
|
728
|
-
function change(enumerable) {
|
|
729
|
-
pageContexts.forEach((pageContext) => {
|
|
730
|
-
changeEnumerable(pageContext, 'urlPathname', enumerable);
|
|
731
|
-
changeEnumerable(pageContext, 'urlParsed', enumerable);
|
|
732
|
-
});
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
752
|
function validatePrerenderConfig(
|
|
736
753
|
// Guaranteed by configDef.type to be either an object or boolean
|
|
737
754
|
prerenderConfig) {
|
|
@@ -770,7 +787,8 @@ prerenderConfig) {
|
|
|
770
787
|
function makePublic(prerenderContext) {
|
|
771
788
|
const prerenderContextPublic = makePublicCopy(prerenderContext, 'prerenderContext', [
|
|
772
789
|
'output', // vite-plugin-vercel
|
|
773
|
-
'pageContexts' // https://vike.dev/i18n#pre-rendering
|
|
790
|
+
'pageContexts', // https://vike.dev/i18n#pre-rendering
|
|
791
|
+
'pageContexts404' // https://vike.dev/i18n#pre-rendering
|
|
774
792
|
]);
|
|
775
793
|
return prerenderContextPublic;
|
|
776
794
|
}
|
|
@@ -13,6 +13,6 @@ export * from '../../utils/pLimit.js';
|
|
|
13
13
|
export * from '../../utils/isFilePathAbsoluteFilesystem.js';
|
|
14
14
|
export * from '../../utils/isArray.js';
|
|
15
15
|
export * from '../../utils/isObject.js';
|
|
16
|
-
export * from '../../utils/changeEnumerable.js';
|
|
17
16
|
export * from '../../utils/makePublicCopy.js';
|
|
18
17
|
export * from '../../utils/isNullish.js';
|
|
18
|
+
export * from '../../utils/preservePropertyGetters.js';
|
|
@@ -15,6 +15,6 @@ export * from '../../utils/pLimit.js';
|
|
|
15
15
|
export * from '../../utils/isFilePathAbsoluteFilesystem.js';
|
|
16
16
|
export * from '../../utils/isArray.js';
|
|
17
17
|
export * from '../../utils/isObject.js';
|
|
18
|
-
export * from '../../utils/changeEnumerable.js';
|
|
19
18
|
export * from '../../utils/makePublicCopy.js';
|
|
20
19
|
export * from '../../utils/isNullish.js';
|
|
20
|
+
export * from '../../utils/preservePropertyGetters.js';
|