vike 0.4.227 → 0.4.228-commit-1553dee

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.
Files changed (91) hide show
  1. package/dist/cjs/node/api/dev.js +2 -0
  2. package/dist/cjs/node/plugin/plugins/build/handleAssetsManifest.js +9 -4
  3. package/dist/cjs/node/plugin/plugins/build/pluginBuildConfig.js +3 -5
  4. package/dist/cjs/node/plugin/plugins/build/pluginBuildEntry.js +13 -8
  5. package/dist/cjs/node/plugin/plugins/build/pluginModuleBanner.js +13 -21
  6. package/dist/cjs/node/plugin/plugins/devConfig/determineFsAllowList.js +8 -9
  7. package/dist/cjs/node/plugin/plugins/envVars.js +22 -13
  8. package/dist/cjs/node/plugin/plugins/extractAssetsPlugin.js +1 -2
  9. package/dist/cjs/node/plugin/plugins/extractExportNamesPlugin.js +1 -2
  10. package/dist/cjs/node/plugin/plugins/fileEnv.js +1 -2
  11. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolvePointerImport.js +1 -3
  12. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +25 -19
  13. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +7 -4
  14. package/dist/cjs/node/plugin/plugins/setGlobalContext.js +3 -4
  15. package/dist/cjs/node/plugin/shared/getViteConfigRuntime.js +21 -0
  16. package/dist/cjs/node/plugin/shared/resolveClientEntriesDev.js +11 -12
  17. package/dist/cjs/node/plugin/utils.js +1 -0
  18. package/dist/cjs/node/prerender/resolvePrerenderConfig.js +1 -1
  19. package/dist/cjs/node/prerender/runPrerender.js +157 -196
  20. package/dist/cjs/node/prerender/utils.js +1 -1
  21. package/dist/cjs/node/runtime/globalContext.js +57 -34
  22. package/dist/cjs/node/runtime/html/stream.js +2 -4
  23. package/dist/cjs/node/runtime/index-common.js +2 -1
  24. package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +0 -23
  25. package/dist/cjs/node/runtime-dev/createDevMiddleware.js +1 -1
  26. package/dist/cjs/shared/route/executeOnBeforeRouteHook.js +1 -1
  27. package/dist/cjs/shared/route/index.js +13 -11
  28. package/dist/cjs/utils/PROJECT_VERSION.js +1 -1
  29. package/dist/cjs/utils/assert.js +2 -5
  30. package/dist/cjs/utils/findPackageJson.js +2 -2
  31. package/dist/cjs/utils/isFilePathAbsoluteFilesystem.js +1 -1
  32. package/dist/cjs/utils/isNpmPackage.js +1 -1
  33. package/dist/cjs/utils/isScriptFile.js +4 -4
  34. package/dist/cjs/utils/parseUrl.js +4 -4
  35. package/dist/cjs/utils/preservePropertyGetters.js +30 -0
  36. package/dist/cjs/utils/requireResolve.js +60 -16
  37. package/dist/cjs/{node/plugin/shared → utils}/rollupSourceMap.js +4 -4
  38. package/dist/esm/client/client-routing-runtime/initOnLinkClick.js +2 -2
  39. package/dist/esm/node/api/dev.js +2 -0
  40. package/dist/esm/node/plugin/plugins/build/handleAssetsManifest.js +9 -4
  41. package/dist/esm/node/plugin/plugins/build/pluginBuildConfig.js +2 -4
  42. package/dist/esm/node/plugin/plugins/build/pluginBuildEntry.d.ts +1 -1
  43. package/dist/esm/node/plugin/plugins/build/pluginBuildEntry.js +12 -7
  44. package/dist/esm/node/plugin/plugins/build/pluginModuleBanner.js +11 -22
  45. package/dist/esm/node/plugin/plugins/devConfig/determineFsAllowList.js +7 -8
  46. package/dist/esm/node/plugin/plugins/envVars.js +19 -13
  47. package/dist/esm/node/plugin/plugins/extractAssetsPlugin.js +2 -3
  48. package/dist/esm/node/plugin/plugins/extractExportNamesPlugin.js +2 -3
  49. package/dist/esm/node/plugin/plugins/fileEnv.js +2 -3
  50. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/resolvePointerImport.js +2 -4
  51. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/transpileAndExecuteFile.js +26 -20
  52. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +7 -4
  53. package/dist/esm/node/plugin/plugins/setGlobalContext.js +4 -5
  54. package/dist/esm/node/plugin/shared/getViteConfigRuntime.d.ts +14 -0
  55. package/dist/esm/node/plugin/shared/getViteConfigRuntime.js +19 -0
  56. package/dist/esm/node/plugin/shared/resolveClientEntriesDev.js +10 -11
  57. package/dist/esm/node/plugin/utils.d.ts +1 -0
  58. package/dist/esm/node/plugin/utils.js +1 -0
  59. package/dist/esm/node/prerender/resolvePrerenderConfig.d.ts +1 -1
  60. package/dist/esm/node/prerender/resolvePrerenderConfig.js +1 -1
  61. package/dist/esm/node/prerender/runPrerender.d.ts +1 -0
  62. package/dist/esm/node/prerender/runPrerender.js +160 -199
  63. package/dist/esm/node/prerender/utils.d.ts +1 -1
  64. package/dist/esm/node/prerender/utils.js +1 -1
  65. package/dist/esm/node/runtime/globalContext.d.ts +26 -17
  66. package/dist/esm/node/runtime/globalContext.js +57 -34
  67. package/dist/esm/node/runtime/html/stream.js +2 -4
  68. package/dist/esm/node/runtime/index-common.d.ts +1 -1
  69. package/dist/esm/node/runtime/index-common.js +1 -1
  70. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.d.ts +9 -197
  71. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +0 -23
  72. package/dist/esm/node/runtime-dev/createDevMiddleware.js +1 -1
  73. package/dist/esm/shared/page-configs/getConfigDefinedAt.d.ts +1 -1
  74. package/dist/esm/shared/route/executeOnBeforeRouteHook.js +1 -1
  75. package/dist/esm/shared/route/index.d.ts +1 -1
  76. package/dist/esm/shared/route/index.js +13 -11
  77. package/dist/esm/shared/types.d.ts +1 -3
  78. package/dist/esm/utils/PROJECT_VERSION.d.ts +1 -1
  79. package/dist/esm/utils/PROJECT_VERSION.js +1 -1
  80. package/dist/esm/utils/assert.js +2 -5
  81. package/dist/esm/utils/isFilePathAbsoluteFilesystem.js +1 -1
  82. package/dist/esm/utils/isNpmPackage.js +1 -1
  83. package/dist/esm/utils/isScriptFile.js +4 -4
  84. package/dist/esm/utils/parseUrl.js +4 -4
  85. package/dist/esm/utils/preservePropertyGetters.d.ts +2 -0
  86. package/dist/esm/utils/preservePropertyGetters.js +28 -0
  87. package/dist/esm/utils/requireResolve.d.ts +7 -1
  88. package/dist/esm/utils/requireResolve.js +54 -13
  89. package/dist/esm/{node/plugin/shared → utils}/rollupSourceMap.d.ts +4 -4
  90. package/dist/esm/{node/plugin/shared → utils}/rollupSourceMap.js +4 -4
  91. package/package.json +3 -2
