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
@@ -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, changeEnumerable, onSetupPrerender, isObject, makePublicCopy, PROJECT_VERSION } from './utils.js';
8
- import { prerenderPage, prerender404Page, getPageContextInitEnhanced } from '../runtime/renderPage/renderPageAlreadyRouted.js';
7
+ import { assert, assertUsage, assertWarning, hasProp, objectAssign, isObjectWithKeys, isCallable, isPropertyGetter, assertPosixPath, urlToFile, isPlainObject, pLimit, isArray, onSetupPrerender, 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';
@@ -78,23 +77,26 @@ async function runPrerender(options = {}, standaloneTrigger) {
78
77
  const viteConfig = await resolveConfig(options.viteConfig || {}, 'build', 'production');
79
78
  const vikeConfig = await getVikeConfig(viteConfig);
80
79
  const vike = getVikeConfigPublic(viteConfig);
81
- assert(vike.prerenderContext.isPrerenderingEnabled);
82
80
  const { outDirClient, outDirServer } = getOutDirs(viteConfig);
83
81
  const { root } = viteConfig;
84
82
  const prerenderConfigGlobal = resolvePrerenderConfigGlobal(vikeConfig);
85
- validatePrerenderConfig(prerenderConfigGlobal);
86
83
  const { partial, noExtraDir, parallel, defaultLocalValue, isPrerenderingEnabled } = prerenderConfigGlobal;
87
84
  if (!isPrerenderingEnabled) {
88
85
  assert(standaloneTrigger);
89
- // TODO/now: make it assertUsage() and remove dist/server/entry.mjs if pre-rendering is completely disabled
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 });
86
+ /* TODO/soon: use this again a little while after https://github.com/magne4000/vite-plugin-vercel/pull/156 is merged.
87
+ assertUsage(
88
+ false,
89
+ `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.`
90
+ )
91
+ */
92
+ return { viteConfig };
91
93
  }
92
94
  const concurrencyLimit = pLimit(parallel === false || parallel === 0 ? 1 : parallel === true || parallel === undefined ? cpus().length : parallel);
93
95
  await initGlobalContext_runPrerender();
94
96
  const globalContext = await getGlobalContextInternal();
95
97
  globalContext.pageFilesAll.forEach(assertExportNames);
96
98
  const prerenderContext = {
97
- noExtraDir: noExtraDir ?? false,
99
+ noExtraDir,
98
100
  pageContexts: [],
99
101
  pageContextInit: options.pageContextInit ?? null,
100
102
  prerenderedPageContexts: {},
@@ -102,21 +104,29 @@ async function runPrerender(options = {}, standaloneTrigger) {
102
104
  };
103
105
  const doNotPrerenderList = [];
104
106
  await collectDoNoPrerenderList(vikeConfig.pageConfigs, doNotPrerenderList, defaultLocalValue, concurrencyLimit, globalContext);
107
+ // Allow user to create `pageContext` for parameterized routes and/or bulk data fetching
108
+ // https://vike.dev/onBeforePrerenderStart
105
109
  await callOnBeforePrerenderStartHooks(prerenderContext, globalContext, concurrencyLimit, doNotPrerenderList);
106
- await handlePagesWithStaticRoutes(prerenderContext, globalContext, doNotPrerenderList, concurrencyLimit);
107
- await callOnPrerenderStartHook(prerenderContext, globalContext);
110
+ // Create `pageContext` for each page with a static route
111
+ const urlList = getUrlListFromPagesWithStaticRoute(globalContext, doNotPrerenderList);
112
+ await createPageContextsForOnPrerenderStartHook(urlList, prerenderContext, globalContext, concurrencyLimit, false);
113
+ // Create `pageContext` for 404 page
114
+ const urlList404 = getUrlList404(globalContext);
115
+ await createPageContextsForOnPrerenderStartHook(urlList404, prerenderContext, globalContext, concurrencyLimit, true);
116
+ // Allow user to duplicate the list of `pageContext` for i18n
117
+ // https://vike.dev/onPrerenderStart
118
+ await callOnPrerenderStartHook(prerenderContext, globalContext, concurrencyLimit);
108
119
  let prerenderedCount = 0;
109
120
  // Write files as soon as pages finish rendering (instead of writing all files at once only after all pages have rendered).
110
121
  const onComplete = async (htmlFile) => {
111
122
  prerenderedCount++;
112
- if (htmlFile.pageId) {
113
- prerenderContext.prerenderedPageContexts[htmlFile.pageId] = htmlFile.pageContext;
114
- }
123
+ const { pageId } = htmlFile.pageContext;
124
+ assert(pageId);
125
+ prerenderContext.prerenderedPageContexts[pageId] = htmlFile.pageContext;
115
126
  await writeFiles(htmlFile, root, outDirClient, options.onPagePrerender, prerenderContext.output, logLevel);
116
127
  };
117
- await routeAndPrerender(prerenderContext, globalContext, concurrencyLimit, onComplete);
128
+ await prerenderPages(prerenderContext, concurrencyLimit, onComplete);
118
129
  warnContradictoryNoPrerenderList(prerenderContext.prerenderedPageContexts, doNotPrerenderList);
119
- await prerender404(prerenderContext, globalContext, onComplete);
120
130
  if (logLevel === 'info') {
121
131
  console.log(`${pc.green(`✓`)} ${prerenderedCount} HTML documents pre-rendered.`);
122
132
  }
@@ -228,12 +238,13 @@ async function callOnBeforePrerenderStartHooks(prerenderContext, globalContext,
228
238
  });
