vike 0.4.146 → 0.4.147-commit-f9a91f3

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 (85) hide show
  1. package/dist/cjs/node/plugin/index.js +6 -4
  2. package/dist/cjs/node/plugin/plugins/devConfig/determineOptimizeDeps.js +3 -4
  3. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getConfigValuesSerialized.js +76 -0
  4. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +61 -40
  5. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +104 -0
  6. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +62 -75
  7. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +43 -17
  8. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +12 -70
  9. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/isRuntimeEnvMatch.js +11 -8
  10. package/dist/cjs/node/plugin/shared/{getConfigValueSourcesRelevant.js → getConfigValueSourcesNotOverriden.js} +3 -3
  11. package/dist/cjs/node/plugin/utils.js +2 -0
  12. package/dist/cjs/node/prerender/runPrerender.js +75 -67
  13. package/dist/cjs/node/runtime/html/injectAssets/injectAssets__public.js +1 -1
  14. package/dist/cjs/node/runtime/index-common.js +3 -1
  15. package/dist/cjs/node/runtime/renderPage/analyzePage.js +2 -2
  16. package/dist/cjs/node/runtime/renderPage/createHttpResponseObject/assertNoInfiniteHttpRedirect.js +12 -12
  17. package/dist/cjs/node/runtime/renderPage/createHttpResponseObject.js +3 -3
  18. package/dist/cjs/node/runtime/renderPage/executeOnRenderHtmlHook.js +1 -2
  19. package/dist/cjs/node/runtime/renderPage/getHttpResponseBody.js +1 -1
  20. package/dist/cjs/node/runtime/renderPage.js +75 -51
  21. package/dist/cjs/shared/getPageFiles/analyzePageClientSide/determineClientEntry.js +1 -0
  22. package/dist/cjs/shared/page-configs/loadConfigValues.js +12 -3
  23. package/dist/cjs/shared/page-configs/serialize/parseConfigValuesSerialized.js +19 -0
  24. package/dist/cjs/shared/page-configs/serialize/parsePageConfigs.js +3 -12
  25. package/dist/cjs/shared/route/resolveRedirects.js +8 -5
  26. package/dist/cjs/utils/assertKeys.js +28 -0
  27. package/dist/cjs/utils/joinEnglish.js +3 -3
  28. package/dist/cjs/utils/parseUrl-extras.js +22 -8
  29. package/dist/cjs/utils/parseUrl.js +24 -16
  30. package/dist/cjs/utils/projectInfo.js +3 -2
  31. package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.js +25 -11
  32. package/dist/esm/client/client-routing-runtime/index.d.ts +1 -0
  33. package/dist/esm/client/client-routing-runtime/index.js +1 -0
  34. package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.js +2 -2
  35. package/dist/esm/client/shared/getPageContextSerializedInHtml.js +1 -1
  36. package/dist/esm/node/plugin/index.d.ts +1 -0
  37. package/dist/esm/node/plugin/index.js +1 -0
  38. package/dist/esm/node/plugin/plugins/devConfig/determineOptimizeDeps.js +3 -4
  39. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getConfigValuesSerialized.d.ts +5 -0
  40. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getConfigValuesSerialized.js +70 -0
  41. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +58 -37
  42. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.d.ts +5 -0
  43. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +98 -0
  44. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +63 -76
  45. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +43 -17
  46. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.d.ts +0 -3
  47. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +13 -68
  48. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/isRuntimeEnvMatch.js +11 -8
  49. package/dist/esm/node/plugin/shared/getConfigValueSourcesNotOverriden.d.ts +5 -0
  50. package/dist/esm/node/plugin/shared/{getConfigValueSourcesRelevant.js → getConfigValueSourcesNotOverriden.js} +2 -2
  51. package/dist/esm/node/plugin/utils.d.ts +2 -0
  52. package/dist/esm/node/plugin/utils.js +2 -0
  53. package/dist/esm/node/prerender/runPrerender.js +75 -67
  54. package/dist/esm/node/runtime/html/injectAssets/injectAssets__public.js +1 -1
  55. package/dist/esm/node/runtime/index-common.d.ts +1 -0
  56. package/dist/esm/node/runtime/index-common.js +1 -0
  57. package/dist/esm/node/runtime/renderPage/analyzePage.js +2 -2
  58. package/dist/esm/node/runtime/renderPage/createHttpResponseObject/assertNoInfiniteHttpRedirect.d.ts +1 -1
  59. package/dist/esm/node/runtime/renderPage/createHttpResponseObject/assertNoInfiniteHttpRedirect.js +13 -13
  60. package/dist/esm/node/runtime/renderPage/createHttpResponseObject.d.ts +1 -1
  61. package/dist/esm/node/runtime/renderPage/createHttpResponseObject.js +3 -3
  62. package/dist/esm/node/runtime/renderPage/executeOnRenderHtmlHook.js +1 -2
  63. package/dist/esm/node/runtime/renderPage/getHttpResponseBody.js +1 -1
  64. package/dist/esm/node/runtime/renderPage.js +76 -52
  65. package/dist/esm/shared/getPageFiles/analyzePageClientSide/determineClientEntry.js +1 -0
  66. package/dist/esm/shared/page-configs/PageConfig.d.ts +14 -4
  67. package/dist/esm/shared/page-configs/loadConfigValues.js +12 -3
  68. package/dist/esm/shared/page-configs/serialize/parseConfigValuesSerialized.d.ts +4 -0
  69. package/dist/esm/shared/page-configs/serialize/parseConfigValuesSerialized.js +16 -0
  70. package/dist/esm/shared/page-configs/serialize/parsePageConfigs.js +4 -13
  71. package/dist/esm/shared/route/resolveRedirects.js +8 -5
  72. package/dist/esm/utils/assertKeys.d.ts +4 -0
  73. package/dist/esm/utils/assertKeys.js +22 -0
  74. package/dist/esm/utils/joinEnglish.d.ts +1 -1
  75. package/dist/esm/utils/joinEnglish.js +3 -3
  76. package/dist/esm/utils/parseUrl-extras.d.ts +3 -1
  77. package/dist/esm/utils/parseUrl-extras.js +21 -7
  78. package/dist/esm/utils/parseUrl.js +24 -16
  79. package/dist/esm/utils/projectInfo.d.ts +3 -1
  80. package/dist/esm/utils/projectInfo.js +2 -1
  81. package/package.json +3 -3
  82. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/helpers.js +0 -28
  83. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/helpers.d.ts +0 -5
  84. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/helpers.js +0 -25
  85. package/dist/esm/node/plugin/shared/getConfigValueSourcesRelevant.d.ts +0 -5