@@ -54,7 +54,6 @@ const resolveRouteString_js_1 = require("../../shared/route/resolveRouteString.j
54
54
  const getConfigValueRuntime_js_1 = require("../../shared/page-configs/getConfigValueRuntime.js");
55
55
  const loadConfigValues_js_1 = require("../../shared/page-configs/loadConfigValues.js");
56
56
  const error_page_js_1 = require("../../shared/error-page.js");
57
- const getPageContextUrlComputed_js_1 = require("../../shared/getPageContextUrlComputed.js");
58
57
  const abort_js_1 = require("../../shared/route/abort.js");
59
58
  const loadUserFilesServerSide_js_1 = require("../runtime/renderPage/loadUserFilesServerSide.js");
60
59
  const getHook_js_1 = require("../../shared/hooks/getHook.js");
@@ -116,23 +115,26 @@ async function runPrerender(options = {}, standaloneTrigger) {
116
115
  const viteConfig = await (0, vite_1.resolveConfig)(options.viteConfig || {}, 'build', 'production');
117
116
  const vikeConfig = await (0, getVikeConfig_js_1.getVikeConfig)(viteConfig);
118
117
  const vike = (0, commonConfig_js_1.getVikeConfigPublic)(viteConfig);
119
- (0, utils_js_1.assert)(vike.prerenderContext.isPrerenderingEnabled);
120
118
  const { outDirClient, outDirServer } = (0, getOutDirs_js_1.getOutDirs)(viteConfig);
121
119
  const { root } = viteConfig;
122
120
  const prerenderConfigGlobal = (0, resolvePrerenderConfig_js_1.resolvePrerenderConfigGlobal)(vikeConfig);
123
- validatePrerenderConfig(prerenderConfigGlobal);
124
121
  const { partial, noExtraDir, parallel, defaultLocalValue, isPrerenderingEnabled } = prerenderConfigGlobal;
125
122
  if (!isPrerenderingEnabled) {
126
123
  (0, utils_js_1.assert)(standaloneTrigger);
127
- // TODO/now: make it assertUsage() and remove dist/server/entry.mjs if pre-rendering is completely disabled
128
- (0, utils_js_1.assertWarning)(false, `You're executing ${picocolors_1.default.cyan(standaloneTrigger)} but you didn't enable pre-rendering. Use the ${picocolors_1.default.cyan('prerender')} setting (${picocolors_1.default.underline('https://vike.dev/prerender')}) to enable pre-rendering for at least one page.`, { onlyOnce: true });
124
+ /* TODO/soon: use this again a little while after https://github.com/magne4000/vite-plugin-vercel/pull/156 is merged.
125
+ assertUsage(
126
+ false,
127
+ `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.`
128
+ )
129
+ */
130
+ return { viteConfig };
129
131
  }
130
132
  const concurrencyLimit = (0, utils_js_1.pLimit)(parallel === false || parallel === 0 ? 1 : parallel === true || parallel === undefined ? (0, os_1.cpus)().length : parallel);
131
133
  await (0, globalContext_js_1.initGlobalContext_runPrerender)();
132
134
  const globalContext = await (0, globalContext_js_1.getGlobalContextInternal)();
133
135
  globalContext.pageFilesAll.forEach(assertExportNames);
134
136
  const prerenderContext = {
135
- noExtraDir: noExtraDir ?? false,
137
+ noExtraDir,
136
138
  pageContexts: [],
137
139
  pageContextInit: options.pageContextInit ?? null,
138
140
  prerenderedPageContexts: {},
@@ -140,21 +142,29 @@ async function runPrerender(options = {}, standaloneTrigger) {
140
142
  };
141
143
  const doNotPrerenderList = [];
142
144
  await collectDoNoPrerenderList(vikeConfig.pageConfigs, doNotPrerenderList, defaultLocalValue, concurrencyLimit, globalContext);
145
+ // Allow user to create `pageContext` for parameterized routes and/or bulk data fetching
146
+ // https://vike.dev/onBeforePrerenderStart
143
147
  await callOnBeforePrerenderStartHooks(prerenderContext, globalContext, concurrencyLimit, doNotPrerenderList);
144
- await handlePagesWithStaticRoutes(prerenderContext, globalContext, doNotPrerenderList, concurrencyLimit);
145
- await callOnPrerenderStartHook(prerenderContext, globalContext);
148
+ // Create `pageContext` for each page with a static route
149
+ const urlList = getUrlListFromPagesWithStaticRoute(globalContext, doNotPrerenderList);
150
+ await createPageContextsForOnPrerenderStartHook(urlList, prerenderContext, globalContext, concurrencyLimit, false);
151
+ // Create `pageContext` for 404 page
152
+ const urlList404 = getUrlList404(globalContext);
153
+ await createPageContextsForOnPrerenderStartHook(urlList404, prerenderContext, globalContext, concurrencyLimit, true);
154
+ // Allow user to duplicate the list of `pageContext` for i18n
155
+ // https://vike.dev/onPrerenderStart
156
+ await callOnPrerenderStartHook(prerenderContext, globalContext, concurrencyLimit);
146
157
  let prerenderedCount = 0;
147
158
  // Write files as soon as pages finish rendering (instead of writing all files at once only after all pages have rendered).
148
159
  const onComplete = async (htmlFile) => {
149
160
  prerenderedCount++;
150
- if (htmlFile.pageId) {
151
- prerenderContext.prerenderedPageContexts[htmlFile.pageId] = htmlFile.pageContext;
152
- }
161
+ const { pageId } = htmlFile.pageContext;
162
+ (0, utils_js_1.assert)(pageId);
163
+ prerenderContext.prerenderedPageContexts[pageId] = htmlFile.pageContext;
153
164
  await writeFiles(htmlFile, root, outDirClient, options.onPagePrerender, prerenderContext.output, logLevel);
154
165
  };
155
- await routeAndPrerender(prerenderContext, globalContext, concurrencyLimit, onComplete);
166
+ await prerenderPages(prerenderContext, concurrencyLimit, onComplete);
156
167
  warnContradictoryNoPrerenderList(prerenderContext.prerenderedPageContexts, doNotPrerenderList);
157
- await prerender404(prerenderContext, globalContext, onComplete);
158
168
  if (logLevel === 'info') {
159
169
  console.log(`${picocolors_1.default.green(`✓`)} ${prerenderedCount} HTML documents pre-rendered.`);
160
170
  }
@@ -266,12 +276,13 @@ async function callOnBeforePrerenderStartHooks(prerenderContext, globalContext,
266
276
  });
267
277
  })));
