vike 0.4.267 → 0.4.268-commit-45c1759

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 (204) hide show
  1. package/RenderErrorPage.js +2 -2
  2. package/abort.js +2 -2
  3. package/dist/client/__internal/index.d.ts +2 -0
  4. package/dist/client/__internal/index.js +3 -0
  5. package/dist/client/runtime-client-routing/createPageContextClient.d.ts +5 -0
  6. package/dist/client/runtime-client-routing/getGlobalContextClientInternal.d.ts +5 -0
  7. package/dist/client/runtime-client-routing/getPageContextFromHooks.d.ts +26 -2
  8. package/dist/client/runtime-client-routing/getPageContextFromHooks.js +4 -5
  9. package/dist/client/runtime-client-routing/renderPageClient.d.ts +481 -10
  10. package/dist/client/runtime-client-routing/renderPageClient.js +116 -41
  11. package/dist/client/runtime-client-routing/streamedValues.d.ts +5 -0
  12. package/dist/client/runtime-client-routing/streamedValues.js +23 -0
  13. package/dist/client/runtime-server-routing/createPageContextClient.d.ts +5 -0
  14. package/dist/client/runtime-server-routing/entry.js +1 -1
  15. package/dist/client/runtime-server-routing/getGlobalContextClientInternal.d.ts +5 -0
  16. package/dist/client/shared/getGlobalContextClientInternalShared.d.ts +5 -0
  17. package/dist/client/shared/getGlobalContextClientInternalShared.js +2 -0
  18. package/dist/client/shared/getJsonSerializedInHtml.d.ts +2 -2
  19. package/dist/client/shared/getJsonSerializedInHtml.js +9 -6
  20. package/dist/client/shared/loadPageConfigsLazyClientSide.js +0 -4
  21. package/dist/client/shared/removeFoucBuster.js +14 -3
  22. package/dist/client/shared/streamedValues/asyncIterable.d.ts +4 -0
  23. package/dist/client/shared/streamedValues/asyncIterable.js +26 -0
  24. package/dist/client/shared/streamedValues/lines.d.ts +11 -0
  25. package/dist/client/shared/streamedValues/lines.js +19 -0
  26. package/dist/client/shared/streamedValues/promise.d.ts +4 -0
  27. package/dist/client/shared/streamedValues/promise.js +19 -0
  28. package/dist/client/shared/streamedValues/readableStream.d.ts +4 -0
  29. package/dist/client/shared/streamedValues/readableStream.js +44 -0
  30. package/dist/client/shared/streamedValues/registry.d.ts +21 -0
  31. package/dist/client/shared/streamedValues/registry.js +40 -0
  32. package/dist/client/shared/streamedValues.d.ts +7 -0
  33. package/dist/client/shared/streamedValues.js +82 -0
  34. package/dist/node/api/dev.js +15 -1
  35. package/dist/node/api/resolveViteConfigUser.js +2 -2
  36. package/dist/node/api/serverEntryDev.d.ts +10 -0
  37. package/dist/node/api/serverEntryDev.js +125 -0
  38. package/dist/node/createDevMiddleware.js +12 -0
  39. package/dist/node/prerender/resolvePrerenderConfig.d.ts +1 -1
  40. package/dist/node/prerender/resolvePrerenderConfig.js +4 -1
  41. package/dist/node/prerender/runPrerender.d.ts +18 -18
  42. package/dist/node/prerender/runPrerender.js +61 -16
  43. package/dist/node/vite/assertEnvVite.js +1 -1
  44. package/dist/node/vite/index.js +2 -0
  45. package/dist/node/vite/plugins/build/handleAssetsManifest.js +6 -2
  46. package/dist/node/vite/plugins/build/pluginBuildApp.js +25 -26
  47. package/dist/node/vite/plugins/build/pluginBuildConfig.d.ts +2 -2
  48. package/dist/node/vite/plugins/build/pluginBuildConfig.js +25 -17
  49. package/dist/node/vite/plugins/build/pluginDistFileNames.js +70 -50
  50. package/dist/node/vite/plugins/build/pluginEnvironmentEntries.d.ts +6 -0
  51. package/dist/node/vite/plugins/build/pluginEnvironmentEntries.js +71 -0
  52. package/dist/node/vite/plugins/build/pluginSuppressRollupWarning.js +19 -17
  53. package/dist/node/vite/plugins/pluginCommon.js +10 -7
  54. package/dist/node/vite/plugins/pluginDev/optimizeDeps.d.ts +2 -2
  55. package/dist/node/vite/plugins/pluginDev/optimizeDeps.js +6 -2
  56. package/dist/node/vite/plugins/pluginReplaceConstantsGlobalThis.js +6 -4
  57. package/dist/node/vite/plugins/pluginUniversalDeploy/getServerConfig.d.ts +3 -0
  58. package/dist/node/vite/plugins/pluginUniversalDeploy/getServerConfig.js +28 -2
  59. package/dist/node/vite/plugins/pluginUniversalDeploy/pluginServerEntryAlias.d.ts +1 -1
  60. package/dist/node/vite/plugins/pluginUniversalDeploy/pluginServerEntryAlias.js +22 -11
  61. package/dist/node/vite/plugins/pluginUniversalDeploy/pluginWrapServerFile.d.ts +4 -0
  62. package/dist/node/vite/plugins/pluginUniversalDeploy/pluginWrapServerFile.js +29 -0
  63. package/dist/node/vite/plugins/pluginUniversalDeploy.js +29 -5
  64. package/dist/node/vite/plugins/pluginVirtualFiles/generateVirtualFileGlobalEntry.d.ts +2 -1
  65. package/dist/node/vite/plugins/pluginVirtualFiles/generateVirtualFileGlobalEntry.js +29 -12
  66. package/dist/node/vite/plugins/pluginVirtualFiles/generateVirtualFileGlobalEntryWithOldDesign.js +3 -2
  67. package/dist/node/vite/plugins/pluginVirtualFiles/generateVirtualFilePageEntry.js +7 -7
  68. package/dist/node/vite/plugins/pluginVirtualFiles/getConfigValueSourcesRelevant.d.ts +10 -6
  69. package/dist/node/vite/plugins/pluginVirtualFiles/getConfigValueSourcesRelevant.js +5 -11
  70. package/dist/node/vite/plugins/pluginVirtualFiles.js +20 -0
  71. package/dist/node/vite/shared/addSsrMiddleware.js +11 -27
  72. package/dist/node/vite/shared/findPageFiles.d.ts +1 -1
  73. package/dist/node/vite/shared/findPageFiles.js +1 -11
  74. package/dist/node/vite/shared/getAssetsDir.d.ts +3 -2
  75. package/dist/node/vite/shared/getAssetsDir.js +3 -3
  76. package/dist/node/vite/shared/isViteCli.d.ts +3 -3
  77. package/dist/node/vite/shared/isViteCli.js +80 -84
  78. package/dist/node/vite/shared/isViteServerSide.js +2 -7
  79. package/dist/node/vite/shared/resolveVikeConfigInternal/metaBuiltIn.d.ts +6 -4
  80. package/dist/node/vite/shared/resolveVikeConfigInternal/metaBuiltIn.js +17 -6
  81. package/dist/node/vite/shared/resolveVikeConfigInternal/transpileAndExecuteFile.js +9 -2
  82. package/dist/node/vite/shared/resolveVikeConfigInternal.d.ts +5 -1
  83. package/dist/node/vite/shared/resolveVikeConfigInternal.js +86 -13
  84. package/dist/server/__internal/fetch-deprecated.d.ts +2 -0
  85. package/dist/server/__internal/fetch-deprecated.js +6 -0
  86. package/dist/server/__internal/fetch.d.ts +9 -0
  87. package/dist/server/__internal/fetch.js +5 -0
  88. package/dist/server/__internal/index.d.ts +4 -0
  89. package/dist/server/__internal/index.js +8 -0
  90. package/dist/server/createPageRenderer.d.ts +2 -2
  91. package/dist/server/createPageRenderer.js +2 -2
  92. package/dist/server/runtime/createDevMiddleware.js +3 -1
  93. package/dist/server/runtime/globalContext.d.ts +69 -10
  94. package/dist/server/runtime/globalContext.js +35 -2
  95. package/dist/server/runtime/index.d.ts +1 -1
  96. package/dist/server/runtime/index.js +1 -1
  97. package/dist/server/runtime/renderPageServer/analyzePage.js +3 -3
  98. package/dist/server/runtime/renderPageServer/createHttpResponse.d.ts +20 -9
  99. package/dist/server/runtime/renderPageServer/createHttpResponse.js +34 -21
  100. package/dist/server/runtime/renderPageServer/createPageContextServer.d.ts +13 -23
  101. package/dist/server/runtime/renderPageServer/csp.d.ts +2 -1
  102. package/dist/server/runtime/renderPageServer/csp.js +2 -1
  103. package/dist/server/runtime/renderPageServer/execHookOnError.js +1 -1
  104. package/dist/server/runtime/renderPageServer/execHookOnRenderHtml.d.ts +9 -0
  105. package/dist/server/runtime/renderPageServer/execHookOnRenderHtml.js +21 -9
  106. package/dist/server/runtime/renderPageServer/getHttpResponseBody.d.ts +2 -2
  107. package/dist/server/runtime/renderPageServer/getHttpResponseBody.js +19 -12
  108. package/dist/server/runtime/renderPageServer/getPageContextJson.d.ts +8 -0
  109. package/dist/server/runtime/renderPageServer/getPageContextJson.js +47 -0
  110. package/dist/server/runtime/renderPageServer/handleErrorWithoutErrorPage.d.ts +2 -0
  111. package/dist/server/runtime/renderPageServer/handleErrorWithoutErrorPage.js +1 -1
  112. package/dist/server/runtime/renderPageServer/handlePageContextRequestUrl.js +2 -2
  113. package/dist/server/runtime/renderPageServer/headersResponse.d.ts +11 -2
  114. package/dist/server/runtime/renderPageServer/headersResponse.js +22 -2
  115. package/dist/server/runtime/renderPageServer/html/injectAssets/getHtmlTags.js +5 -4
  116. package/dist/server/runtime/renderPageServer/html/injectAssets.d.ts +3 -2
  117. package/dist/server/runtime/renderPageServer/html/injectAssets.js +7 -1
  118. package/dist/server/runtime/renderPageServer/html/renderHtml.js +4 -2
  119. package/dist/server/runtime/renderPageServer/html/serializeContext.d.ts +5 -1
  120. package/dist/server/runtime/renderPageServer/html/serializeContext.js +12 -9
  121. package/dist/server/runtime/renderPageServer/html/stream.d.ts +13 -6
  122. package/dist/server/runtime/renderPageServer/html/stream.js +135 -32
  123. package/dist/server/runtime/renderPageServer/html/streamedValuesHtml.d.ts +30 -0
  124. package/dist/server/runtime/renderPageServer/html/streamedValuesHtml.js +92 -0
  125. package/dist/server/runtime/renderPageServer/loadPageConfigsLazyServerSide.d.ts +10 -14
  126. package/dist/server/runtime/renderPageServer/loadPageConfigsLazyServerSide.js +5 -1
  127. package/dist/server/runtime/renderPageServer/loadPageContextEnvironments.d.ts +15 -0
  128. package/dist/server/runtime/renderPageServer/loadPageContextEnvironments.js +61 -0
  129. package/dist/server/runtime/renderPageServer/renderPageServerAfterRoute.d.ts +320 -55
  130. package/dist/server/runtime/renderPageServer/renderPageServerAfterRoute.js +21 -12
  131. package/dist/server/runtime/renderPageServer/streamedValues/asyncIterable.d.ts +4 -0
  132. package/dist/server/runtime/renderPageServer/streamedValues/asyncIterable.js +12 -0
  133. package/dist/server/runtime/renderPageServer/streamedValues/lines.d.ts +10 -0
  134. package/dist/server/runtime/renderPageServer/streamedValues/lines.js +49 -0
  135. package/dist/server/runtime/renderPageServer/streamedValues/promise.d.ts +4 -0
  136. package/dist/server/runtime/renderPageServer/streamedValues/promise.js +14 -0
  137. package/dist/server/runtime/renderPageServer/streamedValues/pump.d.ts +10 -0
  138. package/dist/server/runtime/renderPageServer/streamedValues/pump.js +67 -0
  139. package/dist/server/runtime/renderPageServer/streamedValues/readableStream.d.ts +4 -0
  140. package/dist/server/runtime/renderPageServer/streamedValues/readableStream.js +12 -0
  141. package/dist/server/runtime/renderPageServer/streamedValues/registry.d.ts +28 -0
  142. package/dist/server/runtime/renderPageServer/streamedValues/registry.js +33 -0
  143. package/dist/server/runtime/renderPageServer.d.ts +65 -18
  144. package/dist/server/runtime/renderPageServer.js +33 -62
  145. package/dist/server/runtime/universal-middleware/core.d.ts +25 -0
  146. package/dist/server/runtime/universal-middleware/core.js +167 -0
  147. package/dist/server/runtime/universal-middleware/deprecated-export.d.ts +3 -0
  148. package/dist/server/runtime/universal-middleware/deprecated-export.js +10 -0
  149. package/dist/server/runtime/universal-middleware/getMiddlewaresPipe.d.ts +15 -0
  150. package/dist/server/runtime/universal-middleware/getMiddlewaresPipe.js +51 -0
  151. package/dist/server/runtime/universal-middleware/vikeUniversalMiddleware.d.ts +9 -0
  152. package/dist/server/runtime/universal-middleware/vikeUniversalMiddleware.js +22 -0
  153. package/dist/shared-server-client/createGlobalContextShared.d.ts +8 -0
  154. package/dist/shared-server-client/createGlobalContextShared.js +2 -1
  155. package/dist/shared-server-client/getPageContextPublicShared.js +0 -2
  156. package/dist/shared-server-client/getPageFiles/parseVirtualFileExportsGlobalEntry.d.ts +8 -0
  157. package/dist/shared-server-client/getPageFiles/parseVirtualFileExportsGlobalEntry.js +17 -7
  158. package/dist/shared-server-client/hooks/execHook.d.ts +1 -1
  159. package/dist/shared-server-client/hooks/execHook.js +2 -2
  160. package/dist/shared-server-client/page-configs/serialize/serializeConfigValues.js +2 -0
  161. package/dist/shared-server-client/route/abort.d.ts +1 -1
  162. package/dist/shared-server-client/route/abort.js +4 -2
  163. package/dist/shared-server-client/streamedValues.d.ts +22 -0
  164. package/dist/shared-server-client/streamedValues.js +24 -0
  165. package/dist/shared-server-node/vike-environments.d.ts +4 -0
  166. package/dist/shared-server-node/vike-environments.js +10 -0
  167. package/dist/shared-server-node/virtualFileId.d.ts +7 -5
  168. package/dist/shared-server-node/virtualFileId.js +42 -42
  169. package/dist/types/Config.d.ts +11 -3
  170. package/dist/types/GlobalContext.d.ts +3 -3
  171. package/dist/types/PageConfig.d.ts +13 -5
  172. package/dist/types/PageContext.d.ts +18 -10
  173. package/dist/types/PageContext.js +1 -0
  174. package/dist/types/Server.d.ts +1 -1
  175. package/dist/types/VikeNamespace.d.ts +1 -1
  176. package/dist/types/index.d.ts +1 -0
  177. package/dist/utils/PROJECT_VERSION.d.ts +1 -1
  178. package/dist/utils/PROJECT_VERSION.js +1 -1
  179. package/dist/utils/assertViteVersion.d.ts +1 -3
  180. package/dist/utils/assertViteVersion.js +6 -9
  181. package/dist/utils/catchInfiniteLoop.js +33 -11
  182. package/dist/utils/deepEqual.d.ts +2 -1
  183. package/dist/utils/deepEqual.js +21 -6
  184. package/dist/utils/getContentTypeFromUrl.d.ts +2 -0
  185. package/dist/utils/getContentTypeFromUrl.js +39 -0
  186. package/dist/utils/injectRollupInputs.d.ts +2 -2
  187. package/dist/utils/injectRollupInputs.js +2 -2
  188. package/dist/utils/installUncaughtErrorHandlers.js +9 -0
  189. package/dist/utils/isDev.js +2 -7
  190. package/dist/utils/parseUrl-extras.js +4 -0
  191. package/fetch.js +2 -2
  192. package/modifyUrl.js +2 -2
  193. package/package.json +42 -26
  194. package/routing.js +2 -2
  195. package/universal-middleware.js +2 -2
  196. package/vike-server.d.ts +14 -0
  197. package/dist/node/vite/plugins/pluginUniversalDeploy/pluginUnwrapProdOptions.d.ts +0 -4
  198. package/dist/node/vite/plugins/pluginUniversalDeploy/pluginUnwrapProdOptions.js +0 -22
  199. package/dist/server/runtime/fetch.d.ts +0 -10
  200. package/dist/server/runtime/fetch.js +0 -5
  201. package/dist/server/runtime/universal-middleware.d.ts +0 -10
  202. package/dist/server/runtime/universal-middleware.js +0 -27
  203. package/dist/shared-server-client/addIs404ToPageProps.d.ts +0 -2
  204. package/dist/shared-server-client/addIs404ToPageProps.js +0 -17