229
239
  })));
230
240
  await Promise.all(onBeforePrerenderStartHooks.map(({ hookFn, hookName, hookFilePath, pageId, hookTimeout }) => concurrencyLimit(async () => {
231
- if (doNotPrerenderList.find((p) => p.pageId === pageId)) {
241
+ if (doNotPrerenderList.find((p) => p.pageId === pageId))
232
242
  return;
233
- }
234
243
  const prerenderResult = await executeHook(() => hookFn(), { hookName, hookFilePath, hookTimeout }, null);
235
244
  const result = normalizeOnPrerenderHookResult(prerenderResult, hookFilePath, hookName);
245
+ // Handle result
236
246
  await Promise.all(result.map(async ({ url, pageContext }) => {
247
+ // Assert no duplication
237
248
  {
238
249
  const pageContextFound = prerenderContext.pageContexts.find((pageContext) => isSameUrl(pageContext.urlOriginal, url));
239
250
  if (pageContextFound) {
@@ -244,30 +255,23 @@ async function callOnBeforePrerenderStartHooks(prerenderContext, globalContext,
244
255
  assertUsage(false, `URL ${pc.cyan(url)} provided ${providedTwice}. Make sure to provide the URL only once instead.`);
245
256
  }
246
257
  }
247
- const pageContextNew = await createPageContext(url, prerenderContext, globalContext);
248
- objectAssign(pageContextNew, {
249
- _providedByHook: {
250
- hookFilePath,
251
- hookName
252
- }
253
- });
258
+ // Add result
259
+ const providedByHook = { hookFilePath, hookName };
260
+ const pageContextNew = await createPageContext(url, prerenderContext, globalContext, false, undefined, providedByHook);
254
261
  prerenderContext.pageContexts.push(pageContextNew);
255
262
  if (pageContext) {
256
- objectAssign(pageContextNew, {
257
- _pageContextAlreadyProvidedByOnPrerenderHook: true
258
- });
263
+ objectAssign(pageContextNew, { _pageContextAlreadyProvidedByOnPrerenderHook: true });
259
264
  objectAssign(pageContextNew, pageContext);
260
265
  }
261
266
  }));
262
267
  })));
263
268
  }