268
278
  await Promise.all(onBeforePrerenderStartHooks.map(({ hookFn, hookName, hookFilePath, pageId, hookTimeout }) => concurrencyLimit(async () => {
269
- if (doNotPrerenderList.find((p) => p.pageId === pageId)) {
279
+ if (doNotPrerenderList.find((p) => p.pageId === pageId))
270
280
  return;
271
- }
272
281
  const prerenderResult = await (0, executeHook_js_1.executeHook)(() => hookFn(), { hookName, hookFilePath, hookTimeout }, null);
273
282
  const result = normalizeOnPrerenderHookResult(prerenderResult, hookFilePath, hookName);
283
+ // Handle result
274
284
  await Promise.all(result.map(async ({ url, pageContext }) => {
285
+ // Assert no duplication
275
286
  {
276
287
  const pageContextFound = prerenderContext.pageContexts.find((pageContext) => isSameUrl(pageContext.urlOriginal, url));
277
288
  if (pageContextFound) {
@@ -282,30 +293,23 @@ async function callOnBeforePrerenderStartHooks(prerenderContext, globalContext,
282
293
  (0, utils_js_1.assertUsage)(false, `URL ${picocolors_1.default.cyan(url)} provided ${providedTwice}. Make sure to provide the URL only once instead.`);
283
294
  }
284
295
  }
285
- const pageContextNew = await createPageContext(url, prerenderContext, globalContext);
286
- (0, utils_js_1.objectAssign)(pageContextNew, {
287
- _providedByHook: {
288
- hookFilePath,
289
- hookName
290
- }
291
- });
296
+ // Add result
297
+ const providedByHook = { hookFilePath, hookName };
298
+ const pageContextNew = await createPageContext(url, prerenderContext, globalContext, false, undefined, providedByHook);
292
299
  prerenderContext.pageContexts.push(pageContextNew);
293
300
  if (pageContext) {
294
- (0, utils_js_1.objectAssign)(pageContextNew, {
295
- _pageContextAlreadyProvidedByOnPrerenderHook: true
296
- });
301
+ (0, utils_js_1.objectAssign)(pageContextNew, { _pageContextAlreadyProvidedByOnPrerenderHook: true });
297
302
  (0, utils_js_1.objectAssign)(pageContextNew, pageContext);
298
303
  }
299
304
  }));
300
305
  })));
301
306
  }