@@ -13,6 +13,7 @@ import { objectAssign } from '../../utils/objectAssign.js';
13
13
  import { redirectHard } from '../../utils/redirectHard.js';
14
14
  import { updateType } from '../../utils/updateType.js';
15
15
  import { getPageContextFromHooksClient, getPageContextFromHooksServer, getPageContextFromHooksClient_firstRender, getPageContextFromHooksServer_firstRender, setPageContextInitIsPassedToClient, } from './getPageContextFromHooks.js';
16
+ import { cancelStreamedValues } from './streamedValues.js';
16
17
  import { createPageContextClient } from './createPageContextClient.js';
17
18
  import { addLinkPrefetchHandlers, addLinkPrefetchHandlers_unwatch, addLinkPrefetchHandlers_watch, getPageContextPrefetched, populatePageContextPrefetchCache, } from './prefetch.js';
18
19
  import { execHookOnRenderClient } from '../shared/execHookOnRenderClient.js';
@@ -101,7 +102,7 @@ async function renderPageClient(renderArgs) {
101
102
  }
102
103
  // Get pageContext serialized in <script id="vike_pageContext" type="application/json">
103
104
  if (isFirstRender) {
104
- const pageContextSerialized = getPageContextFromHooksServer_firstRender();
105
+ const pageContextSerialized = await getPageContextFromHooksServer_firstRender();
105
106
  // TO-DO/eventually: create helper assertPageContextFromHook()
106
107
  assert(!('urlOriginal' in pageContextSerialized));
107
108
  objectAssign(pageContext, pageContextSerialized);
@@ -226,8 +227,10 @@ async function renderPageClient(renderArgs) {
226
227
  return;
227
228
  }
228
229
  }
