vinext 0.1.2 → 0.1.3

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 (199) hide show
  1. package/dist/build/prerender.d.ts +9 -1
  2. package/dist/build/prerender.js +41 -12
  3. package/dist/build/run-prerender.d.ts +10 -2
  4. package/dist/build/run-prerender.js +15 -1
  5. package/dist/client/app-nav-failure-handler.d.ts +8 -0
  6. package/dist/client/app-nav-failure-handler.js +44 -0
  7. package/dist/client/vinext-next-data.d.ts +18 -1
  8. package/dist/client/window-next.d.ts +2 -1
  9. package/dist/client/window-next.js +12 -1
  10. package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
  11. package/dist/config/config-matchers.js +73 -14
  12. package/dist/config/next-config.d.ts +46 -4
  13. package/dist/config/next-config.js +147 -48
  14. package/dist/deploy.d.ts +30 -11
  15. package/dist/deploy.js +180 -99
  16. package/dist/entries/app-browser-entry.d.ts +9 -3
  17. package/dist/entries/app-browser-entry.js +21 -3
  18. package/dist/entries/app-rsc-entry.d.ts +2 -0
  19. package/dist/entries/app-rsc-entry.js +64 -5
  20. package/dist/entries/app-rsc-manifest.js +2 -0
  21. package/dist/entries/app-ssr-entry.js +1 -1
  22. package/dist/entries/pages-client-entry.js +53 -8
  23. package/dist/entries/pages-server-entry.js +41 -5
  24. package/dist/index.js +200 -62
  25. package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
  26. package/dist/plugins/extensionless-dynamic-import.js +152 -0
  27. package/dist/plugins/optimize-imports.d.ts +2 -1
  28. package/dist/plugins/optimize-imports.js +11 -9
  29. package/dist/plugins/postcss.js +7 -7
  30. package/dist/plugins/typeof-window.d.ts +14 -0
  31. package/dist/plugins/typeof-window.js +150 -0
  32. package/dist/routing/app-route-graph.d.ts +2 -1
  33. package/dist/routing/app-route-graph.js +44 -14
  34. package/dist/routing/file-matcher.d.ts +10 -1
  35. package/dist/routing/file-matcher.js +22 -1
  36. package/dist/routing/pages-router.js +3 -3
  37. package/dist/routing/utils.d.ts +35 -6
  38. package/dist/routing/utils.js +59 -7
  39. package/dist/server/api-handler.d.ts +6 -1
  40. package/dist/server/api-handler.js +21 -15
  41. package/dist/server/app-browser-action-result.d.ts +19 -6
  42. package/dist/server/app-browser-action-result.js +19 -10
  43. package/dist/server/app-browser-entry.js +167 -90
  44. package/dist/server/app-browser-error.d.ts +10 -6
  45. package/dist/server/app-browser-error.js +43 -8
  46. package/dist/server/app-browser-hydration.d.ts +2 -0
  47. package/dist/server/app-browser-hydration.js +1 -0
  48. package/dist/server/app-browser-navigation-controller.d.ts +4 -2
  49. package/dist/server/app-browser-navigation-controller.js +23 -2
  50. package/dist/server/app-browser-server-action-navigation.d.ts +6 -0
  51. package/dist/server/app-browser-server-action-navigation.js +9 -0
  52. package/dist/server/app-browser-stream.js +86 -43
  53. package/dist/server/app-elements-wire.d.ts +6 -1
  54. package/dist/server/app-elements-wire.js +14 -4
  55. package/dist/server/app-elements.d.ts +2 -2
  56. package/dist/server/app-elements.js +2 -2
  57. package/dist/server/app-fallback-renderer.d.ts +1 -0
  58. package/dist/server/app-fallback-renderer.js +3 -1
  59. package/dist/server/app-optimistic-routing.js +2 -2
  60. package/dist/server/app-page-boundary-render.d.ts +1 -0
  61. package/dist/server/app-page-boundary-render.js +27 -14
  62. package/dist/server/app-page-cache-render.d.ts +53 -0
  63. package/dist/server/app-page-cache-render.js +91 -0
  64. package/dist/server/app-page-cache.d.ts +16 -2
  65. package/dist/server/app-page-cache.js +62 -1
  66. package/dist/server/app-page-dispatch.d.ts +26 -0
  67. package/dist/server/app-page-dispatch.js +149 -92
  68. package/dist/server/app-page-element-builder.d.ts +1 -0
  69. package/dist/server/app-page-element-builder.js +5 -2
  70. package/dist/server/app-page-execution.d.ts +6 -1
  71. package/dist/server/app-page-execution.js +21 -1
  72. package/dist/server/app-page-probe.d.ts +1 -0
  73. package/dist/server/app-page-probe.js +4 -0
  74. package/dist/server/app-page-render-observation.d.ts +3 -1
  75. package/dist/server/app-page-render-observation.js +17 -1
  76. package/dist/server/app-page-render.d.ts +12 -1
  77. package/dist/server/app-page-render.js +42 -4
  78. package/dist/server/app-page-request.d.ts +2 -0
  79. package/dist/server/app-page-request.js +2 -1
  80. package/dist/server/app-page-route-wiring.d.ts +3 -1
  81. package/dist/server/app-page-route-wiring.js +14 -5
  82. package/dist/server/app-page-stream.d.ts +15 -3
  83. package/dist/server/app-page-stream.js +11 -5
  84. package/dist/server/app-pages-bridge.d.ts +18 -0
  85. package/dist/server/app-pages-bridge.js +22 -5
  86. package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
  87. package/dist/server/app-ppr-fallback-shell-render.js +26 -0
  88. package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
  89. package/dist/server/app-ppr-fallback-shell.js +8 -1
  90. package/dist/server/app-route-handler-dispatch.js +9 -2
  91. package/dist/server/app-route-handler-policy.d.ts +1 -0
  92. package/dist/server/app-router-entry.js +5 -0
  93. package/dist/server/app-rsc-cache-busting.js +2 -0
  94. package/dist/server/app-rsc-handler.d.ts +25 -0
  95. package/dist/server/app-rsc-handler.js +154 -54
  96. package/dist/server/app-rsc-route-matching.d.ts +3 -0
  97. package/dist/server/app-rsc-route-matching.js +2 -0
  98. package/dist/server/app-segment-config.d.ts +9 -1
  99. package/dist/server/app-segment-config.js +12 -3
  100. package/dist/server/app-server-action-execution.d.ts +1 -0
  101. package/dist/server/app-server-action-execution.js +42 -13
  102. package/dist/server/app-ssr-entry.d.ts +2 -0
  103. package/dist/server/app-ssr-entry.js +83 -10
  104. package/dist/server/cache-control.js +4 -0
  105. package/dist/server/dev-server.d.ts +2 -2
  106. package/dist/server/dev-server.js +244 -51
  107. package/dist/server/hybrid-route-priority.d.ts +22 -0
  108. package/dist/server/hybrid-route-priority.js +33 -0
  109. package/dist/server/image-optimization.d.ts +18 -9
  110. package/dist/server/image-optimization.js +37 -23
  111. package/dist/server/implicit-tags.d.ts +2 -1
  112. package/dist/server/implicit-tags.js +4 -1
  113. package/dist/server/navigation-planner.d.ts +133 -30
  114. package/dist/server/navigation-planner.js +114 -0
  115. package/dist/server/navigation-trace.d.ts +8 -1
  116. package/dist/server/navigation-trace.js +8 -1
  117. package/dist/server/pages-api-route.d.ts +6 -0
  118. package/dist/server/pages-api-route.js +13 -2
  119. package/dist/server/pages-asset-tags.d.ts +2 -1
  120. package/dist/server/pages-asset-tags.js +6 -2
  121. package/dist/server/pages-data-route.d.ts +8 -1
  122. package/dist/server/pages-data-route.js +11 -2
  123. package/dist/server/pages-get-initial-props.d.ts +54 -4
  124. package/dist/server/pages-get-initial-props.js +43 -1
  125. package/dist/server/pages-node-compat.js +2 -2
  126. package/dist/server/pages-page-data.d.ts +11 -2
  127. package/dist/server/pages-page-data.js +204 -33
  128. package/dist/server/pages-page-handler.d.ts +4 -2
  129. package/dist/server/pages-page-handler.js +59 -22
  130. package/dist/server/pages-page-response.d.ts +2 -1
  131. package/dist/server/pages-page-response.js +7 -4
  132. package/dist/server/pages-request-pipeline.d.ts +1 -0
  133. package/dist/server/pages-request-pipeline.js +73 -36
  134. package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
  135. package/dist/server/pregenerated-concrete-paths.js +2 -19
  136. package/dist/server/prerender-manifest.d.ts +33 -0
  137. package/dist/server/prerender-manifest.js +54 -0
  138. package/dist/server/prerender-route-params.d.ts +1 -2
  139. package/dist/server/prod-server.js +9 -3
  140. package/dist/server/request-pipeline.d.ts +3 -15
  141. package/dist/server/request-pipeline.js +58 -47
  142. package/dist/server/rsc-stream-hints.d.ts +5 -1
  143. package/dist/server/rsc-stream-hints.js +6 -1
  144. package/dist/server/seed-cache.js +10 -18
  145. package/dist/shims/app-router-scroll-state.d.ts +3 -1
  146. package/dist/shims/app-router-scroll-state.js +14 -2
  147. package/dist/shims/app-router-scroll.d.ts +3 -0
  148. package/dist/shims/app-router-scroll.js +28 -18
  149. package/dist/shims/cache-runtime.js +3 -2
  150. package/dist/shims/cache.d.ts +1 -0
  151. package/dist/shims/cache.js +1 -1
  152. package/dist/shims/cdn-cache.d.ts +5 -5
  153. package/dist/shims/dynamic-preload-chunks.js +6 -4
  154. package/dist/shims/error-boundary.d.ts +2 -0
  155. package/dist/shims/error-boundary.js +7 -0
  156. package/dist/shims/error.js +3 -2
  157. package/dist/shims/error.react-server.d.ts +9 -0
  158. package/dist/shims/error.react-server.js +6 -0
  159. package/dist/shims/fetch-cache.d.ts +3 -1
  160. package/dist/shims/fetch-cache.js +45 -20
  161. package/dist/shims/hash-scroll.js +6 -1
  162. package/dist/shims/headers.js +29 -4
  163. package/dist/shims/internal/als-registry.js +28 -1
  164. package/dist/shims/internal/app-route-detection.js +8 -17
  165. package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
  166. package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
  167. package/dist/shims/internal/navigation-untracked.d.ts +35 -0
  168. package/dist/shims/internal/navigation-untracked.js +55 -0
  169. package/dist/shims/internal/pages-data-target.d.ts +7 -2
  170. package/dist/shims/internal/pages-data-target.js +17 -8
  171. package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
  172. package/dist/shims/internal/pages-router-accessor.js +13 -0
  173. package/dist/shims/internal/router-context.d.ts +2 -1
  174. package/dist/shims/internal/router-context.js +3 -1
  175. package/dist/shims/link.js +12 -5
  176. package/dist/shims/navigation.d.ts +8 -2
  177. package/dist/shims/navigation.js +61 -31
  178. package/dist/shims/ppr-fallback-shell.d.ts +5 -1
  179. package/dist/shims/ppr-fallback-shell.js +28 -7
  180. package/dist/shims/router.d.ts +13 -2
  181. package/dist/shims/router.js +419 -128
  182. package/dist/shims/server.d.ts +16 -1
  183. package/dist/shims/server.js +44 -12
  184. package/dist/shims/unified-request-context.js +1 -0
  185. package/dist/utils/built-asset-url.d.ts +4 -0
  186. package/dist/utils/built-asset-url.js +11 -0
  187. package/dist/utils/commonjs-loader.d.ts +16 -0
  188. package/dist/utils/commonjs-loader.js +100 -0
  189. package/dist/utils/deployment-id.d.ts +8 -0
  190. package/dist/utils/deployment-id.js +22 -0
  191. package/dist/utils/html-limited-bots.d.ts +18 -1
  192. package/dist/utils/html-limited-bots.js +23 -1
  193. package/dist/utils/parse-cookie.d.ts +13 -0
  194. package/dist/utils/parse-cookie.js +52 -0
  195. package/dist/utils/path.d.ts +7 -1
  196. package/dist/utils/path.js +9 -1
  197. package/package.json +2 -2
  198. package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
  199. package/dist/shims/internal/parse-cookie-header.js +0 -30