264
- async function handlePagesWithStaticRoutes(prerenderContext, globalContext, doNotPrerenderList, concurrencyLimit) {
265
- // Pre-render pages with a static route
266
- await Promise.all(globalContext.pageRoutes.map((pageRoute) => concurrencyLimit(async () => {
269
+ function getUrlListFromPagesWithStaticRoute(globalContext, doNotPrerenderList) {
270
+ const urlList = [];
271
+ globalContext.pageRoutes.map((pageRoute) => {
267
272
  const { pageId } = pageRoute;
268
- if (doNotPrerenderList.find((p) => p.pageId === pageId)) {
273
+ if (doNotPrerenderList.find((p) => p.pageId === pageId))
269
274
  return;
270
- }
271
275
  let urlOriginal;
272
276
  if (!('routeString' in pageRoute)) {
273
277
  // Abort since the page's route is a Route Function
@@ -283,43 +287,111 @@ async function handlePagesWithStaticRoutes(prerenderContext, globalContext, doNo
283
287
  urlOriginal = url;
284
288
  }
285
289
  assert(urlOriginal.startsWith('/'));
290
+ urlList.push({ urlOriginal, pageId });
291
+ });
292
+ return urlList;
293
+ }
294
+ function getUrlList404(globalContext) {
295
+ const urlList = [];
296
+ const errorPageId = getErrorPageId(globalContext.pageFilesAll, globalContext.pageConfigs);
297
+ if (errorPageId) {
298
+ urlList.push({
299
+ // A URL is required for `viteDevServer.transformIndexHtml(url,html)`
300
+ urlOriginal: '/404',
301
+ pageId: errorPageId
302
+ });
303
+ }
304
+ return urlList;
305
+ }
306
+ async function createPageContextsForOnPrerenderStartHook(urlList, prerenderContext, globalContext, concurrencyLimit, is404) {
307
+ await Promise.all(urlList.map(({ urlOriginal, pageId }) => concurrencyLimit(async () => {
286
308
  // Already included in a onBeforePrerenderStart() hook
287
309
  if (prerenderContext.pageContexts.find((pageContext) => isSameUrl(pageContext.urlOriginal, urlOriginal))) {
288
310
  return;
289
311
  }
290
- const routeParams = {};
291
- const pageContext = await createPageContext(urlOriginal, prerenderContext, globalContext);
292
- objectAssign(pageContext, {
293
- _providedByHook: null,
294
- routeParams,
295
- pageId: pageId,
296
- _debugRouteMatches: [
297
- {
298
- pageId,
299
- routeType: pageRoute.routeType,
300
- routeString: urlOriginal,
301
- routeParams
302
- }
303
- ]
304
- });
305
- objectAssign(pageContext, await loadUserFilesServerSide(pageContext));
312
+ const pageContext = await createPageContext(urlOriginal, prerenderContext, globalContext, is404, pageId, null);
306
313
  prerenderContext.pageContexts.push(pageContext);
307
314
  })));
308
315
  }
309
- async function createPageContext(urlOriginal, prerenderContext, globalContext) {
310
- const pageContextInit = { urlOriginal };
311
- objectAssign(pageContextInit, prerenderContext.pageContextInit);
312
- const pageContext = await getPageContextInitEnhanced(pageContextInit, globalContext, true, {});
316
+ async function createPageContext(urlOriginal, prerenderContext, globalContext, is404, pageId, providedByHook) {
317
+ const pageContextInit = {
318
+ urlOriginal,
319
+ ...prerenderContext.pageContextInit
320
+ };
321
+ const pageContext = await getPageContextInitEnhanced(pageContextInit, globalContext, true);
313
322
  assert(pageContext.isPrerendering === true);
314
323
  objectAssign(pageContext, {
315
324
  _urlHandler: null,
325
+ _httpRequestId: null,
316
326
  _urlRewrite: null,
317
327
  _noExtraDir: prerenderContext.noExtraDir,
318
- _prerenderContext: prerenderContext
328
+ _prerenderContext: prerenderContext,
329
+ _providedByHook: providedByHook,
330
+ _urlOriginalModifiedByHook: null,
331
+ is404
319
332
  });
333
+ if (!is404) {
334
+ const pageContextFromRoute = await route(pageContext);
335
+ assert(hasProp(pageContextFromRoute, 'pageId', 'null') || hasProp(pageContextFromRoute, 'pageId', 'string')); // Help TS
336
+ assertRouteMatch(pageContextFromRoute, pageContext);
337
+ assert(pageContextFromRoute.pageId);
338
+ objectAssign(pageContext, pageContextFromRoute);
339
+ }
340
+ else {
341
+ assert(pageId);
342
+ objectAssign(pageContext, {
343
+ pageId,
344
+ _debugRouteMatches: [],
345
+ routeParams: {}
346
+ });
347
+ }
348
+ objectAssign(pageContext, await loadUserFilesServerSide(pageContext));
349
+ let usesClientRouter;
350
+ {
351
+ const { pageId } = pageContext;
352
+ assert(pageId);
353
+ assert(globalContext.isPrerendering);
354
+ if (globalContext.pageConfigs.length > 0) {
355
+ const pageConfig = globalContext.pageConfigs.find((p) => p.pageId === pageId);
356
+ assert(pageConfig);
357
+ usesClientRouter = getConfigValueRuntime(pageConfig, 'clientRouting', 'boolean')?.value ?? false;
358
+ }
359
+ else {
360
+ usesClientRouter = globalContext.usesClientRouter;
361
+ }
362
+ }
363
+ objectAssign(pageContext, { _usesClientRouter: usesClientRouter });
320
364
  return pageContext;
321
365
  }
322
- async function callOnPrerenderStartHook(prerenderContext, globalContext) {
366
+ function assertRouteMatch(pageContextFromRoute, pageContext) {
367
+ if (pageContextFromRoute.pageId !== null) {
368
+ assert(pageContextFromRoute.pageId);
369
+ return;
370
+ }
371
+ let hookName;
372
+ let hookFilePath;
373
+ if (pageContext._urlOriginalModifiedByHook) {
374
+ hookName = pageContext._urlOriginalModifiedByHook.hookName;
375
+ hookFilePath = pageContext._urlOriginalModifiedByHook.hookFilePath;
376
+ }
377
+ else if (pageContext._providedByHook) {
378
+ hookName = pageContext._providedByHook.hookName;
379
+ hookFilePath = pageContext._providedByHook.hookFilePath;
380
+ }
381
+ if (hookName) {
382
+ assert(hookFilePath);
383
+ const { urlOriginal } = pageContext;
384
+ assert(urlOriginal);
385
+ 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.`);
386
+ }
387
+ else {
388
+ // `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.
389
+ assert(pageContextFromRoute._routingProvidedByOnBeforeRouteHook);
390
+ // Abort since the URL doesn't correspond to any page
391
+ return;
392
+ }
393
+ }
394
+ async function callOnPrerenderStartHook(prerenderContext, globalContext, concurrencyLimit) {
323
395
  let onPrerenderStartHook;
324
396
  // V1 design
325
397
  if (globalContext.pageConfigs.length > 0) {
@@ -389,8 +461,11 @@ async function callOnPrerenderStartHook(prerenderContext, globalContext) {
389
461
  pageContext._urlOriginalBeforeHook = pageContext.urlOriginal;
390
462
  });
391
463
  const docLink = 'https://vike.dev/i18n#pre-rendering';
392
- // Set `enumerable` to `false` to avoid computed URL properties from being iterated & copied in onPrerenderStart() hook, e.g. /examples/i18n/
393
- const { restoreEnumerable, addPageContextComputedUrl } = makePageContextComputedUrlNonEnumerable(prerenderContext.pageContexts);
464
+ prerenderContext.pageContexts.forEach((pageContext) => {
465
+ // Preserve URL computed properties when the user is copying pageContext is his onPrerenderStart() hook, e.g. /examples/i18n/
466
+ // https://vike.dev/i18n#pre-rendering
467
+ preservePropertyGetters(pageContext);
468
+ });
394
469
  let result = await executeHook(() => {
395
470
  const prerenderContextPublic = makePublic(prerenderContext);
396
471
  // TODO/v1-release: remove warning
@@ -405,7 +480,11 @@ async function callOnPrerenderStartHook(prerenderContext, globalContext) {
405
480
  });
406
481
  return hookFn(prerenderContextPublic);
407
482
  }, onPrerenderStartHook, null);
408
- restoreEnumerable();
483
+ // Before applying result
484
+ prerenderContext.pageContexts.forEach((pageContext) => {
485
+ ;
486
+ pageContext._restorePropertyGetters?.();
487
+ });
409
488
  if (result === null || result === undefined) {
410
489
  return;
411
490
  }
@@ -436,82 +515,42 @@ async function callOnPrerenderStartHook(prerenderContext, globalContext) {
436
515
  }
437
516
  delete pageContext.url;
438
517
  });
518
+ // After applying result
439
519
  prerenderContext.pageContexts.forEach((pageContext) => {
440
- if (pageContext.urlOriginal !== pageContext._urlOriginalBeforeHook) {
520
+ ;
521
+ pageContext._restorePropertyGetters?.();
522
+ });
523
+ // Assert URL modified by user
524
+ await Promise.all(prerenderContext.pageContexts.map((pageContext) => concurrencyLimit(async () => {
525
+ if (pageContext.urlOriginal !== pageContext._urlOriginalBeforeHook && !pageContext.is404) {
441
526
  pageContext._urlOriginalModifiedByHook = {
442
527
  hookFilePath,
443
528
  hookName
444
529
  };
530
+ const pageContextFromRoute = await route(pageContext,
531
+ // 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.
532
+ true);
533
+ assertRouteMatch(pageContextFromRoute, pageContext);
445
534
  }
446
- });
447
- addPageContextComputedUrl(prerenderContext.pageContexts);
535
+ })));
448
536
  }
449
- async function routeAndPrerender(prerenderContext, globalContext, concurrencyLimit, onComplete) {
450
- assert(globalContext.isPrerendering);
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
- });
537
+ async function prerenderPages(prerenderContext, concurrencyLimit, onComplete) {
538
+ await Promise.all(prerenderContext.pageContexts.map((pageContextBeforeRender) => concurrencyLimit(async () => {
499
539
  let res;
500
540
  try {
501
- res = await prerenderPage(pageContext);
541
+ res = await prerenderPage(pageContextBeforeRender);
502
542
  }
503
543
  catch (err) {
504
- assertIsNotAbort(err, pc.cyan(pageContext.urlOriginal));
544
+ assertIsNotAbort(err, pc.cyan(pageContextBeforeRender.urlOriginal));
505
545
  throw err;
506
546
  }
507
- const { documentHtml, pageContextSerialized } = res;
547
+ const { documentHtml, pageContext } = res;
548
+ const pageContextSerialized = pageContext.is404 ? null : res.pageContextSerialized;
508
549
  await onComplete({
509
- urlOriginal,
510
550
  pageContext,
511
551
  htmlString: documentHtml,
512
552
  pageContextSerialized,
513
- doNotCreateExtraDirectory: prerenderContext.noExtraDir,
514
- pageId
553
+ doNotCreateExtraDirectory: prerenderContext.noExtraDir ?? pageContext.is404
515
554
  });
516
555
  })));
517
556
  }
@@ -543,31 +582,8 @@ async function warnMissingPages(prerenderedPageContexts, globalContext, doNotPre
543
582
  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
583
  });
545
584
  }
546
- async function prerender404(prerenderContext, globalContext, onComplete) {
547
- if (!Object.values(prerenderContext.prerenderedPageContexts).find(({ urlOriginal }) => urlOriginal === '/404')) {
548
- let result;
549
- try {
550
- result = await prerender404Page(prerenderContext.pageContextInit, globalContext);
551
- }
552
- catch (err) {
553
- assertIsNotAbort(err, 'the 404 page');
554
- throw err;
555
- }
556
- if (result) {
557
- const urlOriginal = '/404';
558
- const { documentHtml, pageContext } = result;
559
- await onComplete({
560
- urlOriginal,
561
- pageContext,
562
- htmlString: documentHtml,
563
- pageContextSerialized: null,
564
- doNotCreateExtraDirectory: true,
565
- pageId: null
566
- });
567
- }
568
- }
569
- }
570
- async function writeFiles({ urlOriginal, pageContext, htmlString, pageContextSerialized, doNotCreateExtraDirectory }, root, outDirClient, onPagePrerender, output, logLevel) {
585
+ async function writeFiles({ pageContext, htmlString, pageContextSerialized, doNotCreateExtraDirectory }, root, outDirClient, onPagePrerender, output, logLevel) {
586
+ const { urlOriginal } = pageContext;
571
587
  assert(urlOriginal.startsWith('/'));
572
588
  const writeJobs = [
573
589
  write(urlOriginal, pageContext, 'HTML', htmlString, root, outDirClient, doNotCreateExtraDirectory, onPagePrerender, output, logLevel)
@@ -699,7 +715,7 @@ function runPrerender_forceExit() {
699
715
  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 })
700
716
  */
701
717
  }
702
- function assertIsNotAbort(err, urlOr404) {
718
+ function assertIsNotAbort(err, urlOriginal) {
703
719
  if (!isAbortError(err))
704
720
  return;
705
721
  const pageContextAbort = err._pageContextAbort;
@@ -710,62 +726,7 @@ function assertIsNotAbort(err, urlOr404) {
710
726
  assert(abortCaller);
711
727
  const abortCall = pageContextAbort._abortCall;
712
728
  assert(abortCall);
713
- assertUsage(false, `${pc.cyan(abortCall)} thrown${thrownBy} while pre-rendering ${urlOr404} but ${pc.cyan(abortCaller)} isn't supported for pre-rendered pages`);
714
- }
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
- function validatePrerenderConfig(
736
- // Guaranteed by configDef.type to be either an object or boolean
737
- prerenderConfig) {
738
- if (!prerenderConfig || typeof prerenderConfig === 'boolean')
739
- return;
740
- assert(isObject(prerenderConfig));
741
- const wrongValue = (() => {
742
- {
743
- const p = 'partial';
744
- if (!hasProp(prerenderConfig, p, 'boolean') && !hasProp(prerenderConfig, p, 'undefined'))
745
- return { prop: p, errMsg: 'should be a boolean' };
746
- }
747
- {
748
- const p = 'noExtraDir';
749
- if (!hasProp(prerenderConfig, p, 'boolean') && !hasProp(prerenderConfig, p, 'undefined'))
750
- return { prop: p, errMsg: 'should be a boolean' };
751
- }
752
- {
753
- const p = 'disableAutoRun';
754
- if (!hasProp(prerenderConfig, p, 'boolean') && !hasProp(prerenderConfig, p, 'undefined'))
755
- return { prop: p, errMsg: 'should be a boolean' };
756
- }
757
- {
758
- const p = 'parallel';
759
- if (!hasProp(prerenderConfig, p, 'boolean') &&
760
- !hasProp(prerenderConfig, p, 'number') &&
761
- !hasProp(prerenderConfig, p, 'undefined'))
762
- return { prop: p, errMsg: 'should be a boolean or a number' };
763
- }
764
- })();
765
- if (wrongValue) {
766
- const { prop, errMsg } = wrongValue;
767
- assertUsage(false, `Setting ${pc.cyan(`prerender.${prop}`)} ${errMsg}`);
768
- }
729
+ assertUsage(false, `${pc.cyan(abortCall)} thrown${thrownBy} while pre-rendering ${urlOriginal} but ${pc.cyan(abortCaller)} isn't supported for pre-rendered pages`);
769
730
  }
770
731
  function makePublic(prerenderContext) {
771
732
  const prerenderContextPublic = makePublicCopy(prerenderContext, 'prerenderContext', [
@@ -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';
@@ -1,3 +1,4 @@
1
+ export { getGlobalContext };
1
2
  export { getGlobalContextSync };
2
3
  export { getGlobalContextAsync };
3
4
  export { getGlobalContextInternal };
@@ -13,7 +14,6 @@ export { setGlobalContext_isProduction };
13
14
  export { setGlobalContext_buildEntry };
14
15
  export { clearGlobalContext };
15
16
  export { assertBuildInfo };
16
- export { getViteConfigRuntime };
17
17
  export { updateUserFiles };
18
18
  export type { BuildInfo };
19
19
  export type { GlobalContextInternal };
@@ -22,14 +22,13 @@ import type { ViteManifest } from '../shared/ViteManifest.js';
22
22
  import type { ResolvedConfig, ViteDevServer } from 'vite';
23
23
  import type { PageConfigUserFriendly, PageConfigsUserFriendly } from '../../shared/page-configs/getPageConfigUserFriendly.js';
24
24
  import { type BaseUrlsResolved } from '../shared/resolveBase.js';
25
+ import type { ViteConfigRuntime } from '../plugin/shared/getViteConfigRuntime.js';
25
26
  type PageRuntimeInfo = Awaited<ReturnType<typeof getUserFiles>>;
26
27
  type GlobalContextInternal = GlobalContext & {
27
28
  globalContext_public: GlobalContextPublic;
28
29
  };
29
30
  type GlobalContext = {
30
- viteConfigRuntime: {
31
- _baseViteOriginal: null | string;
32
- };
31
+ viteConfigRuntime: ViteConfigRuntime;
33
32
  config: PageConfigUserFriendly['config'];
34
33
  pages: PageConfigsUserFriendly;
35
34
  } & BaseUrlsResolved & PageRuntimeInfo & ({
@@ -51,16 +50,32 @@ type GlobalContext = {
51
50
  viteConfig: ResolvedConfig;
52
51
  })));
53
52
  declare function getGlobalContextInternal(): Promise<GlobalContextInternal>;
54
- /** @experimental https://vike.dev/getGlobalContext */
55
- declare function getGlobalContextSync(): GlobalContextPublic;
56
- /** @experimental https://vike.dev/getGlobalContext */
53
+ /**
54
+ * Get runtime information about your app.
55
+ *
56
+ * https://vike.dev/getGlobalContext
57
+ */
58
+ declare function getGlobalContext(): Promise<GlobalContextPublic>;
59
+ /**
60
+ * Get runtime information about your app.
61
+ *
62
+ * https://vike.dev/getGlobalContext
63
+ */
57
64
  declare function getGlobalContextAsync(isProduction: boolean): Promise<GlobalContextPublic>;
65
+ /**
66
+ * Get runtime information about your app.
67
+ *
68
+ * https://vike.dev/getGlobalContext
69
+ *
70
+ * @deprecated
71
+ */
72
+ declare function getGlobalContextSync(): GlobalContextPublic;
58
73
  type GlobalContextPublic = ReturnType<typeof makePublic>;
59
- declare function makePublic(globalContext: GlobalContext): Pick<GlobalContext, "pages" | "baseServer" | "baseAssets" | "config" | "assetsManifest" | "viteConfig">;
74
+ declare function makePublic(globalContext: GlobalContext): Pick<GlobalContext, "pages" | "baseServer" | "baseAssets" | "config" | "assetsManifest" | "viteConfig" | "viteConfigRuntime">;
60
75
  declare function setGlobalContext_viteDevServer(viteDevServer: ViteDevServer): Promise<void>;
61
- declare function setGlobalContext_viteConfig(viteConfig: ResolvedConfig, outDirRoot: string): void;
76
+ declare function setGlobalContext_viteConfig(viteConfig: ResolvedConfig, viteConfigRuntime: ViteConfigRuntime): void;
62
77
  declare function setGlobalContext_isPrerendering(): void;
63
- declare function setGlobalContext_isProduction(isProduction: boolean): void;
78
+ declare function setGlobalContext_isProduction(isProduction: boolean, tolerateContraditction?: true): void;
64
79
  declare function getViteDevServer(): ViteDevServer | null;
65
80
  declare function getViteConfig(): ResolvedConfig | null;
66
81
  declare function initGlobalContext_renderPage(): Promise<void>;
@@ -80,14 +95,8 @@ declare function setGlobalContext_buildEntry(buildEntry: unknown): Promise<void>
80
95
  type BuildInfo = {
81
96
  versionAtBuildTime: string;
82
97
  usesClientRouter: boolean;
83
- viteConfigRuntime: {
84
- _baseViteOriginal: string;
85
- vitePluginServerEntry: {
86
- inject?: boolean;
87
- };
88
- };
98
+ viteConfigRuntime: ViteConfigRuntime;
89
99
  };
90
100
  declare function assertBuildInfo(buildInfo: unknown): asserts buildInfo is BuildInfo;
91
- declare function getViteConfigRuntime(viteConfig: ResolvedConfig): BuildInfo['viteConfigRuntime'];
92
101
  declare function updateUserFiles(): Promise<void>;
93
102
  declare function clearGlobalContext(): void;