229
- if (isRenderOutdated())
230
+ if (isRenderOutdated()) {
231
+ cancelStreamedValues(pageContextFromHooksServer, false);
230
232
  return;
233
+ }
231
234
  // TO-DO/eventually: create helper assertPageContextFromHook()
232
235
  assert(!('urlOriginal' in pageContextFromHooksServer));
233
236
  objectAssign(pageContext, pageContextFromHooksServer);
@@ -308,13 +311,6 @@ async function renderPageClient(renderArgs) {
308
311
  else {
309
312
  objectAssign(pageContext, { is404: false });
310
313
  }
311
- const isClientRoutable = await isClientSideRoutable(pageContext.pageId, pageContext);
312
- if (isRenderOutdated())
313
- return;
314
- if (!isClientRoutable) {
315
- redirectHard(urlOriginal);
316
- return;
317
- }
318
314
  if (import.meta.env.DEV || globalThis.__VIKE__IS_DEBUG) {
319
315
  assertInfo(false, `Rendering error page ${errorPageId}`, { onlyOnce: false });
320
316
  }
@@ -363,7 +359,7 @@ async function renderPageClient(renderArgs) {
363
359
  const errAbort = err;
364
360
  logAbort(err, !import.meta.env.DEV, pageContext);
365
361
  const pageContextAbort = errAbort._pageContextAbort;
366
- addNewPageContextAborted(pageContextsAborted, pageContext, pageContextAbort);
362
+ addNewPageContextAborted(pageContextsAborted, pageContext, pageContextAbort, getPageContextPublicClientMinimal);
367
363
  // throw render('/some-url')
368
364
  if (pageContextAbort._urlRewrite) {
369
365
  await renderPageClient({
@@ -447,6 +443,7 @@ async function renderPageClient(renderArgs) {
447
443
  // We purposely abort *after* onHydrationEnd() is called (see comment above).
448
444
  if (isRenderOutdated(true))
449
445
  return;
446
+ cancelStreamedValues(pageContext, true);
450
447
  // onPageTransitionEnd()
451
448
  if (globalObject.isTransitioning) {
452
449
  globalObject.isTransitioning = undefined;
@@ -491,7 +488,9 @@ async function renderPageClient(renderArgs) {
491
488
  }
492
489
  }
493
490
  async function getPageContextBegin(isForErrorPage, { urlOriginal, isBackwardNavigation, isHistoryNavigation, pageContextsAborted, isClientSideNavigation, pageContextInitClient, isFirstRender, }) {
494
- const previousPageContext = globalObject.previousPageContext ?? null;
491
+ const previousPageContext = globalObject.previousPageContext
492
+ ? getPageContextPublicClient(globalObject.previousPageContext)
493
+ : null;
495
494
  const pageContext = await createPageContextClient(urlOriginal);
496
495
  objectAssign(pageContext, {
497
496
  isBackwardNavigation,
@@ -527,21 +526,12 @@ function stampFinished(urlOriginal) {
527
526
  window._vike ?? (window._vike = {});
528
527
  window._vike.fullyRenderedUrl = urlOriginal;
529
528
  }
530
- function disableClientRouting(err, log) {
529
+ function disableClientRouting(err, logError) {
531
530
  globalObject.clientRoutingIsDisabled = true;
532
531
  assert(isErrorFetchingStaticAssets(err));
533
- if (log) {
534
- // We purposely don't use console.error() to avoid flooding error trackers such as Sentry
535
- console.log(err);
536
- }
537
- assertInfo(false, [
538
- 'Failed to fetch static asset.',
539
- import.meta.env.PROD ? 'This usually happens when a new frontend is deployed.' : null,
540
- 'Falling back to Server Routing.',
541
- '(The next page navigation will use Server Routing instead of Client Routing.)',
542
- ]
543
- .filter(Boolean)
544
- .join(' '), { onlyOnce: true });
532
+ if (logError)
533
+ console.log(err); // We purposely don't use console.error() to avoid flooding error trackers such as Sentry
534
+ assertInfo(false, 'Failed to fetch static asset (due to a connection issue, or a new deployment) — falling back to Server Routing', { onlyOnce: true });
545
535
  }
546
536
  function getIsRenderOutdated() {
547
537
  const renderNumber = ++globalObject.renderCounter;
@@ -581,7 +571,7 @@ function getKeepScrollPositionSetting(pageContext) {
581
571
  assert(configDefinedAt);
582
572
  const routeParameterList = getRouteStringParameterList(configDefinedAt);
583
573
  if (isCallable(val))
584
- val = val(pageContext, {
574
+ val = val(getPageContextPublicClient(pageContext), {
585
575
  configDefinedAt: c.definedAt,
586
576
  /* We don't pass routeParameterList because it's useless: the user knows the parameter list.
587
577
  routeParameterList
@@ -628,17 +618,14 @@ async function loadPageConfigsLazyClientSideAndExecHook(pageContext, isFirstRend
628
618
  catch (err_) {
629
619
  err = err_;
630
620
  hasErr = true;
631
- if (handleErrorFetchingStaticAssets(err, pageContext, isFirstRender)) {
632
- return { skip: true };
633
- }
634
- else {
635
- // Syntax error in user file
636
- }
637
621
  }
638
622
  if (isRenderOutdated())
639
623
  return { skip: true };
640
- if (hasErr)
624
+ if (hasErr) {
625
+ if (await handleErrorFetchingStaticAssets(err, pageContext, isFirstRender))
626
+ return { skip: true };
641
627
  return { err };
628
+ }
642
629
  objectAssign(pageContext, pageContextAddendum);
643
630
  try {
644
631
  await execHook('onCreatePageContext', pageContext, getPageContextPublicClient);
@@ -653,21 +640,109 @@ async function loadPageConfigsLazyClientSideAndExecHook(pageContext, isFirstRend
653
640
  return { err };
654
641
  return { pageContext };
655
642
  }
656
- function handleErrorFetchingStaticAssets(err, pageContext, isFirstRender) {
657
- if (!isErrorFetchingStaticAssets(err)) {
643
+ async function handleErrorFetchingStaticAssets(err, pageContext, isFirstRender) {
644
+ if (import.meta.env.DEV)
658
645
  return false;
659
- }
660
- if (isFirstRender) {
646
+ if (!isErrorFetchingStaticAssets(err))
647
+ return false; // Syntax error in user file
648
+ // *******************************************
649
+ // ******* The three possible actions ********
650
+ // *******************************************
651
+ /** Show Vike's error page */
652
+ const showErrorPage = () => {
661
653
  disableClientRouting(err, false);
662
- // This may happen if the frontend was newly deployed during hydration.
663
- // Ideally: re-try a couple of times by reloading the page (not entirely trivial to implement since `localStorage` is needed.)
654
+ // Vike handles the error like any other error: Vike logs it with `console.error()` and renders Vike's error page
655
+ return false;
656
+ };
657
+ /** Show the rendered HTML (with broken hydration) */
658
+ const showCurrentBrokenPage = () => {
659
+ disableClientRouting(err, false);
660
+ // Abort rendering (and don't show error page), not gracefully: the error throws (i.e. the error is handled by the browser and shown in the browser's developer console)
664
661
  throw err;
662
+ };
663
+ /** Do a full (re-)load of the page */
664
+ const hardReload = (url) => {
665
+ disableClientRouting(err, true);
666
+ if (url) {
667
+ redirectHard(url);
668
+ }
669
+ else {
670
+ // We use `location.reload()` instead of redirectHard(): navigating with `location.href = url` creates a `type: 'navigate'` entry, which would lead to an infinite reload loop — see isPageReload()
671
+ window.location.reload();
672
+ }
673
+ // Abort rendering (and don't show error page), gracefully (i.e. without throwing nor logging any error)
674
+ return true;
675
+ };
676
+ // **************************
677
+ // ******* The logic ********
678
+ // **************************
679
+ // Possible causes that lead to this point:
680
+ // - New deployment
681
+ // - Connection problem
682
+ // === Client-side navigation ===
683
+ // We hard load the next page:
684
+ // - New deployment => fully reloading the website is exactly what we want
685
+ // - Connection problem => next page isn't shown => only useful action is to try again with a hard reload
686
+ // - It's usually better to show the browser's offline page than to leave the user stuck on the old page. (This way, the user knows there's a connection problem instead of wondering whether the website is broken.)
687
+ if (!isFirstRender) {
688
+ return hardReload(pageContext.urlOriginal);
689
+ }
690
+ // === First render ===
691
+ // Avoid infinite reload loop: we don't reload a page that was itself loaded by a reload
692
+ if (isPageReload()) {
693
+ if (isBlankPage()) {
694
+ return showErrorPage();
695
+ }
696
+ else {
697
+ return showCurrentBrokenPage();
698
+ }
699
+ }
700
+ if (isBlankPage()) {
701
+ return hardReload();
665
702
  }
666
703
  else {
667
- disableClientRouting(err, true);
704
+ globalObject.clientRoutingIsDisabled = true; // Eagerly disable before connection check
705
+ if (!(await isConnectionDown())) {
706
+ // Most likely a new deployment (or the connection is back): either way, reloading fixes the page
707
+ return hardReload();
708
+ }
709
+ else {
710
+ // - Reloading is counterproductive since it would likely get another connection error, resulting in either: the browser's offline page, or repeating this asset loading failure.
711
+ // - Handling flaky connections is the browser's job (e.g. the user reloads the page)
712
+ // - Showing the rendered HTML is usually more useful to the user (even when unhydrated thus broken) than showing Vike's error page
713
+ return showCurrentBrokenPage();
714
+ }
668
715
  }
669
- redirectHard(pageContext.urlOriginal);
670
- return true;
716
+ }
717
+ // Whether fetching static assets fails because of the connection. (The error thrown by `import()` doesn't tell: it's the same whether a new frontend was deployed, i.e. the static assets don't exist anymore, or the connection is down.)
718
+ async function isConnectionDown() {
719
+ try {
720
+ await fetch(window.location.href, {
721
+ method: 'HEAD',
722
+ cache: 'no-store',
723
+ // On a flaky connection, the request may hang and succeed much later: we don't want to reload the page long after it was shown (e.g. while the user is filling a form)
724
+ signal: AbortSignal.timeout(4000),
725
+ });
726
+ // The server responds
727
+ return false;
728
+ }
729
+ catch {
730
+ return true;
731
+ }
732
+ }
733
+ // The page shows nothing (e.g. SPA)
734
+ function isBlankPage() {
735
+ return !document.body.innerText.trim();
736
+ }
737
+ // Whether the current page was loaded by a page reload
738
+ function isPageReload() {
739
+ // The browser records how the current document was loaded (Navigation Timing API)
740
+ const navigation = performance.getEntriesByType('navigation')[0];
741
+ return (
742
+ // Cannot be determined (e.g. older browsers)
743
+ !navigation ||
744
+ // A document loaded by `location.reload()` has `type: 'reload'`
745
+ navigation.type === 'reload');
671
746
  }
672
747
  // [HMR] If error page is shown => re-render whole page
673
748
  if (import.meta.env.DEV && import.meta.hot)
@@ -0,0 +1,5 @@
1
+ export { readPageContextJson };
2
+ export { cancelStreamedValues };
3
+ import '../assertEnvClient.js';
4
+ declare function readPageContextJson(response: Response): Promise<unknown>;
5
+ declare function cancelStreamedValues(pageContext: object, isRendered: boolean): void;
@@ -0,0 +1,23 @@
1
+ // Streamed pageContext values https://vike.dev/passToClient#streaming, upon client-side navigation: the decoder
2
+ // (../shared/streamedValues.ts) is loaded only if the `.pageContext.json` response is a JSON array (see
3
+ // server/runtime/renderPageServer/getPageContextJson.ts).
4
+ export { readPageContextJson };
5
+ export { cancelStreamedValues };
6
+ import { parse } from '@brillout/json-serializer/parse';
7
+ import '../assertEnvClient.js';
8
+ let decoder;
9
+ async function readPageContextJson(response) {
10
+ const reader = response.clone().body.getReader();
11
+ let chunk = await reader.read();
12
+ while (!chunk.done && !chunk.value.length)
13
+ chunk = await reader.read();
14
+ reader.cancel();
15
+ // A pageContext always serializes as `{…}`, so an array (`[` is 91) means streamed values
16
+ if (chunk.value?.[0] !== 91)
17
+ return parse(await response.text());
18
+ decoder ?? (decoder = await import('../shared/streamedValues.js'));
19
+ return decoder.readPageContextJsonStreamed(response);
20
+ }
21
+ function cancelStreamedValues(pageContext, isRendered) {
22
+ decoder?.cancelStreamedValues(pageContext, isRendered);
23
+ }
@@ -35,9 +35,14 @@ declare function createPageContextClient(): Promise<{
35
35
  _pageFilesAll: import("../../shared-server-client/getPageFiles.js").PageFile[];
36
36
  _pageConfigs: import("../../types/PageConfig.js").PageConfigRuntime[];
37
37
  _pageConfigGlobal: import("../../types/PageConfig.js").PageConfigGlobalRuntime;
38
+ _environmentEntries: Record<string, {
39
+ pageConfigs: import("../../types/PageConfig.js").PageConfigRuntime[];
40
+ pageConfigGlobal: import("../../types/PageConfig.js").PageConfigGlobalRuntime;
41
+ } | null>;
38
42
  _allPageIds: string[];
39
43
  } & {
40
44
  isClientSide: true;
45
+ devMiddleware: null;
41
46
  };
42
47
  _pageFilesAll: import("../../shared-server-client/getPageFiles.js").PageFile[];
43
48
  } & import("../../shared-server-client/page-configs/resolveVikeConfigPublic.js").GlobalConfigPublic>;
@@ -23,7 +23,7 @@ if (import.meta.env.DEV)
23
23
  hydrate();
24
24
  async function hydrate() {
25
25
  const pageContext = await createPageContextClient();
26
- objectAssign(pageContext, getPageContextSerializedInHtml());
26
+ objectAssign(pageContext, await getPageContextSerializedInHtml());
27
27
  // Sets pageContext.config using non-global configs — overrides the pageContext.config set using global configs at createPageContextClient()
28
28
  const pageContextAddendum = await loadPageConfigsLazyClientSide(pageContext.pageId, pageContext._pageFilesAll, pageContext._globalContext._pageConfigs, pageContext._globalContext._pageConfigGlobal);
29
29
  objectAssign(pageContext, pageContextAddendum);
@@ -25,7 +25,12 @@ declare function getGlobalContextClientInternal(): Promise<{
25
25
  _pageFilesAll: import("../../shared-server-client/getPageFiles.js").PageFile[];
26
26
  _pageConfigs: import("../../types/PageConfig.js").PageConfigRuntime[];
27
27
  _pageConfigGlobal: import("../../types/PageConfig.js").PageConfigGlobalRuntime;
28
+ _environmentEntries: Record<string, {
29
+ pageConfigs: import("../../types/PageConfig.js").PageConfigRuntime[];
30
+ pageConfigGlobal: import("../../types/PageConfig.js").PageConfigGlobalRuntime;
31
+ } | null>;
28
32
  _allPageIds: string[];
29
33
  } & {
30
34
  isClientSide: true;
35
+ devMiddleware: null;
31
36
  }>;
@@ -29,6 +29,10 @@ declare function getGlobalContextClientInternalShared(): Promise<{
29
29
  _pageFilesAll: import("../../shared-server-client/getPageFiles.js").PageFile[];
30
30
  _pageConfigs: import("../../types/PageConfig.js").PageConfigRuntime[];
31
31
  _pageConfigGlobal: import("../../types/PageConfig.js").PageConfigGlobalRuntime;
32
+ _environmentEntries: Record<string, {
33
+ pageConfigs: import("../../types/PageConfig.js").PageConfigRuntime[];
34
+ pageConfigGlobal: import("../../types/PageConfig.js").PageConfigGlobalRuntime;
35
+ } | null>;
32
36
  _allPageIds: string[];
33
37
  } & {
34
38
  /**
@@ -39,6 +43,7 @@ declare function getGlobalContextClientInternalShared(): Promise<{
39
43
  * https://vike.dev/globalContext#isClientSide
40
44
  */
41
45
  isClientSide: true;
46
+ devMiddleware: null;
42
47
  }>;
43
48
  type TypeIsNotExported = never;
44
49
  declare function getGlobalContext(): Promise<TypeIsNotExported>;
@@ -36,6 +36,8 @@ async function getGlobalContextClientInternalShared() {
36
36
  * https://vike.dev/globalContext#isClientSide
37
37
  */
38
38
  isClientSide: true,
39
+ // https://vike.dev/globalContext#devMiddleware
40
+ devMiddleware: null,
39
41
  };
40
42
  objectAssign(globalContextAddendum, getGlobalContextSerializedInHtml());
41
43
  return globalContextAddendum;
@@ -1,8 +1,8 @@
1
1
  export { getPageContextSerializedInHtml };
2
2
  export { getGlobalContextSerializedInHtml };
3
3
  import '../assertEnvClient.js';
4
- declare function getPageContextSerializedInHtml(): {
4
+ declare function getPageContextSerializedInHtml(): Promise<{
5
5
  pageId: string;
6
6
  routeParams: Record<string, string>;
7
- };
7
+ }>;
8
8
  declare function getGlobalContextSerializedInHtml(): object;
@@ -9,23 +9,26 @@ import '../assertEnvClient.js';
9
9
  // 1. <script id="vike_pageContext" type="application/json"> appears before the <script> that loads Vike's client runtime (which includes this file)
10
10
  // 2. <script id="vike_pageContext" type="application/json"> is neither async nor defer
11
11
  // See https://github.com/vikejs/vike/pull/1271
12
- function getPageContextSerializedInHtml() {
13
- const pageContextSerializedInHtml = findAndParseJson(htmlElementId_pageContext);
12
+ async function getPageContextSerializedInHtml() {
13
+ const pageContextJson = findJson(htmlElementId_pageContext);
14
+ // A pageContext always serializes as `{…}`, so an array means streamed values https://vike.dev/passToClient#streaming
15
+ const pageContextSerializedInHtml = pageContextJson[0] === '['
16
+ ? (await import('./streamedValues.js')).parsePageContextHtml(pageContextJson)
17
+ : parse(pageContextJson);
14
18
  assert(hasProp(pageContextSerializedInHtml, 'pageId', 'string'));
15
19
  assert(hasProp(pageContextSerializedInHtml, 'routeParams', 'string{}'));
16
20
  return pageContextSerializedInHtml;
17
21
  }
18
22
  function getGlobalContextSerializedInHtml() {
19
- const globalContextSerializedInHtml = findAndParseJson(htmlElementId_globalContext);
23
+ const globalContextSerializedInHtml = parse(findJson(htmlElementId_globalContext));
20
24
  return globalContextSerializedInHtml;
21
25
  }
22
- function findAndParseJson(id) {
26
+ function findJson(id) {
23
27
  const elem = document.getElementById(id);
24
28
  assertUsage(elem,
25
29
  // It seems like it can be missing when HTML is malformed: https://github.com/vikejs/vike/issues/913
26
30
  `Couldn't find #${id} (which Vike automatically injects in the HTML): make sure it exists (i.e. don't remove it and make sure your HTML isn't malformed)`);
27
31
  const jsonStr = elem.textContent;
28
32
  assert(jsonStr);
29
- const json = parse(jsonStr);
30
- return json;
33
+ return jsonStr;
31
34
  }
@@ -53,10 +53,6 @@ function isFetchError(err) {
53
53
  'error loading dynamically imported module',
54
54
  // safari
55
55
  'Importing a module script failed',
56
- // ??
57
- 'error resolving module specifier',
58
- // ??
59
- 'failed to resolve module',
60
56
  ];
61
57
  return FAILED_TO_FETCH_MESSAGES.some((s) => err.message.toLowerCase().includes(s.toLowerCase()));
62
58
  }
@@ -38,9 +38,20 @@ function clean() {
38
38
  const href = linkVike.getAttribute('href');
39
39
  assert(href && href.endsWith(suffix));
40
40
  let filePathAbsoluteUserRootDir = href.slice(0, -suffix.length);
41
- const prefix = '/@fs/';
42
- if (filePathAbsoluteUserRootDir.startsWith(prefix))
43
- filePathAbsoluteUserRootDir = filePathAbsoluteUserRootDir.slice(prefix.length);
41
+ const prefixFs = '/@fs/';
42
+ if (filePathAbsoluteUserRootDir.startsWith(prefixFs))
43
+ filePathAbsoluteUserRootDir = filePathAbsoluteUserRootDir.slice(prefixFs.length);
44
+ // CSS virtual module:
45
+ // ```js
46
+ // import 'virtual:some.css'
47
+ // ```
48
+ // ID becomes:
49
+ // ```
50
+ // <link href="/@id/__x00__virtual:some.css?direct" rel="stylesheet" type="text/css">
51
+ // ```
52
+ const prefixId = '/@id/';
53
+ if (filePathAbsoluteUserRootDir.startsWith(prefixId))
54
+ filePathAbsoluteUserRootDir = filePathAbsoluteUserRootDir.slice(prefixId.length).replace('__x00__', '\0');
44
55
  if (injectedByVite.some((filePathAbsoluteFilesystem) => filePathAbsoluteFilesystem.endsWith(filePathAbsoluteUserRootDir))) {
45
56
  linkVike.remove();
46
57
  }
@@ -0,0 +1,4 @@
1
+ export { asyncIterable };
2
+ import type { StreamedValueType } from './registry.js';
3
+ import '../../assertEnvClient.js';
4
+ declare const asyncIterable: StreamedValueType;
@@ -0,0 +1,26 @@
1
+ export { asyncIterable };
2
+ import { markers } from '../../../shared-server-client/streamedValues.js';
3
+ import { readableStream } from './readableStream.js';
4
+ import '../../assertEnvClient.js';
5
+ // A ReadableStream, consumed as an async iterable: `for await (const chunk of pageContext.someAsyncIterable)` (Safari's
6
+ // ReadableStream isn't async-iterable)
7
+ const asyncIterable = {
8
+ marker: markers.asyncIterable,
9
+ revive(parseValue) {
10
+ const streamedValue = readableStream.revive(parseValue);
11
+ return { ...streamedValue, value: toAsyncIterable(streamedValue.value) };
12
+ },
13
+ };
14
+ function toAsyncIterable(stream) {
15
+ const reader = stream.getReader();
16
+ const iterator = {
17
+ next: () => reader.read(),
18
+ // Called upon `break` in `for await`
19
+ async return(value) {
20
+ await reader.cancel();
21
+ return { done: true, value };
22
+ },
23
+ [Symbol.asyncIterator]: () => iterator,
24
+ };
25
+ return iterator;
26
+ }
@@ -0,0 +1,11 @@
1
+ export { decodeChunk };
2
+ export { getLineError };
3
+ import '../../assertEnvClient.js';
4
+ declare function decodeChunk(line: {
5
+ t: string;
6
+ } | {
7
+ b: string;
8
+ } | {
9
+ v: unknown;
10
+ }, parseValue: (value: unknown) => unknown): unknown;
11
+ declare function getLineError(): Error;
@@ -0,0 +1,19 @@
1
+ // The decoding of the lines (see shared-server-client/streamedValues.ts)
2
+ export { decodeChunk };
3
+ export { getLineError };
4
+ import '../../assertEnvClient.js';
5
+ const textEncoder = new TextEncoder();
6
+ function decodeChunk(line, parseValue) {
7
+ if ('t' in line)
8
+ return textEncoder.encode(line.t);
9
+ if ('b' in line)
10
+ return decodeBase64url(line.b);
11
+ return parseValue(line.v);
12
+ }
13
+ function getLineError() {
14
+ return new Error('A streamed pageContext value failed on the server-side (see the server logs)');
15
+ }
16
+ function decodeBase64url(str) {
17
+ const binary = atob(str.replaceAll('-', '+').replaceAll('_', '/'));
18
+ return Uint8Array.from(binary, (c) => c.charCodeAt(0));
19
+ }
@@ -0,0 +1,4 @@
1
+ export { promise };
2
+ import type { StreamedValueType } from './registry.js';
3
+ import '../../assertEnvClient.js';
4
+ declare const promise: StreamedValueType;
@@ -0,0 +1,19 @@
1
+ export { promise };
2
+ import { markers } from '../../../shared-server-client/streamedValues.js';
3
+ import { getLineError } from './lines.js';
4
+ import { genPromise } from '../../../utils/genPromise.js';
5
+ import '../../assertEnvClient.js';
6
+ // Settled by its `v` or `error` line
7
+ const promise = {
8
+ marker: markers.promise,
9
+ revive(parseValue) {
10
+ const { promise: value, resolve, reject } = genPromise({ timeout: null });
11
+ // Avoid an unhandled rejection if the user doesn't use the promise
12
+ value.catch(() => { });
13
+ return {
14
+ value,
15
+ push: (line) => ('v' in line ? resolve(parseValue(line.v)) : reject(getLineError())),
16
+ fail: reject,
17
+ };
18
+ },
19
+ };
@@ -0,0 +1,4 @@
1
+ export { readableStream };
2
+ import type { StreamedValueType } from './registry.js';
3
+ import '../../assertEnvClient.js';
4
+ declare const readableStream: StreamedValueType;
@@ -0,0 +1,44 @@
1
+ export { readableStream };
2
+ import { markers } from '../../../shared-server-client/streamedValues.js';
3
+ import { decodeChunk, getLineError } from './lines.js';
4
+ import '../../assertEnvClient.js';
5
+ // Fed by its chunk lines, until its `end` or `error` line
6
+ const readableStream = {
7
+ marker: markers.readableStream,
8
+ revive(parseValue) {
9
+ let controller;
10
+ let isClosed = false;
11
+ const value = new ReadableStream({
12
+ start(controller_) {
13
+ controller = controller_;
14
+ },
15
+ cancel() {
16
+ // Released by its consumer: the rest is ignored
17
+ isClosed = true;
18
+ },
19
+ });
20
+ const close = (err) => {
21
+ if (isClosed)
22
+ return;
23
+ isClosed = true;
24
+ if (err)
25
+ controller.error(err);
26
+ else
27
+ controller.close();
28
+ };
29
+ return {
30
+ value,
31
+ push(line) {
32
+ if (isClosed)
33
+ return;
34
+ if ('end' in line)
35
+ close();
36
+ else if ('error' in line)
37
+ close(getLineError());
38
+ else
39
+ controller.enqueue(decodeChunk(line, parseValue));
40
+ },
41
+ fail: close,
42
+ };
43
+ },
44
+ };
@@ -0,0 +1,21 @@
1
+ export { createReceiver };
2
+ export type { StreamedValueType };
3
+ import { type Reviver } from '@brillout/json-serializer/parse';
4
+ import type { Line } from '../../../shared-server-client/streamedValues.js';
5
+ import '../../assertEnvClient.js';
6
+ type StreamedValueType = {
7
+ marker: string;
8
+ /** `parseValue()` parses the value of a `v` line, which can contain further streamed values */
9
+ revive: (parseValue: (value: unknown) => unknown) => StreamedValue;
10
+ };
11
+ type StreamedValue = {
12
+ value: unknown;
13
+ push: (line: Line) => void;
14
+ fail: (err: unknown) => void;
15
+ };
16
+ declare function createReceiver(): {
17
+ reviver: Reviver;
18
+ onLine(lineStr: string): void;
19
+ /** The response failed, ended or was cancelled: the values that didn't end fail */
20
+ fail(err: unknown): void;
21
+ };
@@ -0,0 +1,40 @@
1
+ // The types of streamed pageContext values (see shared-server-client/streamedValues.ts), and the receiver: its reviver
2
+ // replaces the markers with values, which it then feeds with their lines.
3
+ export { createReceiver };
4
+ import { parseTransform } from '@brillout/json-serializer/parse';
5
+ import { assert } from '../../../utils/assert.js';
6
+ import { readableStream } from './readableStream.js';
7
+ import { promise } from './promise.js';
8
+ import { asyncIterable } from './asyncIterable.js';
9
+ import '../../assertEnvClient.js';
10
+ const types = [readableStream, promise, asyncIterable];
11
+ function createReceiver() {
12
+ const streamedValues = new Map();
13
+ const parseValue = (value) => parseTransform(value, { reviver });
14
+ const reviver = (_path, value) => {
15
+ const type = types.find((type) => value.startsWith(type.marker));
16
+ if (!type)
17
+ return undefined;
18
+ const id = value.slice(type.marker.length);
19
+ assert(/^\d+$/.test(id));
20
+ // The same value referenced twice
21
+ let streamedValue = streamedValues.get(Number(id));
22
+ if (!streamedValue) {
23
+ streamedValue = type.revive(parseValue);
24
+ streamedValues.set(Number(id), streamedValue);
25
+ }
26
+ return { replacement: streamedValue.value };
27
+ };
28
+ return {
29
+ reviver,
30
+ onLine(lineStr) {
31
+ const line = JSON.parse(lineStr);
32
+ // Unknown if contained in a chunk nobody read
33
+ streamedValues.get(line.s)?.push(line);
34
+ },
35
+ /** The response failed, ended or was cancelled: the values that didn't end fail */
36
+ fail(err) {
37
+ streamedValues.forEach((streamedValue) => streamedValue.fail(err));
38
+ },
39
+ };
40
+ }
@@ -0,0 +1,7 @@
1
+ export { parsePageContextHtml };
2
+ export { readPageContextJsonStreamed };
3
+ export { cancelStreamedValues };
4
+ import '../assertEnvClient.js';
5
+ declare function parsePageContextHtml(pageContextJson: string): unknown;
6
+ declare function readPageContextJsonStreamed(response: Response): Promise<Record<string, unknown>>;
7
+ declare function cancelStreamedValues(pageContext: object, isRendered: boolean): void;