@@ -88,8 +88,7 @@ function resolveAppPageSegmentConfig(options) {
88
88
  }
89
89
  if (config.dynamicConfig === "force-dynamic") config.revalidateSeconds = 0;
90
90
  if (config.fetchCache === void 0) {
91
- if (config.dynamicConfig === "force-dynamic") config.fetchCache = "force-no-store";
92
- else if (config.dynamicConfig === "error") config.fetchCache = "only-cache";
91
+ if (config.dynamicConfig === "error") config.fetchCache = "only-cache";
93
92
  }
94
93
  if (config.dynamicParamsConfig === void 0 && (config.dynamicConfig === "error" || config.dynamicConfig === "force-static")) config.dynamicParamsConfig = false;
95
94
  return config;
@@ -97,8 +96,18 @@ function resolveAppPageSegmentConfig(options) {
97
96
  function resolveAppPageFetchCacheMode(options) {
98
97
  return resolveAppPageSegmentConfig(options).fetchCache ?? null;
99
98
  }
99
+ /**
100
+ * Resolve the `fetchCache` segment config exported by a route handler module.
101
+ *
102
+ * Route handlers have no layout chain, so the module's own export applies
103
+ * directly. Mirrors upstream's app-route module, which copies
104
+ * `userland.fetchCache` into the work store before invoking the handler.
105
+ */
106
+ function resolveAppRouteHandlerFetchCacheMode(handler) {
107
+ return isRouteSegmentFetchCache(handler.fetchCache) ? handler.fetchCache : null;
108
+ }
100
109
  function isEdgeRuntime(runtime) {
101
110
  return isEdgeApiRuntime(runtime);
102
111
  }
103
112
  //#endregion
104
- export { isEdgeRuntime, resolveAppPageFetchCacheMode, resolveAppPageSegmentConfig };
113
+ export { isEdgeRuntime, resolveAppPageFetchCacheMode, resolveAppPageSegmentConfig, resolveAppRouteHandlerFetchCacheMode };
@@ -173,6 +173,7 @@ type HandleServerActionRscRequestOptions<TElement, TRoute extends AppServerActio
173
173
  renderToReadableStream: (model: AppServerActionRscModel<TElement>, options: RenderServerActionRscStreamOptions<TTemporaryReferences>) => BodyInit | null | Promise<BodyInit | null>;
174
174
  reportRequestError: AppServerActionErrorReporter;
175
175
  resolveRouteFetchCacheMode?: (route: TRoute) => FetchCacheMode | null;
176
+ resolveRouteDynamicConfig?: (route: TRoute) => string | null | undefined;
176
177
  resolveRouteRuntime?: (route: TRoute) => AppServerActionRouteRuntime;
177
178
  request: Request;
178
179
  sanitizeErrorForClient: (error: unknown) => unknown;
@@ -7,7 +7,7 @@ import { validateCsrfOrigin, validateServerActionPayload } from "./request-pipel
7
7
  import { headersContextFromRequest, setHeadersContext } from "../shims/headers.js";
8
8
  import { getAndClearActionRevalidationKind } from "../shims/cache.js";
9
9
  import { APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI } from "./app-rsc-render-mode.js";
10
- import { setCurrentFetchCacheMode, setCurrentFetchSoftTags } from "../shims/fetch-cache.js";
10
+ import { setCurrentFetchCacheMode, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault } from "../shims/fetch-cache.js";
11
11
  import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
12
12
  import { readStreamAsTextWithLimit } from "../utils/text-stream.js";
13
13
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
@@ -15,9 +15,9 @@ import { applyEdgeRuntimeHeader } from "./app-page-response.js";
15
15
  import { getNextErrorDigest, parseNextHttpErrorDigest, parseNextRedirectDigest } from "./next-error-digest.js";
16
16
  import { createServerActionNotFoundResponse, getServerActionNotFoundMessage, isServerActionNotFoundError } from "./server-action-not-found.js";
17
17
  import { deferUntilStreamConsumed } from "./app-page-stream.js";
18
+ import { buildAppPageTags } from "./implicit-tags.js";
18
19
  import { resolveAppPageNavigationParams } from "./app-page-element-builder.js";
19
20
  import { resolveAppPageActionRerenderTarget } from "./app-page-request.js";
20
- import { buildPageCacheTags } from "./implicit-tags.js";
21
21
  import { getSetCookieName } from "./cookie-utils.js";
22
22
  //#region src/server/app-server-action-execution.ts
23
23
  /**
@@ -46,6 +46,10 @@ function resolveActionRevalidationKind(hasModifiedCookies) {
46
46
  if (hasModifiedCookies) return ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC;
47
47
  return revalidationKind;
48
48
  }
49
+ function clearRejectedActionSideEffects(getAndClearPendingCookies) {
50
+ getAndClearPendingCookies();
51
+ getAndClearActionRevalidationKind();
52
+ }
49
53
  function cloneActionRedirectHeaders(requestHeaders) {
50
54
  const headers = new Headers(requestHeaders);
51
55
  for (const header of ACTION_REDIRECT_RENDER_STRIPPED_HEADERS) headers.delete(header);
@@ -233,7 +237,7 @@ function applyActionRedirectBasePath(url, basePath) {
233
237
  return `${addBasePathToPathname(pathname, basePath)}${suffix}`;
234
238
  }
235
239
  function buildServerActionPageTags(route, pathname) {
236
- return buildPageCacheTags(pathname, [], [...route.routeSegments ?? []], "page");
240
+ return buildAppPageTags(pathname, [], route.routeSegments ?? []);
237
241
  }
238
242
  function resolveInternalActionRedirectTarget(redirectUrl, requestUrl, basePath) {
239
243
  if (isExternalUrl(redirectUrl)) {
@@ -331,6 +335,7 @@ async function handleProgressiveServerActionRequest(options) {
331
335
  }
332
336
  const payloadResponse = await validateServerActionPayload(body);
333
337
  if (payloadResponse) {
338
+ clearRejectedActionSideEffects(options.getAndClearPendingCookies);
334
339
  options.clearRequestContext();
335
340
  return payloadResponse;
336
341
  }
@@ -482,6 +487,24 @@ async function handleServerActionRscRequest(options) {
482
487
  if (csrfResponse) return csrfResponse;
483
488
  if (parseInt(options.request.headers.get("content-length") || "0", 10) > options.maxActionBodySize) return renderFetchActionBodyExceededResponse(options);
484
489
  try {
490
+ let action;
491
+ if (options.contentType.startsWith("multipart/form-data")) {
492
+ let loadedAction;
493
+ try {
494
+ loadedAction = await options.loadServerAction(options.actionId);
495
+ } catch (error) {
496
+ if (isServerActionNotFoundError(error, options.actionId)) return createActionNotFoundResponse(options.actionId, {
497
+ clearRequestContext: options.clearRequestContext,
498
+ getAndClearPendingCookies: options.getAndClearPendingCookies
499
+ });
500
+ throw error;
501
+ }
502
+ if (!isAppServerActionFunction(loadedAction)) return createActionNotFoundResponse(options.actionId, {
503
+ clearRequestContext: options.clearRequestContext,
504
+ getAndClearPendingCookies: options.getAndClearPendingCookies
505
+ });
506
+ action = loadedAction;
507
+ }
485
508
  let body;
486
509
  try {
487
510
  body = options.contentType.startsWith("multipart/form-data") ? await options.readFormDataWithLimit(options.request, options.maxActionBodySize) : await options.readBodyWithLimit(options.request, options.maxActionBodySize);
@@ -491,23 +514,27 @@ async function handleServerActionRscRequest(options) {
491
514
  }
492
515
  const payloadResponse = await validateServerActionPayload(body);
493
516
  if (payloadResponse) {
517
+ clearRejectedActionSideEffects(options.getAndClearPendingCookies);
494
518
  options.clearRequestContext();
495
519
  return payloadResponse;
496
520
  }
497
- let action;
498
- try {
499
- action = await options.loadServerAction(options.actionId);
500
- } catch (error) {
501
- if (isServerActionNotFoundError(error, options.actionId)) return createActionNotFoundResponse(options.actionId, {
521
+ if (action === void 0) {
522
+ let loadedAction;
523
+ try {
524
+ loadedAction = await options.loadServerAction(options.actionId);
525
+ } catch (error) {
526
+ if (isServerActionNotFoundError(error, options.actionId)) return createActionNotFoundResponse(options.actionId, {
527
+ clearRequestContext: options.clearRequestContext,
528
+ getAndClearPendingCookies: options.getAndClearPendingCookies
529
+ });
530
+ throw error;
531
+ }
532
+ if (!isAppServerActionFunction(loadedAction)) return createActionNotFoundResponse(options.actionId, {
502
533
  clearRequestContext: options.clearRequestContext,
503
534
  getAndClearPendingCookies: options.getAndClearPendingCookies
504
535
  });
505
- throw error;
536
+ action = loadedAction;
506
537
  }
507
- if (!isAppServerActionFunction(action)) return createActionNotFoundResponse(options.actionId, {
508
- clearRequestContext: options.clearRequestContext,
509
- getAndClearPendingCookies: options.getAndClearPendingCookies
510
- });
511
538
  const temporaryReferences = options.createTemporaryReferenceSet();
512
539
  const args = await options.decodeReply(body, { temporaryReferences });
513
540
  let returnValue;
@@ -599,6 +626,7 @@ async function handleServerActionRscRequest(options) {
599
626
  params: redirectNavigationParams
600
627
  });
601
628
  setCurrentFetchCacheMode(options.resolveRouteFetchCacheMode?.(targetMatch.route) ?? null);
629
+ setCurrentForceDynamicFetchDefault(options.resolveRouteDynamicConfig?.(targetMatch.route) === "force-dynamic");
602
630
  setCurrentFetchSoftTags(buildServerActionPageTags(targetMatch.route, targetPathname));
603
631
  const element = options.buildPageElement({
604
632
  cleanPathname: targetPathname,
@@ -677,6 +705,7 @@ async function handleServerActionRscRequest(options) {
677
705
  });
678
706
  await options.ensureRouteLoaded?.(actionRerenderTarget.route);
679
707
  setCurrentFetchCacheMode(options.resolveRouteFetchCacheMode?.(actionRerenderTarget.route) ?? null);
708
+ setCurrentForceDynamicFetchDefault(options.resolveRouteDynamicConfig?.(actionRerenderTarget.route) === "force-dynamic");
680
709
  setCurrentFetchSoftTags(buildServerActionPageTags(actionRerenderTarget.route, options.cleanPathname));
681
710
  element = options.buildPageElement({
682
711
  cleanPathname: options.cleanPathname,
@@ -22,6 +22,7 @@ declare function handleSsr(rscStream: ReadableStream<Uint8Array>, navContext: Na
22
22
  capturedRscDataRef?: {
23
23
  value: Promise<ArrayBuffer> | null;
24
24
  };
25
+ pprFallbackShellSignal?: AbortSignal;
25
26
  formState?: ReactFormState | null;
26
27
  basePath?: string;
27
28
  /**
@@ -42,6 +43,7 @@ declare function handleSsr(rscStream: ReadableStream<Uint8Array>, navContext: Na
42
43
  * to resolve before returning the HTML stream. Used for static prerender
43
44
  * and ISR cache writes to avoid caching fallback content. */
44
45
  waitForAllReady?: boolean;
46
+ fallbackToErrorDocumentOnShellError?: boolean;
45
47
  }): Promise<AppSsrRenderResult>;