@@ -71,19 +71,25 @@ async function runPrerender(options, manuallyTriggered) {
71
71
  const doNotPrerenderList = [];
72
72
  const vikeConfig = await getVikeConfig(viteConfig, false);
73
73
  await collectDoNoPrerenderList(renderContext, vikeConfig.pageConfigs, doNotPrerenderList, concurrencyLimit);
74
- await callOnBeforePrerenderStartHooks(prerenderContext, renderContext, concurrencyLimit);
74
+ await callOnBeforePrerenderStartHooks(prerenderContext, renderContext, concurrencyLimit, doNotPrerenderList);
75
75
  await handlePagesWithStaticRoutes(prerenderContext, renderContext, doNotPrerenderList, concurrencyLimit);
76
76
  await callOnPrerenderStartHook(prerenderContext, renderContext);
77
- const prerenderPageIds = {};
78
- const htmlFiles = [];
79
- await routeAndPrerender(prerenderContext, htmlFiles, prerenderPageIds, concurrencyLimit);
80
- warnContradictoryNoPrerenderList(prerenderPageIds, doNotPrerenderList);
81
- await prerender404(htmlFiles, renderContext, prerenderContext);
77
+ const prerenderedPageContexts = {};
78
+ let prerenderedCount = 0;
79
+ const onComplete = async (htmlFile) => {
80
+ prerenderedCount++;
81
+ if (htmlFile.pageId) {
82
+ prerenderedPageContexts[htmlFile.pageId] = htmlFile.pageContext;
83
+ }
84
+ await writeFiles(htmlFile, root, outDirClient, options.onPagePrerender, logLevel);
85
+ };
86
+ await routeAndPrerender(prerenderContext, concurrencyLimit, onComplete);
87
+ warnContradictoryNoPrerenderList(prerenderedPageContexts, doNotPrerenderList);
88
+ await prerender404(prerenderedPageContexts, renderContext, prerenderContext, onComplete);
82
89
  if (logLevel === 'info') {
83
- console.log(`${pc.green(`✓`)} ${htmlFiles.length} HTML documents pre-rendered.`);
90
+ console.log(`${pc.green(`✓`)} ${prerenderedCount} HTML documents pre-rendered.`);
84
91
  }
85
- await Promise.all(htmlFiles.map((htmlFile) => writeHtmlFile(htmlFile, root, outDirClient, concurrencyLimit, options.onPagePrerender, logLevel)));
86
- warnMissingPages(prerenderPageIds, doNotPrerenderList, renderContext, partial);
92
+ warnMissingPages(prerenderedPageContexts, doNotPrerenderList, renderContext, partial);
87
93
  }