302
- async function handlePagesWithStaticRoutes(prerenderContext, globalContext, doNotPrerenderList, concurrencyLimit) {
303
- // Pre-render pages with a static route
304
- await Promise.all(globalContext.pageRoutes.map((pageRoute) => concurrencyLimit(async () => {
307
+ function getUrlListFromPagesWithStaticRoute(globalContext, doNotPrerenderList) {
308
+ const urlList = [];
309
+ globalContext.pageRoutes.map((pageRoute) => {
305
310
  const { pageId } = pageRoute;
306
- if (doNotPrerenderList.find((p) => p.pageId === pageId)) {
311
+ if (doNotPrerenderList.find((p) => p.pageId === pageId))
307
312
  return;
308
- }
309
313
  let urlOriginal;
310
314
  if (!('routeString' in pageRoute)) {
311
315
  // Abort since the page's route is a Route Function
@@ -321,43 +325,111 @@ async function handlePagesWithStaticRoutes(prerenderContext, globalContext, doNo
321
325
  urlOriginal = url;
322
326
  }
323
327
  (0, utils_js_1.assert)(urlOriginal.startsWith('/'));
328
+ urlList.push({ urlOriginal, pageId });
329
+ });
330
+ return urlList;
331
+ }
332
+ function getUrlList404(globalContext) {
333
+ const urlList = [];
334
+ const errorPageId = (0, error_page_js_1.getErrorPageId)(globalContext.pageFilesAll, globalContext.pageConfigs);
335
+ if (errorPageId) {
336
+ urlList.push({
337
+ // A URL is required for `viteDevServer.transformIndexHtml(url,html)`
338
+ urlOriginal: '/404',
339
+ pageId: errorPageId
340
+ });
341
+ }
342
+ return urlList;
343
+ }
344
+ async function createPageContextsForOnPrerenderStartHook(urlList, prerenderContext, globalContext, concurrencyLimit, is404) {
345
+ await Promise.all(urlList.map(({ urlOriginal, pageId }) => concurrencyLimit(async () => {
324
346
  // Already included in a onBeforePrerenderStart() hook
325
347
  if (prerenderContext.pageContexts.find((pageContext) => isSameUrl(pageContext.urlOriginal, urlOriginal))) {
326
348
  return;
327
349
  }
328
- const routeParams = {};
329
- const pageContext = await createPageContext(urlOriginal, prerenderContext, globalContext);
330
- (0, utils_js_1.objectAssign)(pageContext, {
331
- _providedByHook: null,
332
- routeParams,
333
- pageId: pageId,
334
- _debugRouteMatches: [
335
- {
336
- pageId,
337
- routeType: pageRoute.routeType,
338
- routeString: urlOriginal,
339
- routeParams
340
- }
341
- ]
342
- });
343
- (0, utils_js_1.objectAssign)(pageContext, await (0, loadUserFilesServerSide_js_1.loadUserFilesServerSide)(pageContext));
350
+ const pageContext = await createPageContext(urlOriginal, prerenderContext, globalContext, is404, pageId, null);
344
351
  prerenderContext.pageContexts.push(pageContext);
345
352
  })));
346
353
  }
347
- async function createPageContext(urlOriginal, prerenderContext, globalContext) {
348
- const pageContextInit = { urlOriginal };
349
- (0, utils_js_1.objectAssign)(pageContextInit, prerenderContext.pageContextInit);
350
- const pageContext = await (0, renderPageAlreadyRouted_js_1.getPageContextInitEnhanced)(pageContextInit, globalContext, true, {});
354
+ async function createPageContext(urlOriginal, prerenderContext, globalContext, is404, pageId, providedByHook) {
355
+ const pageContextInit = {
356
+ urlOriginal,
357
+ ...prerenderContext.pageContextInit
358
+ };
359
+ const pageContext = await (0, renderPageAlreadyRouted_js_1.getPageContextInitEnhanced)(pageContextInit, globalContext, true);
351
360
  (0, utils_js_1.assert)(pageContext.isPrerendering === true);
352
361
  (0, utils_js_1.objectAssign)(pageContext, {
353
362
  _urlHandler: null,
363
+ _httpRequestId: null,
354
364
  _urlRewrite: null,
355
365
  _noExtraDir: prerenderContext.noExtraDir,
356
- _prerenderContext: prerenderContext
366
+ _prerenderContext: prerenderContext,
367
+ _providedByHook: providedByHook,
368
+ _urlOriginalModifiedByHook: null,
369
+ is404
357
370
  });
371
+ if (!is404) {
372
+ const pageContextFromRoute = await (0, index_js_1.route)(pageContext);
373
+ (0, utils_js_1.assert)((0, utils_js_1.hasProp)(pageContextFromRoute, 'pageId', 'null') || (0, utils_js_1.hasProp)(pageContextFromRoute, 'pageId', 'string')); // Help TS
374
+ assertRouteMatch(pageContextFromRoute, pageContext);
375
+ (0, utils_js_1.assert)(pageContextFromRoute.pageId);
376
+ (0, utils_js_1.objectAssign)(pageContext, pageContextFromRoute);
377
+ }
378
+ else {
379
+ (0, utils_js_1.assert)(pageId);
380
+ (0, utils_js_1.objectAssign)(pageContext, {
381
+ pageId,
382
+ _debugRouteMatches: [],
383
+ routeParams: {}
384
+ });
385
+ }
386
+ (0, utils_js_1.objectAssign)(pageContext, await (0, loadUserFilesServerSide_js_1.loadUserFilesServerSide)(pageContext));
387
+ let usesClientRouter;
388
+ {
389
+ const { pageId } = pageContext;
390
+ (0, utils_js_1.assert)(pageId);
391
+ (0, utils_js_1.assert)(globalContext.isPrerendering);
392
+ if (globalContext.pageConfigs.length > 0) {
393
+ const pageConfig = globalContext.pageConfigs.find((p) => p.pageId === pageId);
394
+ (0, utils_js_1.assert)(pageConfig);
395
+ usesClientRouter = (0, getConfigValueRuntime_js_1.getConfigValueRuntime)(pageConfig, 'clientRouting', 'boolean')?.value ?? false;
396
+ }
397
+ else {
398
+ usesClientRouter = globalContext.usesClientRouter;
399
+ }
400
+ }
401
+ (0, utils_js_1.objectAssign)(pageContext, { _usesClientRouter: usesClientRouter });
358
402
  return pageContext;
359
403
  }
360
- async function callOnPrerenderStartHook(prerenderContext, globalContext) {
404
+ function assertRouteMatch(pageContextFromRoute, pageContext) {
405
+ if (pageContextFromRoute.pageId !== null) {
406
+ (0, utils_js_1.assert)(pageContextFromRoute.pageId);
407
+ return;
408
+ }
409
+ let hookName;
410
+ let hookFilePath;
411
+ if (pageContext._urlOriginalModifiedByHook) {
412
+ hookName = pageContext._urlOriginalModifiedByHook.hookName;
413
+ hookFilePath = pageContext._urlOriginalModifiedByHook.hookFilePath;
414
+ }
415
+ else if (pageContext._providedByHook) {
416
+ hookName = pageContext._providedByHook.hookName;
417
+ hookFilePath = pageContext._providedByHook.hookFilePath;
418
+ }
419
+ if (hookName) {
420
+ (0, utils_js_1.assert)(hookFilePath);
421
+ const { urlOriginal } = pageContext;
422
+ (0, utils_js_1.assert)(urlOriginal);
423
+ (0, utils_js_1.assertUsage)(false, `The ${hookName}() hook defined by ${hookFilePath} returns a URL ${picocolors_1.default.cyan(urlOriginal)} that ${noRouteMatch_js_1.noRouteMatch}. Make sure that the URLs returned by ${hookName}() always match the route of a page.`);
424
+ }
425
+ else {
426
+ // `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.
427
+ (0, utils_js_1.assert)(pageContextFromRoute._routingProvidedByOnBeforeRouteHook);
428
+ // Abort since the URL doesn't correspond to any page
429
+ return;
430
+ }
431
+ }
432
+ async function callOnPrerenderStartHook(prerenderContext, globalContext, concurrencyLimit) {
361
433
  let onPrerenderStartHook;
362
434
  // V1 design
363
435
  if (globalContext.pageConfigs.length > 0) {
@@ -427,8 +499,11 @@ async function callOnPrerenderStartHook(prerenderContext, globalContext) {
427
499
  pageContext._urlOriginalBeforeHook = pageContext.urlOriginal;
428
500
  });
429
501
  const docLink = 'https://vike.dev/i18n#pre-rendering';
430
- // Set `enumerable` to `false` to avoid computed URL properties from being iterated & copied in onPrerenderStart() hook, e.g. /examples/i18n/
431
- const { restoreEnumerable, addPageContextComputedUrl } = makePageContextComputedUrlNonEnumerable(prerenderContext.pageContexts);
502
+ prerenderContext.pageContexts.forEach((pageContext) => {
503
+ // Preserve URL computed properties when the user is copying pageContext is his onPrerenderStart() hook, e.g. /examples/i18n/
504
+ // https://vike.dev/i18n#pre-rendering
505
+ (0, utils_js_1.preservePropertyGetters)(pageContext);
506
+ });
432
507
  let result = await (0, executeHook_js_1.executeHook)(() => {
433
508
  const prerenderContextPublic = makePublic(prerenderContext);
434
509
  // TODO/v1-release: remove warning
@@ -443,7 +518,11 @@ async function callOnPrerenderStartHook(prerenderContext, globalContext) {
443
518
  });
444
519
  return hookFn(prerenderContextPublic);
445
520
  }, onPrerenderStartHook, null);
446
- restoreEnumerable();
521
+ // Before applying result
522
+ prerenderContext.pageContexts.forEach((pageContext) => {
523
+ ;
524
+ pageContext._restorePropertyGetters?.();
525
+ });
447
526
  if (result === null || result === undefined) {
448
527
  return;
449
528
  }
@@ -474,82 +553,42 @@ async function callOnPrerenderStartHook(prerenderContext, globalContext) {
474
553
  }
475
554
  delete pageContext.url;
476
555
  });
556
+ // After applying result
477
557
  prerenderContext.pageContexts.forEach((pageContext) => {
478
- if (pageContext.urlOriginal !== pageContext._urlOriginalBeforeHook) {
558
+ ;
559
+ pageContext._restorePropertyGetters?.();
560
+ });
561
+ // Assert URL modified by user
562
+ await Promise.all(prerenderContext.pageContexts.map((pageContext) => concurrencyLimit(async () => {
563
+ if (pageContext.urlOriginal !== pageContext._urlOriginalBeforeHook && !pageContext.is404) {
479
564
  pageContext._urlOriginalModifiedByHook = {
480
565
  hookFilePath,
481
566
  hookName
482
567
  };
568
+ const pageContextFromRoute = await (0, index_js_1.route)(pageContext,
569
+ // Avoid calling onBeforeRoute() twice, otherwise onBeforeRoute() will wrongfully believe URL doesn't have locale after onBeforeRoute() already removed the local from the URL when called the first time.
570
+ true);
571
+ assertRouteMatch(pageContextFromRoute, pageContext);
483
572
  }
484
- });
485
- addPageContextComputedUrl(prerenderContext.pageContexts);
573
+ })));
486
574
  }
487
- async function routeAndPrerender(prerenderContext, globalContext, concurrencyLimit, onComplete) {
488
- (0, utils_js_1.assert)(globalContext.isPrerendering);
489
- // Route all URLs
490
- await Promise.all(prerenderContext.pageContexts.map((pageContext) => concurrencyLimit(async () => {
491
- const { urlOriginal } = pageContext;
492
- (0, utils_js_1.assert)(urlOriginal);
493
- const pageContextFromRoute = await (0, index_js_1.route)(pageContext);
494
- (0, utils_js_1.assert)((0, utils_js_1.hasProp)(pageContextFromRoute, 'pageId', 'null') || (0, utils_js_1.hasProp)(pageContextFromRoute, 'pageId', 'string'));
495
- if (pageContextFromRoute.pageId === null) {
496
- let hookName;
497
- let hookFilePath;
498
- if (pageContext._providedByHook) {
499
- hookName = pageContext._providedByHook.hookName;
500
- hookFilePath = pageContext._providedByHook.hookFilePath;
501
- }
502
- else if (pageContext._urlOriginalModifiedByHook) {
503
- hookName = pageContext._urlOriginalModifiedByHook.hookName;
504
- hookFilePath = pageContext._urlOriginalModifiedByHook.hookFilePath;
505
- }
506
- if (hookName) {
507
- (0, utils_js_1.assert)(hookFilePath);
508
- (0, utils_js_1.assertUsage)(false, `The ${hookName}() hook defined by ${hookFilePath} returns a URL ${picocolors_1.default.cyan(urlOriginal)} that ${noRouteMatch_js_1.noRouteMatch}. Make sure that the URLs returned by ${hookName}() always match the route of a page.`);
509
- }
510
- else {
511
- // `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.
512
- (0, utils_js_1.assert)(pageContextFromRoute._routingProvidedByOnBeforeRouteHook);
513
- // Abort since the URL doesn't correspond to any page
514
- return;
515
- }
516
- }
517
- (0, utils_js_1.assert)(pageContextFromRoute.pageId);
518
- (0, utils_js_1.objectAssign)(pageContext, pageContextFromRoute);
519
- const { pageId: pageId } = pageContext;
520
- (0, utils_js_1.objectAssign)(pageContext, await (0, loadUserFilesServerSide_js_1.loadUserFilesServerSide)(pageContext));
521
- let usesClientRouter;
522
- {
523
- if (pageContext._pageConfigs.length > 0) {
524
- const pageConfig = pageContext._pageConfigs.find((p) => p.pageId === pageId);
525
- (0, utils_js_1.assert)(pageConfig);
526
- usesClientRouter = (0, getConfigValueRuntime_js_1.getConfigValueRuntime)(pageConfig, 'clientRouting', 'boolean')?.value ?? false;
527
- }
528
- else {
529
- usesClientRouter = globalContext.usesClientRouter;
530
- }
531
- }
532
- (0, utils_js_1.objectAssign)(pageContext, {
533
- is404: null,
534
- _httpRequestId: null,
535
- _usesClientRouter: usesClientRouter
536
- });
575
+ async function prerenderPages(prerenderContext, concurrencyLimit, onComplete) {
576
+ await Promise.all(prerenderContext.pageContexts.map((pageContextBeforeRender) => concurrencyLimit(async () => {
537
577
  let res;
538
578
  try {
539
- res = await (0, renderPageAlreadyRouted_js_1.prerenderPage)(pageContext);
579
+ res = await (0, renderPageAlreadyRouted_js_1.prerenderPage)(pageContextBeforeRender);
540
580
  }
541
581
  catch (err) {
542
- assertIsNotAbort(err, picocolors_1.default.cyan(pageContext.urlOriginal));
582
+ assertIsNotAbort(err, picocolors_1.default.cyan(pageContextBeforeRender.urlOriginal));
543
583
  throw err;
544
584
  }
545
- const { documentHtml, pageContextSerialized } = res;
585
+ const { documentHtml, pageContext } = res;
586
+ const pageContextSerialized = pageContext.is404 ? null : res.pageContextSerialized;
546
587
  await onComplete({
547
- urlOriginal,
548
588
  pageContext,
549
589
  htmlString: documentHtml,
550
590
  pageContextSerialized,
551
- doNotCreateExtraDirectory: prerenderContext.noExtraDir,
552
- pageId
591
+ doNotCreateExtraDirectory: prerenderContext.noExtraDir ?? pageContext.is404
553
592
  });
554
593
  })));
555
594
  }
@@ -581,31 +620,8 @@ async function warnMissingPages(prerenderedPageContexts, globalContext, doNotPre
581
620
  (0, utils_js_1.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 });
582
621
  });
583
622
  }
584
- async function prerender404(prerenderContext, globalContext, onComplete) {
585
- if (!Object.values(prerenderContext.prerenderedPageContexts).find(({ urlOriginal }) => urlOriginal === '/404')) {
586
- let result;
587
- try {
588
- result = await (0, renderPageAlreadyRouted_js_1.prerender404Page)(prerenderContext.pageContextInit, globalContext);
589
- }
590
- catch (err) {
591
- assertIsNotAbort(err, 'the 404 page');
592
- throw err;
593
- }
594
- if (result) {
595
- const urlOriginal = '/404';
596
- const { documentHtml, pageContext } = result;
597
- await onComplete({
598
- urlOriginal,
599
- pageContext,
600
- htmlString: documentHtml,
601
- pageContextSerialized: null,
602
- doNotCreateExtraDirectory: true,
603
- pageId: null
604
- });
605
- }
606
- }
607
- }
608
- async function writeFiles({ urlOriginal, pageContext, htmlString, pageContextSerialized, doNotCreateExtraDirectory }, root, outDirClient, onPagePrerender, output, logLevel) {
623
+ async function writeFiles({ pageContext, htmlString, pageContextSerialized, doNotCreateExtraDirectory }, root, outDirClient, onPagePrerender, output, logLevel) {
624
+ const { urlOriginal } = pageContext;
609
625
  (0, utils_js_1.assert)(urlOriginal.startsWith('/'));
610
626
  const writeJobs = [
611
627
  write(urlOriginal, pageContext, 'HTML', htmlString, root, outDirClient, doNotCreateExtraDirectory, onPagePrerender, output, logLevel)
@@ -737,7 +753,7 @@ function runPrerender_forceExit() {
737
753
  assertInfo(false, "Pre-rendering was forced exit. (Didn't gracefully exit because the event queue isn't empty. This is usally fine, see ...", { onlyOnce: false })
738
754
  */
739
755
  }
740
- function assertIsNotAbort(err, urlOr404) {
756
+ function assertIsNotAbort(err, urlOriginal) {
741
757
  if (!(0, abort_js_1.isAbortError)(err))
742
758
  return;
743
759
  const pageContextAbort = err._pageContextAbort;
@@ -748,62 +764,7 @@ function assertIsNotAbort(err, urlOr404) {
748
764
  (0, utils_js_1.assert)(abortCaller);
749
765
  const abortCall = pageContextAbort._abortCall;
750
766
  (0, utils_js_1.assert)(abortCall);
751
- (0, utils_js_1.assertUsage)(false, `${picocolors_1.default.cyan(abortCall)} thrown${thrownBy} while pre-rendering ${urlOr404} but ${picocolors_1.default.cyan(abortCaller)} isn't supported for pre-rendered pages`);
752
- }
753
- function makePageContextComputedUrlNonEnumerable(pageContexts) {
754
- change(false);
755
- return { restoreEnumerable, addPageContextComputedUrl };
756
- function restoreEnumerable() {
757
- change(true);
758
- }
759
- function addPageContextComputedUrl(pageContexts) {
760
- // Add URL computed props to the user-generated pageContext copies
761
- pageContexts.forEach((pageContext) => {
762
- const pageContextUrlComputed = (0, getPageContextUrlComputed_js_1.getPageContextUrlComputed)(pageContext);
763
- (0, utils_js_1.objectAssign)(pageContext, pageContextUrlComputed);
764
- });
765
- }
766
- function change(enumerable) {
767
- pageContexts.forEach((pageContext) => {
768
- (0, utils_js_1.changeEnumerable)(pageContext, 'urlPathname', enumerable);
769
- (0, utils_js_1.changeEnumerable)(pageContext, 'urlParsed', enumerable);
770
- });
771
- }
772
- }
773
- function validatePrerenderConfig(
774
- // Guaranteed by configDef.type to be either an object or boolean
775
- prerenderConfig) {
776
- if (!prerenderConfig || typeof prerenderConfig === 'boolean')
777
- return;
778
- (0, utils_js_1.assert)((0, utils_js_1.isObject)(prerenderConfig));
779
- const wrongValue = (() => {
780
- {
781
- const p = 'partial';
782
- if (!(0, utils_js_1.hasProp)(prerenderConfig, p, 'boolean') && !(0, utils_js_1.hasProp)(prerenderConfig, p, 'undefined'))
783
- return { prop: p, errMsg: 'should be a boolean' };
784
- }
785
- {
786
- const p = 'noExtraDir';
787
- if (!(0, utils_js_1.hasProp)(prerenderConfig, p, 'boolean') && !(0, utils_js_1.hasProp)(prerenderConfig, p, 'undefined'))
788
- return { prop: p, errMsg: 'should be a boolean' };
789
- }
790
- {
791
- const p = 'disableAutoRun';
792
- if (!(0, utils_js_1.hasProp)(prerenderConfig, p, 'boolean') && !(0, utils_js_1.hasProp)(prerenderConfig, p, 'undefined'))
793
- return { prop: p, errMsg: 'should be a boolean' };
794
- }
795
- {
796
- const p = 'parallel';
797
- if (!(0, utils_js_1.hasProp)(prerenderConfig, p, 'boolean') &&
798
- !(0, utils_js_1.hasProp)(prerenderConfig, p, 'number') &&
799
- !(0, utils_js_1.hasProp)(prerenderConfig, p, 'undefined'))
800
- return { prop: p, errMsg: 'should be a boolean or a number' };
801
- }
802
- })();
803
- if (wrongValue) {
804
- const { prop, errMsg } = wrongValue;
805
- (0, utils_js_1.assertUsage)(false, `Setting ${picocolors_1.default.cyan(`prerender.${prop}`)} ${errMsg}`);
806
- }
767
+ (0, utils_js_1.assertUsage)(false, `${picocolors_1.default.cyan(abortCall)} thrown${thrownBy} while pre-rendering ${urlOriginal} but ${picocolors_1.default.cyan(abortCaller)} isn't supported for pre-rendered pages`);
807
768
  }
808
769
  function makePublic(prerenderContext) {
809
770
  const prerenderContextPublic = (0, utils_js_1.makePublicCopy)(prerenderContext, 'prerenderContext', [
@@ -31,6 +31,6 @@ __exportStar(require("../../utils/pLimit.js"), exports);
31
31
  __exportStar(require("../../utils/isFilePathAbsoluteFilesystem.js"), exports);
32
32
  __exportStar(require("../../utils/isArray.js"), exports);
33
33
  __exportStar(require("../../utils/isObject.js"), exports);
34
- __exportStar(require("../../utils/changeEnumerable.js"), exports);
35
34
  __exportStar(require("../../utils/makePublicCopy.js"), exports);
36
35
  __exportStar(require("../../utils/isNullish.js"), exports);
36
+ __exportStar(require("../../utils/preservePropertyGetters.js"), exports);