46
48
  declare const _default: {
47
49
  fetch(request: Request): Promise<Response>;
@@ -1,23 +1,26 @@
1
1
  import "./server-globals.js";
2
2
  import { notFoundResponse } from "./http-error-responses.js";
3
3
  import { isOpenRedirectShaped } from "./request-pipeline.js";
4
+ import { isPprFallbackShellAbortError } from "../shims/ppr-fallback-shell.js";
4
5
  import { AppElementsWire } from "./app-elements-wire.js";
5
6
  import "./app-elements.js";
6
7
  import { AppRouterContext } from "../shims/internal/app-router-context.js";
8
+ import { appendAssetDeploymentIdQuery } from "../utils/deployment-id.js";
7
9
  import { ServerInsertedHTMLContext, appRouterInstance, clearServerInsertedHTML, getBfcacheIdMapContext, renderServerInsertedHTML, setNavigationContext, useServerInsertedHTML } from "../shims/navigation.js";
8
10
  import { runWithNavigationContext } from "../shims/navigation-state.js";
9
11
  import { withScriptNonce } from "../shims/script-nonce-context.js";
10
12
  import { createInlineScriptTag, createNonceAttribute, escapeHtmlAttr, safeJsonStringify } from "./html.js";
11
13
  import { getClientTraceMetadataHTML } from "./client-trace-metadata.js";
14
+ import DefaultGlobalError from "../shims/default-global-error.js";
12
15
  import { BfcacheStateKeyMapContext, ElementsContext, Slot } from "../shims/slot.js";
13
16
  import { createSsrErrorMetaRenderer } from "./app-ssr-error-meta.js";
14
17
  import { createNavigationRuntimeRscMetadataScript, createRscEmbedTransform, createTickBufferedTransform } from "./app-ssr-stream.js";
18
+ import { BeforeInteractiveContext } from "../shims/before-interactive-context.js";
19
+ import { runWithRootParamsScope } from "../shims/root-params.js";
15
20
  import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap } from "./app-browser-state.js";