88
94
  async function collectDoNoPrerenderList(renderContext, pageConfigs, doNotPrerenderList, concurrencyLimit) {
89
95
  // V1 design
@@ -145,7 +151,7 @@ function assertExportNames(pageFile) {
145
151
  const { exportNames, fileType } = pageFile;
146
152
  assert(exportNames || fileType === '.page.route' || fileType === '.css', pageFile.filePath);
147
153
  }
148
- async function callOnBeforePrerenderStartHooks(prerenderContext, renderContext, concurrencyLimit) {
154
+ async function callOnBeforePrerenderStartHooks(prerenderContext, renderContext, concurrencyLimit, doNotPrerenderList) {
149
155
  const onBeforePrerenderStartHooks = [];
150
156
  // V1 design
151
157
  await Promise.all(renderContext.pageConfigs.map((pageConfig) => concurrencyLimit(async () => {
@@ -161,7 +167,8 @@ async function callOnBeforePrerenderStartHooks(prerenderContext, renderContext,
161
167
  onBeforePrerenderStartHooks.push({
162
168
  hookFn,
163
169
  hookName: 'onBeforePrerenderStart',
164
- hookFilePath
170
+ hookFilePath,
171
+ pageId: pageConfig.pageId
165
172
  });
166
173
  })));
167
174
  // 0.4 design
@@ -184,10 +191,14 @@ async function callOnBeforePrerenderStartHooks(prerenderContext, renderContext,
184
191
  onBeforePrerenderStartHooks.push({
185
192
  hookFn,
186
193
  hookName: 'prerender',
187
- hookFilePath
194
+ hookFilePath,
195
+ pageId: p.pageId
188
196
  });
189
197
  })));
190
- await Promise.all(onBeforePrerenderStartHooks.map(({ hookFn, hookName, hookFilePath }) => concurrencyLimit(async () => {
198
+ await Promise.all(onBeforePrerenderStartHooks.map(({ hookFn, hookName, hookFilePath, pageId }) => concurrencyLimit(async () => {
199
+ if (doNotPrerenderList.find((p) => p.pageId === pageId)) {
200
+ return;
201
+ }
191
202
  const prerenderResult = await hookFn();
192
203
  const result = normalizeOnPrerenderHookResult(prerenderResult, hookFilePath, hookName);
193
204
  result.forEach(({ url, pageContext }) => {
@@ -406,7 +417,7 @@ async function callOnPrerenderStartHook(prerenderContext, renderContext) {
406
417
  addUrlComputedProps(pageContext);
407
418
  });
408
419
  }
409
- async function routeAndPrerender(prerenderContext, htmlFiles, prerenderPageIds, concurrencyLimit) {
420
+ async function routeAndPrerender(prerenderContext, concurrencyLimit, onComplete) {
410
421
  const globalContext = getGlobalContext();
411
422
  assert(globalContext.isPrerendering);
412
423
  // Route all URLs
@@ -466,7 +477,7 @@ async function routeAndPrerender(prerenderContext, htmlFiles, prerenderPageIds,
466
477
  throw err;
467
478
  }
468
479
  const { documentHtml, pageContextSerialized } = res;
469
- htmlFiles.push({
480
+ await onComplete({
470
481
  urlOriginal,
471
482
  pageContext,
472
483
  htmlString: documentHtml,
@@ -474,11 +485,10 @@ async function routeAndPrerender(prerenderContext, htmlFiles, prerenderPageIds,
474
485
  doNotCreateExtraDirectory: prerenderContext._noExtraDir,
475
486
  pageId
476
487
  });
477
- prerenderPageIds[pageId] = pageContext;
478
488
  })));
479
489
  }
480
- function warnContradictoryNoPrerenderList(prerenderPageIds, doNotPrerenderList) {
481
- Object.entries(prerenderPageIds).forEach(([pageId, pageContext]) => {
490
+ function warnContradictoryNoPrerenderList(prerenderedPageContexts, doNotPrerenderList) {
491
+ Object.entries(prerenderedPageContexts).forEach(([pageId, pageContext]) => {
482
492
  const doNotPrerenderListEntry = doNotPrerenderList.find((p) => p.pageId === pageId);
483
493
  const { urlOriginal, _providedByHook: providedByHook } = pageContext;
484
494
  {
@@ -490,7 +500,7 @@ function warnContradictoryNoPrerenderList(prerenderPageIds, doNotPrerenderList)
490
500
  assertWarning(false, `The ${providedByHook.hookName}() hook defined by ${providedByHook.hookFilePath} returns the URL ${pc.cyan(urlOriginal)}, while ${setByConfigFile} sets the config ${pc.cyan(setByConfigName)} to ${pc.cyan(String(setByConfigValue))}. This is contradictory: either don't set the config ${pc.cyan(setByConfigName)} to ${pc.cyan(String(setByConfigValue))} or remove the URL ${pc.cyan(urlOriginal)} from the list of URLs to be pre-rendered.`, { onlyOnce: true });
491
501
  });
492
502
  }
493
- function warnMissingPages(prerenderPageIds, doNotPrerenderList, renderContext, partial) {
503
+ function warnMissingPages(prerenderedPageContexts, doNotPrerenderList, renderContext, partial) {
494
504
  const isV1 = renderContext.pageConfigs.length > 0;
495
505
  const hookName = isV1 ? 'onBeforePrerenderStart' : 'prerender';
496
506
  /* TODO/after-v1-design-release: document setting `prerender: false` as an alternative to using prerender.partial (both in the warnings and the docs)
@@ -498,7 +508,7 @@ function warnMissingPages(prerenderPageIds, doNotPrerenderList, renderContext, p
498
508
  const msgAddendum = `Explicitly opt-out by setting the config ${optOutName} to ${isV1 ? 'false' : 'true'} or use the option prerender.partial`
499
509
  */
500
510
  renderContext.allPageIds
501
- .filter((pageId) => !prerenderPageIds[pageId])
511
+ .filter((pageId) => !prerenderedPageContexts[pageId])
502
512
  .filter((pageId) => !doNotPrerenderList.find((p) => p.pageId === pageId))
503
513
  .filter((pageId) => !isErrorPage(pageId, renderContext.pageConfigs))
504
514
  .forEach((pageId) => {
@@ -506,8 +516,8 @@ function warnMissingPages(prerenderPageIds, doNotPrerenderList, renderContext, p
506
516
  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-config#partial) to suppress this warning.`, { onlyOnce: true });
507
517
  });
508
518
  }
509
- async function prerender404(htmlFiles, renderContext, prerenderContext) {
510
- if (!htmlFiles.find(({ urlOriginal }) => urlOriginal === '/404')) {
519
+ async function prerender404(prerenderedPageContexts, renderContext, prerenderContext, onComplete) {
520
+ if (!Object.values(prerenderedPageContexts).find(({ urlOriginal }) => urlOriginal === '/404')) {
511
521
  let result;
512
522
  try {
513
523
  result = await prerender404Page(renderContext, prerenderContext.pageContextInit);
@@ -519,7 +529,7 @@ async function prerender404(htmlFiles, renderContext, prerenderContext) {
519
529
  if (result) {
520
530
  const urlOriginal = '/404';
521
531
  const { documentHtml, pageContext } = result;
522
- htmlFiles.push({
532
+ await onComplete({
523
533
  urlOriginal,
524
534
  pageContext,
525
535
  htmlString: documentHtml,
@@ -530,59 +540,57 @@ async function prerender404(htmlFiles, renderContext, prerenderContext) {
530
540
  }
531
541
  }
532
542
  }
533
- async function writeHtmlFile({ urlOriginal, pageContext, htmlString, pageContextSerialized, doNotCreateExtraDirectory }, root, outDirClient, concurrencyLimit, onPagePrerender, logLevel) {
543
+ async function writeFiles({ urlOriginal, pageContext, htmlString, pageContextSerialized, doNotCreateExtraDirectory }, root, outDirClient, onPagePrerender, logLevel) {
534
544
  assert(urlOriginal.startsWith('/'));
535
545
  const writeJobs = [
536
- write(urlOriginal, pageContext, '.html', htmlString, root, outDirClient, doNotCreateExtraDirectory, concurrencyLimit, onPagePrerender, logLevel)
546
+ write(urlOriginal, pageContext, '.html', htmlString, root, outDirClient, doNotCreateExtraDirectory, onPagePrerender, logLevel)
537
547
  ];
538
548
  if (pageContextSerialized !== null) {
539
- writeJobs.push(write(urlOriginal, pageContext, '.pageContext.json', pageContextSerialized, root, outDirClient, doNotCreateExtraDirectory, concurrencyLimit, onPagePrerender, logLevel));
549
+ writeJobs.push(write(urlOriginal, pageContext, '.pageContext.json', pageContextSerialized, root, outDirClient, doNotCreateExtraDirectory, onPagePrerender, logLevel));
540
550
  }
541
551
  await Promise.all(writeJobs);
542
552
  }
543
- function write(urlOriginal, pageContext, fileExtension, fileContent, root, outDirClient, doNotCreateExtraDirectory, concurrencyLimit, onPagePrerender, logLevel) {
544
- return concurrencyLimit(async () => {
545
- let fileUrl;
546
- if (fileExtension === '.html') {
547
- fileUrl = urlToFile(urlOriginal, '.html', doNotCreateExtraDirectory);
548
- }
549
- else {
550
- fileUrl = getPageContextRequestUrl(urlOriginal);
551
- }
552
- assertPosixPath(fileUrl);
553
- assert(fileUrl.startsWith('/'));
554
- const filePathRelative = fileUrl.slice(1);
555
- assert(!filePathRelative.startsWith('/'));
556
- assertPosixPath(outDirClient);
557
- assertPosixPath(filePathRelative);
558
- const filePath = path.posix.join(outDirClient, filePathRelative);
559
- if (onPagePrerender) {
560
- const prerenderPageContext = {};
561
- objectAssign(prerenderPageContext, pageContext);
562
- objectAssign(prerenderPageContext, {
563
- _prerenderResult: {
564
- filePath,
565
- fileContent
566
- }
567
- });
568
- await onPagePrerender(prerenderPageContext);
569
- }
570
- else {
571
- const { promises } = await import('fs');
572
- const { writeFile, mkdir } = promises;
573
- await mkdir(path.posix.dirname(filePath), { recursive: true });
574
- await writeFile(filePath, fileContent);
575
- if (logLevel === 'info') {
576
- assertPosixPath(root);
577
- assertPosixPath(outDirClient);
578
- let outDirClientRelative = path.posix.relative(root, outDirClient);
579
- if (!outDirClientRelative.endsWith('/')) {
580
- outDirClientRelative = outDirClientRelative + '/';
581
- }
582
- console.log(`${pc.dim(outDirClientRelative)}${pc.blue(filePathRelative)}`);
553
+ async function write(urlOriginal, pageContext, fileExtension, fileContent, root, outDirClient, doNotCreateExtraDirectory, onPagePrerender, logLevel) {
554
+ let fileUrl;
555
+ if (fileExtension === '.html') {
556
+ fileUrl = urlToFile(urlOriginal, '.html', doNotCreateExtraDirectory);
557
+ }
558
+ else {
559
+ fileUrl = getPageContextRequestUrl(urlOriginal);
560
+ }
561
+ assertPosixPath(fileUrl);
562
+ assert(fileUrl.startsWith('/'));
563
+ const filePathRelative = fileUrl.slice(1);
564
+ assert(!filePathRelative.startsWith('/'));
565
+ assertPosixPath(outDirClient);
566
+ assertPosixPath(filePathRelative);
567
+ const filePath = path.posix.join(outDirClient, filePathRelative);
568
+ if (onPagePrerender) {
569
+ const prerenderPageContext = {};
570
+ objectAssign(prerenderPageContext, pageContext);
571
+ objectAssign(prerenderPageContext, {
572
+ _prerenderResult: {
573
+ filePath,
574
+ fileContent
583
575
  }
576
+ });
577
+ await onPagePrerender(prerenderPageContext);
578
+ }
579
+ else {
580
+ const { promises } = await import('fs');
581
+ const { writeFile, mkdir } = promises;
582
+ await mkdir(path.posix.dirname(filePath), { recursive: true });
583
+ await writeFile(filePath, fileContent);
584
+ if (logLevel === 'info') {
585
+ assertPosixPath(root);
586
+ assertPosixPath(outDirClient);
587
+ let outDirClientRelative = path.posix.relative(root, outDirClient);
588
+ if (!outDirClientRelative.endsWith('/')) {
589
+ outDirClientRelative = outDirClientRelative + '/';
590
+ }
591
+ console.log(`${pc.dim(outDirClientRelative)}${pc.blue(filePathRelative)}`);
584
592
  }
585
- });
593
+ }
586
594
  }
587
595
  function normalizeOnPrerenderHookResult(prerenderResult, prerenderHookFile, hookName) {
588
596
  if (Array.isArray(prerenderResult)) {
@@ -1,7 +1,7 @@
1
1
  export { injectAssets__public };
2
2
  import { assertUsage, assertWarning, castProp, hasProp } from '../../utils.js';
3
3
  import { injectHtmlTagsToString } from '../injectAssets.js';
4
- // TODO: remove this on next semver major
4
+ // TODO/v1-release: remove
5
5
  async function injectAssets__public(htmlString, pageContext) {
6
6
  assertWarning(false, '`_injectAssets()` is deprecated and will be removed.', { onlyOnce: true, showStackTrace: true });
7
7
  assertUsage(typeof htmlString === 'string', '[injectAssets(htmlString, pageContext)]: Argument `htmlString` should be a string.', { showStackTrace: true });
@@ -1,6 +1,7 @@
1
1
  export { renderPage } from './renderPage.js';
2
2
  export { escapeInject, dangerouslySkipEscape } from './html/renderHtml.js';
3
3
  export { pipeWebStream, pipeNodeStream, pipeStream, stampPipe } from './html/stream.js';
4
+ export { PROJECT_VERSION as version } from './utils.js';
4
5
  export { injectAssets__public as _injectAssets } from './html/injectAssets/injectAssets__public.js';
5
6
  export { createPageRenderer } from '../createPageRenderer.js';
6
7
  declare global {
@@ -1,6 +1,7 @@
1
1
  export { renderPage } from './renderPage.js';
2
2
  export { escapeInject, dangerouslySkipEscape } from './html/renderHtml.js';
3
3
  export { pipeWebStream, pipeNodeStream, pipeStream, stampPipe } from './html/stream.js';
4
+ export { PROJECT_VERSION as version } from './utils.js';
4
5
  // TODO/v1-release: remove
5
6
  export { injectAssets__public as _injectAssets } from './html/injectAssets/injectAssets__public.js';
6
7
  // TODO/v1-release: remove
@@ -29,8 +29,8 @@ function analyzePage(pageFilesAll, pageConfig, pageId) {
29
29
  if (configElement.importPath) {
30
30
  const { env } = configElement
31
31
  assert(env)
32
- const onlyAssets = env === 'server-only'
33
- const eagerlyImported = env === '_routing-eager'
32
+ const onlyAssets = env === { server: true }
33
+ const eagerlyImported = env === { server: true, client: 'if-client-routing', eager: true }
34
34
  if (onlyAssets || eagerlyImported) {
35
35
  clientDependencies.push({
36
36
  id: configElement.importPath,
@@ -1,2 +1,2 @@
1
1
  export { assertNoInfiniteHttpRedirect };
2
- declare function assertNoInfiniteHttpRedirect(urlRedirectOriginal: string, urlRedirectPathnameLogical: string): void;
2
+ declare function assertNoInfiniteHttpRedirect(urlRedirectTarget: string, urlLogical: string): void;
@@ -1,24 +1,24 @@
1
1
  export { assertNoInfiniteHttpRedirect };
2
- import { assert, assertUsage, getGlobalObject } from '../../utils.js';
2
+ import { assert, assertUsage, getGlobalObject, isUriWithProtocol } from '../../utils.js';
3
3
  import pc from '@brillout/picocolors';
4
4
  const globalObject = getGlobalObject('assertNoInfiniteHttpRedirect.ts', {
5
5
  redirectGraph: {}
6
6
  });
7
- function assertNoInfiniteHttpRedirect(urlRedirectOriginal, urlRedirectPathnameLogical) {
8
- if (urlRedirectOriginal.startsWith('http')) {
9
- // We assume that the redirect points to an external origin, and we can therefore assume that the app doesn't define an infinite loop (in itself).
10
- // - There isn't a reliable way to check whether the redirect points to an external origin or the same origin: the user usually passes the URL without origin.
7
+ function assertNoInfiniteHttpRedirect(urlRedirectTarget, urlLogical) {
8
+ if (isUriWithProtocol(urlRedirectTarget)) {
9
+ // We assume that urlRedirectTarget points to an origin that is external (not the same origin), and we can therefore assume that the app doesn't define an infinite loop (in itself).
10
+ // - There isn't a reliable way to check whether the redirect points to an external origin or the same origin. For same origins, we assume/hope the user to pass the URL without origin.
11
11
  // ```js
12
- // // URL origin is usually missing
12
+ // // For same-origin, the user usually/hopefully passes a URL without origin
13
13
  // renderPage({ urlOriginal: '/some/pathname' })
14
14
  // ```
15
15
  return;
16
16
  }
17
- assert(urlRedirectOriginal.startsWith('/'));
18
- assert(urlRedirectPathnameLogical.startsWith('/'));
17
+ assert(urlRedirectTarget.startsWith('/'));
18
+ assert(urlLogical.startsWith('/'));
19
19
  const graph = copy(globalObject.redirectGraph);
20
- graph[urlRedirectOriginal] ?? (graph[urlRedirectOriginal] = new Set());
21
- graph[urlRedirectOriginal].add(urlRedirectPathnameLogical);
20
+ graph[urlRedirectTarget] ?? (graph[urlRedirectTarget] = new Set());
21
+ graph[urlRedirectTarget].add(urlLogical);
22
22
  validate(graph);
23
23
  globalObject.redirectGraph = graph;
24
24
  }
@@ -26,6 +26,9 @@ function copy(G) {
26
26
  return Object.fromEntries(Object.entries(G).map(([key, val]) => [key, new Set(val)]));
27
27
  }
28
28
  // Adapted from: https://stackoverflow.com/questions/60904464/detect-cycle-in-directed-graph/60907076#60907076
29
+ function validate(G) {
30
+ Object.keys(G).forEach((n) => check(G, n, []));
31
+ }
29
32
  function check(G, n, path) {
30
33
  if (path.includes(n)) {
31
34
  const cycle = path.slice(path.indexOf(n)).concat(n);
@@ -33,6 +36,3 @@ function check(G, n, path) {
33
36
  }
34
37
  G[n]?.forEach((node) => check(G, node, [...path, n]));
35
38
  }
36
- function validate(G) {
37
- Object.keys(G).forEach((n) => check(G, n, []));
38
- }
@@ -25,4 +25,4 @@ declare function createHttpResponseObject(htmlRender: null | HtmlRender, renderH
25
25
  abortStatusCode?: AbortStatusCode;
26
26
  }): Promise<HttpResponse | null>;
27
27
  declare function createHttpResponsePageContextJson(pageContextSerialized: string): Promise<HttpResponse>;
28
- declare function createHttpResponseObjectRedirect({ url, statusCode }: UrlRedirect, urlPathnameLogical: string): HttpResponse;
28
+ declare function createHttpResponseObjectRedirect({ url, statusCode }: UrlRedirect, urlLogical: string): HttpResponse;
@@ -33,9 +33,9 @@ async function createHttpResponsePageContextJson(pageContextSerialized) {
33
33
  return httpResponse;
34
34
  }
35
35
  function createHttpResponseObjectRedirect({ url, statusCode },
36
- // The URL pathname we assume the redirect to be logically based on
37
- urlPathnameLogical) {
38
- assertNoInfiniteHttpRedirect(url, urlPathnameLogical);
36
+ // The URL we assume the redirect to be logically based on
37
+ urlLogical) {
38
+ assertNoInfiniteHttpRedirect(url, urlLogical);
39
39
  assert(url);
40
40
  assert(statusCode);
41
41
  assert(300 <= statusCode && statusCode <= 399);
@@ -9,8 +9,7 @@ import { assertHookReturnedObject } from '../../../shared/assertHookReturnedObje
9
9
  import { logRuntimeError } from './loggerRuntime.js';
10
10
  import pc from '@brillout/picocolors';
11
11
  async function executeOnRenderHtmlHook(pageContext) {
12
- const hookFound = getRenderHook(pageContext);
13
- const { renderHook, hookFn } = hookFound;
12
+ const { renderHook, hookFn } = getRenderHook(pageContext);
14
13
  objectAssign(pageContext, { _renderHook: renderHook });
15
14
  preparePageContextForUserConsumptionServerSide(pageContext);
16
15
  const hookReturnValue = await executeHook(() => hookFn(pageContext), renderHook.hookName, renderHook.hookFilePath);
@@ -7,7 +7,7 @@ import pc from '@brillout/picocolors';
7
7
  const streamDocs = 'See https://vike.dev/stream for more information.';
8
8
  function getHttpResponseBody(htmlRender, renderHook) {
9
9
  if (typeof htmlRender !== 'string') {
10
- assertUsage(false, getErrMsg(htmlRender, renderHook, 'body', `Use ${pc.cyan('pageContext.httpResponse.pipe()')} or ${pc.cyan('pageContext.httpResponse.getBody()')} instead`));
10
+ assertUsage(false, getErrMsg(htmlRender, renderHook, 'body', `Use ${pc.cyan('pageContext.httpResponse.pipe()')} instead`));
11
11
  }
12
12
  const body = htmlRender;
13
13
  return body;
@@ -2,7 +2,7 @@ export { renderPage };
2
2
  export { renderPage_addWrapper };
3
3
  import { getRenderContext, getPageContextInitEnhanced, renderPageAlreadyRouted } from './renderPage/renderPageAlreadyRouted.js';
4
4
  import { route } from '../../shared/route/index.js';
5
- import { assert, hasProp, objectAssign, isParsable, parseUrl, assertEnv, assertWarning, getGlobalObject, checkType, assertUsage, normalizeUrlPathname, removeBaseServer, modifyUrlPathname, prependBase, removeUrlOrigin, addUrlOrigin } from './utils.js';
5
+ import { assert, hasProp, objectAssign, isParsable, parseUrl, assertEnv, assertWarning, getGlobalObject, checkType, assertUsage, normalizeUrlPathname, removeBaseServer, modifyUrlPathname, prependBase, removeUrlOrigin, addUrlOrigin, createUrlFromComponents } from './utils.js';
6
6
  import { assertNoInfiniteAbortLoop, getPageContextFromAllRewrites, isAbortError, logAbortErrorHandled } from '../../shared/route/abort.js';
7
7
  import { getGlobalContext, initGlobalContext } from './globalContext.js';
8
8
  import { handlePageContextRequestUrl } from './renderPage/handlePageContextRequestUrl.js';
@@ -34,17 +34,17 @@ async function renderPage(pageContextInit) {
34
34
  assertArguments(...arguments);
35
35
  assert(hasProp(pageContextInit, 'urlOriginal', 'string'));
36
36
  assertEnv();
37
- if (skipRequest(pageContextInit.urlOriginal)) {
38
- const pageContextHttpReponseNull = getPageContextHttpResponseNull(pageContextInit);
39
- checkType(pageContextHttpReponseNull);
40
- return pageContextHttpReponseNull;
37
+ if (isIgnoredUrl(pageContextInit.urlOriginal)) {
38
+ const pageContextHttpResponseNull = getPageContextHttpResponseNull(pageContextInit);
39
+ checkType(pageContextHttpResponseNull);
40
+ return pageContextHttpResponseNull;
41
41
  }
42
42
  const httpRequestId = getRequestId();
43
- const urlToShowToUser = pageContextInit.urlOriginal;
44
- logHttpRequest(urlToShowToUser, httpRequestId);
43
+ const { urlOriginal } = pageContextInit;
44
+ logHttpRequest(urlOriginal, httpRequestId);
45
45
  globalObject.pendingRequestsCount++;
46
46
  const { pageContextReturn, onRequestDone } = await renderPage_wrapper(httpRequestId, () => renderPageAndPrepare(pageContextInit, httpRequestId));
47
- logHttpResponse(urlToShowToUser, httpRequestId, pageContextReturn);
47
+ logHttpResponse(urlOriginal, httpRequestId, pageContextReturn);
48
48
  globalObject.pendingRequestsCount--;
49
49
  onRequestDone();
50
50
  checkType(pageContextReturn);
@@ -54,8 +54,8 @@ async function renderPageAndPrepare(pageContextInit, httpRequestId) {
54
54
  // Invalid config
55
55
  const handleInvalidConfig = () => {
56
56
  logRuntimeInfo?.(pc.bold(pc.red("Couldn't load configuration: see error above.")), httpRequestId, 'error');
57
- const pageContextHttpReponseNull = getPageContextHttpResponseNull(pageContextInit);
58
- return pageContextHttpReponseNull;
57
+ const pageContextHttpResponseNull = getPageContextHttpResponseNull(pageContextInit);
58
+ return pageContextHttpResponseNull;
59
59
  };
60
60
  if (isConfigInvalid) {
61
61
  return handleInvalidConfig();
@@ -71,8 +71,8 @@ async function renderPageAndPrepare(pageContextInit, httpRequestId) {
71
71
  // initGlobalContext() and getRenderContext() don't call any user hooks => err isn't thrown from user code
72
72
  assert(!isAbortError(err));
73
73
  logRuntimeError(err, httpRequestId);
74
- const pageContextHttpReponseNull = getPageContextHttpResponseNullWithError(err, pageContextInit);
75
- return pageContextHttpReponseNull;
74
+ const pageContextHttpResponseNull = getPageContextHttpResponseNullWithError(err, pageContextInit);
75
+ return pageContextHttpResponseNull;
76
76
  }
77
77
  if (isConfigInvalid) {
78
78
  return handleInvalidConfig();
@@ -80,15 +80,23 @@ async function renderPageAndPrepare(pageContextInit, httpRequestId) {
80
80
  else {
81
81
  // From now on, renderContext.pageConfigs contains all the configuration data; getVikeConfig() isn't called anymore for this request
82
82
  }
83
+ // Check Base URL
84
+ {
85
+ const pageContextHttpResponse = checkBaseUrl(pageContextInit, httpRequestId);
86
+ if (pageContextHttpResponse)
87
+ return pageContextHttpResponse;
88
+ }
89
+ // Normalize URL
83
90
  {
84
- const pageContextHttpReponse = normalizeUrl(pageContextInit, httpRequestId);
85
- if (pageContextHttpReponse)
86
- return pageContextHttpReponse;
91
+ const pageContextHttpResponse = normalizeUrl(pageContextInit, httpRequestId);
92
+ if (pageContextHttpResponse)
93
+ return pageContextHttpResponse;
87
94
  }
95
+ // Permanent redirects (HTTP status code `301`)
88
96
  {
89
- const pageContextHttpReponse = getPermanentRedirect(pageContextInit, httpRequestId);
90
- if (pageContextHttpReponse)
91
- return pageContextHttpReponse;
97
+ const pageContextHttpResponse = getPermanentRedirect(pageContextInit, httpRequestId);
98
+ if (pageContextHttpResponse)
99
+ return pageContextHttpResponse;
92
100
  }
93
101
  return await renderPageAlreadyPrepared(pageContextInit, httpRequestId, renderContext, []);
94
102
  }
@@ -171,8 +179,8 @@ async function renderPageAlreadyPrepared(pageContextInit, httpRequestId, renderC
171
179
  if (!handled.pageContextReturn) {
172
180
  const pageContextAbort = errErrorPage._pageContextAbort;
173
181
  assertWarning(false, `Failed to render error page because ${pc.cyan(pageContextAbort._abortCall)} was called: make sure ${pc.cyan(pageContextAbort._abortCaller)} doesn't occur while the error page is being rendered.`, { onlyOnce: false });
174
- const pageContextHttpReponseNull = getPageContextHttpResponseNullWithError(errNominalPage, pageContextInit);
175
- return pageContextHttpReponseNull;
182
+ const pageContextHttpResponseNull = getPageContextHttpResponseNullWithError(errNominalPage, pageContextInit);
183
+ return pageContextHttpResponseNull;
176
184
  }
177
185
  // `throw redirect()` / `throw render(url)`
178
186
  return handled.pageContextReturn;
@@ -180,18 +188,28 @@ async function renderPageAlreadyPrepared(pageContextInit, httpRequestId, renderC
180
188
  if (isNewError(errErrorPage, errNominalPage)) {
181
189
  logRuntimeError(errErrorPage, httpRequestId);
182
190
  }
183
- const pageContextHttpReponseNull = getPageContextHttpResponseNullWithError(errNominalPage, pageContextInit);
184
- return pageContextHttpReponseNull;
191
+ const pageContextHttpResponseNull = getPageContextHttpResponseNullWithError(errNominalPage, pageContextInit);
192
+ return pageContextHttpResponseNull;
185
193
  }
186
194
  return pageContextErrorPage;
187
195
  }
188
196
  }
189
- function logHttpRequest(urlToShowToUser, httpRequestId) {
197
+ function logHttpRequest(urlOriginal, httpRequestId) {
190
198
  const clearErrors = globalObject.pendingRequestsCount === 0;
191
- logRuntimeInfo?.(`HTTP request: ${pc.bold(urlToShowToUser)}`, httpRequestId, 'info', clearErrors);
199
+ logRuntimeInfo?.(getRequestInfoMessage(urlOriginal), httpRequestId, 'info', clearErrors);
192
200
  }
193
- function logHttpResponse(urlToShowToUser, httpRequestId, pageContextReturn) {
201
+ function getRequestInfoMessage(urlOriginal) {
202
+ return `HTTP request: ${pc.bold(urlOriginal)}`;
203
+ }
204
+ function logHttpResponse(urlOriginal, httpRequestId, pageContextReturn) {
194
205
  const statusCode = pageContextReturn.httpResponse?.statusCode ?? null;
206
+ {
207
+ // If URL doesn't include Base URL
208
+ const { errorWhileRendering } = pageContextReturn;
209
+ const isSkipped = statusCode === null && (errorWhileRendering === null || errorWhileRendering === undefined);
210
+ if (isSkipped)
211
+ return;
212
+ }
195
213
  const isSuccess = statusCode !== null && statusCode >= 200 && statusCode <= 399;
196
214
  const isNominal = isSuccess || statusCode === 404;
197
215
  const color = (s) => pc.bold(isSuccess ? pc.green(String(s)) : pc.red(String(s)));
@@ -205,39 +223,30 @@ function logHttpResponse(urlToShowToUser, httpRequestId, pageContextReturn) {
205
223
  .find((header) => header[0] === 'Location');
206
224
  assert(headerRedirect);
207
225
  const urlRedirect = headerRedirect[1];
208
- urlToShowToUser = urlRedirect;
226
+ urlOriginal = urlRedirect;
209
227
  }
210
- logRuntimeInfo?.(`HTTP ${type} ${pc.bold(urlToShowToUser)} ${color(statusCode ?? 'ERR')}`, httpRequestId, isNominal ? 'info' : 'error');
228
+ logRuntimeInfo?.(`HTTP ${type} ${pc.bold(urlOriginal)} ${color(statusCode ?? 'ERR')}`, httpRequestId, isNominal ? 'info' : 'error');
211
229
  }
212
230
  function getPageContextHttpResponseNullWithError(err, pageContextInit) {
213
- const pageContextHttpReponseNull = {};
214
- objectAssign(pageContextHttpReponseNull, pageContextInit);
215
- objectAssign(pageContextHttpReponseNull, {
231
+ const pageContextHttpResponseNull = {};
232
+ objectAssign(pageContextHttpResponseNull, pageContextInit);
233
+ objectAssign(pageContextHttpResponseNull, {
216
234
  httpResponse: null,
217
235
  errorWhileRendering: err
218
236
  });
219
- return pageContextHttpReponseNull;
237
+ return pageContextHttpResponseNull;
220
238
  }
221
239
  function getPageContextHttpResponseNull(pageContextInit) {
222
- const pageContextHttpReponseNull = {};
223
- objectAssign(pageContextHttpReponseNull, pageContextInit);
224
- objectAssign(pageContextHttpReponseNull, {
240
+ const pageContextHttpResponseNull = {};
241
+ objectAssign(pageContextHttpResponseNull, pageContextInit);
242
+ objectAssign(pageContextHttpResponseNull, {
225
243
  httpResponse: null,
226
244
  errorWhileRendering: null
227
245
  });
228
- return pageContextHttpReponseNull;
246
+ return pageContextHttpResponseNull;
229
247
  }
230
248
  async function renderPageNominal(pageContext) {
231
249
  objectAssign(pageContext, { errorWhileRendering: null });
232
- // Check Base URL
233
- {
234
- const { urlWithoutPageContextRequestSuffix } = handlePageContextRequestUrl(pageContext.urlOriginal);
235
- const hasBaseServer = parseUrl(urlWithoutPageContextRequestSuffix, pageContext._baseServer).hasBaseServer || !!pageContext._urlRewrite;
236
- if (!hasBaseServer) {
237
- objectAssign(pageContext, { httpResponse: null });
238
- return pageContext;
239
- }
240
- }
241
250
  // Route
242
251
  {
243
252
  const pageContextFromRoute = await route(pageContext);
@@ -303,7 +312,7 @@ function getRequestId() {
303
312
  assert(httpRequestId >= 1);
304
313
  return httpRequestId;
305
314
  }
306
- function skipRequest(urlOriginal) {
315
+ function isIgnoredUrl(urlOriginal) {
307
316
  const isViteClientRequest = urlOriginal.endsWith('/@vite/client') || urlOriginal.startsWith('/@fs/');
308
317
  assertWarning(!isViteClientRequest, `The vike middleware renderPage() was called with the URL ${urlOriginal} which is unexpected because the HTTP request should have already been handled by Vite's development middleware. Make sure to 1. install Vite's development middleware and 2. add Vite's middleware *before* Vike's middleware, see https://vike.dev/renderPage`, { onlyOnce: true });
309
318
  return (urlOriginal.endsWith('/__vite_ping') ||
@@ -312,11 +321,11 @@ function skipRequest(urlOriginal) {
312
321
  isViteClientRequest);
313
322
  }
314
323
  function normalizeUrl(pageContextInit, httpRequestId) {
315
- const { trailingSlash, disableUrlNormalization } = getGlobalContext();
324
+ const { trailingSlash, disableUrlNormalization, baseServer } = getGlobalContext();
316
325
  if (disableUrlNormalization)
317
326
  return null;
318
327
  const { urlOriginal } = pageContextInit;
319
- const urlNormalized = normalizeUrlPathname(urlOriginal, trailingSlash);
328
+ const urlNormalized = normalizeUrlPathname(urlOriginal, trailingSlash, baseServer);
320
329
  if (!urlNormalized)
321
330
  return null;
322
331
  logRuntimeInfo?.(`URL normalized from ${pc.cyan(urlOriginal)} to ${pc.cyan(urlNormalized)} (https://vike.dev/url-normalization)`, httpRequestId, 'info');
@@ -327,10 +336,8 @@ function normalizeUrl(pageContextInit, httpRequestId) {
327
336
  function getPermanentRedirect(pageContextInit, httpRequestId) {
328
337
  const { redirects, baseServer } = getGlobalContext();
329
338
  const urlWithoutBase = removeBaseServer(pageContextInit.urlOriginal, baseServer);
330
- let urlOriginalPathnameWithouBase;
331
339
  let origin = null;
332
340
  let urlTarget = modifyUrlPathname(urlWithoutBase, (urlPathname) => {
333
- urlOriginalPathnameWithouBase = urlPathname;
334
341
  const urlTargetWithOrigin = resolveRedirects(redirects, urlPathname);
335
342
  if (urlTargetWithOrigin === null)
336
343
  return null;
@@ -340,13 +347,12 @@ function getPermanentRedirect(pageContextInit, httpRequestId) {
340
347
  });
341
348
  if (origin)
342
349
  urlTarget = addUrlOrigin(urlTarget, origin);
343
- assert(urlOriginalPathnameWithouBase);
344
350
  if (urlTarget === urlWithoutBase)
345
351
  return null;
346
352
  logRuntimeInfo?.(`Permanent redirect defined by your config.redirects (https://vike.dev/redirects)`, httpRequestId, 'info');
347
353
  urlTarget = prependBase(urlTarget, baseServer);
348
354
  assert(urlTarget !== pageContextInit.urlOriginal);
349
- const httpResponse = createHttpResponseObjectRedirect({ url: urlTarget, statusCode: 301 }, urlOriginalPathnameWithouBase);
355
+ const httpResponse = createHttpResponseObjectRedirect({ url: urlTarget, statusCode: 301 }, urlWithoutBase);
350
356
  const pageContextHttpResponse = { ...pageContextInit, httpResponse };
351
357
  return pageContextHttpResponse;
352
358
  }
@@ -390,10 +396,28 @@ async function handleAbortError(errAbort, pageContextsFromRewrite, pageContextIn
390
396
  ...pageContextInit,
391
397
  ...pageContextAbort
392
398
  };
393
- const httpResponse = createHttpResponseObjectRedirect(pageContextAbort._urlRedirect, pageContextNominalPageInit.urlPathname);
399
+ const httpResponse = createHttpResponseObjectRedirect(pageContextAbort._urlRedirect, (() => {
400
+ const { pathname, searchOriginal } = pageContextNominalPageInit.urlParsed;
401
+ const urlLogical = createUrlFromComponents(null, pathname, searchOriginal,
402
+ // The server-side doesn't have access to the hash
403
+ null);
404
+ return urlLogical;
405
+ })());
394
406
  objectAssign(pageContextReturn, { httpResponse });
395
407
  return { pageContextReturn };
396
408
  }
397
409
  assert(pageContextAbort.abortStatusCode);
398
410
  return { pageContextAbort };
399
411
  }
412
+ function checkBaseUrl(pageContextInit, httpRequestId) {
413
+ const { baseServer } = getGlobalContext();
414
+ const { urlOriginal } = pageContextInit;
415
+ const { urlWithoutPageContextRequestSuffix } = handlePageContextRequestUrl(urlOriginal);
416
+ const { hasBaseServer } = parseUrl(urlWithoutPageContextRequestSuffix, baseServer);
417
+ if (!hasBaseServer) {
418
+ logRuntimeInfo?.(`${getRequestInfoMessage(urlOriginal)} skipped because URL ${pc.bold(urlOriginal)} doesn't start with Base URL ${pc.bold(baseServer)} (https://vike.dev/base-url)`, httpRequestId, 'info');
419
+ const pageContextHttpResponseNull = getPageContextHttpResponseNull(pageContextInit);
420
+ return pageContextHttpResponseNull;
421
+ }
422
+ return null;
423
+ }