16
21
  import { RSC_FORM_STATE_GLOBAL } from "./app-browser-hydration.js";
17
22
  import { createClientReferencePreloader } from "./app-client-reference-preloader.js";
18
23
  import { deferUntilStreamConsumed } from "./app-page-stream.js";
19
- import { runWithRootParamsScope } from "../shims/root-params.js";
20
- import { BeforeInteractiveContext } from "../shims/before-interactive-context.js";
21
24
  import { createInitialDevServerErrorScript } from "./dev-initial-server-error.js";
22
25
  import { Fragment, createElement, use } from "react";
23
26
  import { renderToReadableStream, renderToStaticMarkup } from "react-dom/server.edge";
@@ -31,6 +34,50 @@ import clientReferences from "virtual:vite-rsc/client-references";
31
34
  * the response-layer combine cap.
32
35
  */
33
36
  const DEFAULT_REACT_MAX_HEADERS_LENGTH = 6e3;
37
+ function isReactDevelopmentRuntime() {
38
+ if (process.env.NODE_ENV === "production") return false;
39
+ if (process.env.NODE_ENV === "development") return true;
40
+ return Function.prototype.toString.call(createElement).includes("getOwner");
41
+ }
42
+ function isStaticPrerenderModule(value) {
43
+ return typeof value === "object" && value !== null && "prerender" in value && typeof value.prerender === "function";
44
+ }
45
+ async function loadStaticPrerender() {
46
+ const staticRenderer = await import("react-dom/static.edge");
47
+ if (isStaticPrerenderModule(staticRenderer)) return staticRenderer.prerender;
48
+ if (isReactDevelopmentRuntime()) try {
49
+ const [{ createRequire }, path] = await Promise.all([import("node:module"), import("node:path")]);
50
+ const reactDomPackageJson = createRequire(import.meta.url).resolve("react-dom/package.json");
51
+ const reactDomDir = path.dirname(reactDomPackageJson);
52
+ const devRenderer = await import(path.join(reactDomDir, "cjs/react-dom-server.edge.development.js"));
53
+ if (isStaticPrerenderModule(devRenderer)) return devRenderer.prerender;
54
+ const devRendererDefault = typeof devRenderer === "object" && devRenderer !== null && "default" in devRenderer && devRenderer.default;
55
+ if (isStaticPrerenderModule(devRendererDefault)) return devRendererDefault.prerender;
56
+ throw new Error("react-dom development renderer did not expose prerender().");
57
+ } catch (error) {
58
+ throw new Error("[vinext] Failed to load React static development renderer.", { cause: error });
59
+ }
60
+ throw new Error("[vinext] react-dom/static.edge did not expose prerender().");
61
+ }
62
+ function createUtf8Stream(html) {
63
+ const encoder = new TextEncoder();
64
+ return new ReadableStream({ start(controller) {
65
+ controller.enqueue(encoder.encode(html));
66
+ controller.close();
67
+ } });
68
+ }
69
+ function buildBootstrapModuleScript(bootstrapModuleUrl, nonce) {
70
+ if (!bootstrapModuleUrl) return "";
71
+ return `<script type="module"${createNonceAttribute(nonce)} src="` + escapeHtmlAttr(bootstrapModuleUrl) + "\" id=\"_R_\" async=\"\"><\/script>";
72
+ }
73
+ function renderSsrErrorDocumentShell(bootstrapModuleUrl, nonce) {
74
+ const html = renderToStaticMarkup(createElement(DefaultGlobalError, { error: null })).replace("<style>", "<style data-vinext-error-shell-style=\"\">");
75
+ const bootstrapScript = buildBootstrapModuleScript(bootstrapModuleUrl, nonce);
76
+ if (!bootstrapScript) return createUtf8Stream(`<!DOCTYPE html>${html}`);
77
+ const documentClose = "</body></html>";
78
+ if (!html.endsWith(documentClose)) return createUtf8Stream(`<!DOCTYPE html>${html}${bootstrapScript}`);
79
+ return createUtf8Stream(`<!DOCTYPE html>${html.slice(0, -14)}${bootstrapScript}${documentClose}`);
80
+ }
34
81
  const clientReferencePreloader = createClientReferencePreloader({
35
82
  getReferences() {
36
83
  return clientReferences;
@@ -94,8 +141,8 @@ function renderFontHtml(fontData, nonce, options = {}) {
94
141
  let fontHTML = "";
95
142
  const nonceAttr = createNonceAttribute(nonce);
96
143
  const includeStyles = options.includeStyles ?? true;
97
- for (const url of fontData.links ?? []) fontHTML += `<link rel="stylesheet"${nonceAttr} href="${escapeHtmlAttr(url)}" />\n`;
98
- for (const preload of fontData.preloads ?? []) fontHTML += `<link rel="preload"${nonceAttr} href="${escapeHtmlAttr(preload.href)}" as="font" type="${escapeHtmlAttr(preload.type)}" crossorigin />\n`;
144
+ for (const url of fontData.links ?? []) fontHTML += `<link rel="stylesheet"${nonceAttr} href="${escapeHtmlAttr(appendAssetDeploymentIdQuery(url))}" />\n`;
145
+ for (const preload of fontData.preloads ?? []) fontHTML += `<link rel="preload"${nonceAttr} href="${escapeHtmlAttr(appendAssetDeploymentIdQuery(preload.href))}" as="font" type="${escapeHtmlAttr(preload.type)}" crossorigin />\n`;
99
146
  if (includeStyles && fontData.styles && fontData.styles.length > 0) fontHTML += `<style data-vinext-fonts${nonceAttr}>${fontData.styles.join("\n")}</style>\n`;
100
147
  return fontHTML;
101
148
  }
@@ -182,24 +229,50 @@ async function handleSsr(rscStream, navContext, fontData, options) {
182
229
  const ssrRoot = withScriptNonce(createElement(BeforeInteractiveContext.Provider, { value: registerBeforeInteractiveInlineScript }, ssrTree), options?.scriptNonce);
183
230
  const bootstrapModuleUrl = extractBootstrapModuleUrl(await import.meta.viteRsc.loadBootstrapScriptContent("index"));
184
231
  const errorMetaRenderer = createSsrErrorMetaRenderer({ basePath: options?.basePath });
232
+ const pprFallbackShellSignal = options?.pprFallbackShellSignal;
185
233
  let reactLinkHeader = "";
186
234
  const maxHeadersLength = options?.reactMaxHeadersLength ?? DEFAULT_REACT_MAX_HEADERS_LENGTH;
187
235
  const captureHeaders = maxHeadersLength > 0;
188
- const htmlStream = await renderToReadableStream(ssrRoot, {
236
+ const renderOptions = {
237
+ bootstrapModules: bootstrapModuleUrl ? [bootstrapModuleUrl] : void 0,
238
+ formState: options?.formState ?? null,
239
+ nonce: options?.scriptNonce,
189
240
  onHeaders: captureHeaders ? (headers) => {
190
241
  const link = headers.get("Link");
191
242
  if (link) reactLinkHeader = link;
192
243
  } : void 0,
193
244
  maxHeadersLength: captureHeaders ? maxHeadersLength : void 0,
194
- bootstrapModules: bootstrapModuleUrl ? [bootstrapModuleUrl] : void 0,
195
- formState: options?.formState ?? null,
196
- nonce: options?.scriptNonce,
197
245
  onError(error) {
246
+ if (pprFallbackShellSignal && isPprFallbackShellAbortError(error)) return;
198
247
  errorMetaRenderer.capture(error);
199
248
  if (error && typeof error === "object" && "digest" in error) return String(error.digest);
200
249
  if (process.env.NODE_ENV === "production" && error) return ssrErrorDigest(getErrorMessage(error) + (error instanceof Error ? error.stack ?? "" : ""));
201
250
  }
202
- });
251
+ };
252
+ let htmlStream;
253
+ let shellErrorRecovered = false;
254
+ if (pprFallbackShellSignal) {
255
+ const prerender = await loadStaticPrerender();
256
+ const htmlAbortController = new AbortController();
257
+ const pendingHtml = prerender(ssrRoot, {
258
+ ...renderOptions,
259
+ signal: htmlAbortController.signal
260
+ });
261
+ setTimeout(() => htmlAbortController.abort(), 0);
262
+ htmlStream = (await pendingHtml).prelude;
263
+ } else {
264
+ let streamingHtmlStream;
265
+ try {
266
+ streamingHtmlStream = await renderToReadableStream(ssrRoot, { ...renderOptions });
267
+ if (options?.waitForAllReady === true) await streamingHtmlStream.allReady;
268
+ htmlStream = streamingHtmlStream;
269
+ } catch (error) {
270
+ streamingHtmlStream?.cancel().catch(() => {});
271
+ if (options?.fallbackToErrorDocumentOnShellError !== true || options?.waitForAllReady === true || typeof error?.digest === "string") throw error;
272
+ shellErrorRecovered = true;
273
+ htmlStream = renderSsrErrorDocumentShell(bootstrapModuleUrl, options?.scriptNonce);
274
+ }
275
+ }
203
276
  const inlineCssManifest = globalThis.__VINEXT_INLINE_CSS__;
204
277
  const fontStyles = fontData?.styles ?? [];
205
278
  const mergeFontStylesIntoInlineCss = fontStyles.length > 0 && hasInlineCssManifest(inlineCssManifest);
@@ -221,11 +294,11 @@ async function handleSsr(rscStream, navContext, fontData, options) {
221
294
  return buildHeadInjectionHtml(ssrNavigationContext, bootstrapModuleUrl, options?.formState ?? null, insertedHTML + errorMetaHTML + getTraceMetaHTML() + initialDevServerErrorHTML, fontHTML, options?.scriptNonce);
222
295
  };
223
296
  const getBeforeInteractiveHeadHTML = () => renderBeforeInteractiveInlineScripts(beforeInteractiveInlineScripts);
224
- if (options?.waitForAllReady === true) await htmlStream.allReady;
225
297
  return {
226
298
  htmlStream: deferUntilStreamConsumed(htmlStream.pipeThrough(createTickBufferedTransform(rscEmbed, getInsertedHTML, getBeforeInteractiveHeadHTML, inlineCssManifest, inlineCssFontStyles, inlineCssFontStyleFallbackHTML, options?.scriptNonce)), cleanup),
227
299
  metadataReady: Promise.resolve(),
228
300
  capturedRscData: options?.capturedRscDataRef?.value ?? null,
301
+ shellErrorRecovered,
229
302
  linkHeader: reactLinkHeader
230
303
  };
231
304
  } catch (error) {
@@ -19,6 +19,10 @@ function applyCdnResponseHeaders(headers, input) {
19
19
  headers.delete("Cache-Control");
20
20
  const map = getCdnCacheAdapter().buildResponseHeaders(input);
21
21
  for (const [name, value] of Object.entries(map)) {
22
+ if (value === null) {
23
+ headers.delete(name);
24
+ continue;
25
+ }
22
26
  if (value === "") continue;
23
27
  headers.set(name, value);
24
28
  }
@@ -43,7 +43,7 @@ declare function createSSRHandler(server: ViteDevServer, runner: ModuleImporter,
43
43
  * `next.config`. When undefined or empty, no meta tags are emitted.
44
44
  */
45
45
 
46
- clientTraceMetadata?: readonly string[]): (req: IncomingMessage, res: ServerResponse, url: string, /** Status code override — propagated from middleware rewrite status. */
46
+ clientTraceMetadata?: readonly string[], htmlLimitedBots?: string): (req: IncomingMessage, res: ServerResponse, url: string, /** Status code override — propagated from middleware rewrite status. */
47
47
 
48
48
  statusCode?: number,
49
49
  /**
@@ -53,6 +53,6 @@ statusCode?: number,
53
53
  * client-side navigations in the Pages Router.
54
54
  */
55
55
 
56
- isDataReq?: boolean) => Promise<void>;
56
+ isDataReq?: boolean, originalUrl?: string) => Promise<void>;
57
57
  //#endregion
58
58
  export { createSSRHandler, detectLocaleFromHeaders, extractLocaleFromUrl, parseCookieLocale };