vinext 1.0.0 → 1.1.0

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 (263) hide show
  1. package/README.md +72 -1
  2. package/THIRD_PARTY_LICENSES.md +26 -0
  3. package/dist/build/app-page-static-eligibility.d.ts +15 -0
  4. package/dist/build/app-page-static-eligibility.js +82 -0
  5. package/dist/build/lifecycle.js +10 -10
  6. package/dist/build/pages-client-assets-module.js +6 -1
  7. package/dist/build/precompress.js +1 -1
  8. package/dist/build/prerender-paths.js +6 -85
  9. package/dist/build/prerender.d.ts +8 -1
  10. package/dist/build/prerender.js +167 -46
  11. package/dist/build/run-prerender.js +4 -3
  12. package/dist/build/server-entry.d.ts +2 -0
  13. package/dist/build/server-entry.js +7 -1
  14. package/dist/build/server-manifest.d.ts +7 -0
  15. package/dist/build/server-manifest.js +11 -1
  16. package/dist/cache/cache-adapters-virtual.d.ts +7 -1
  17. package/dist/cache/cache-adapters-virtual.js +3 -3
  18. package/dist/client/browser-globals.d.ts +4 -0
  19. package/dist/client/browser-globals.js +5 -0
  20. package/dist/client/navigation-runtime.d.ts +11 -1
  21. package/dist/client/navigation-runtime.js +3 -3
  22. package/dist/config/config-matchers.js +3 -1
  23. package/dist/config/dotenv.js +14 -3
  24. package/dist/config/next-config.d.ts +7 -0
  25. package/dist/config/next-config.js +18 -3
  26. package/dist/entries/app-rsc-entry.d.ts +2 -0
  27. package/dist/entries/app-rsc-entry.js +67 -45
  28. package/dist/index.d.ts +4 -1
  29. package/dist/index.js +200 -100
  30. package/dist/init-cloudflare.d.ts +1 -1
  31. package/dist/init-cloudflare.js +6 -6
  32. package/dist/init-platform.js +1 -1
  33. package/dist/init.js +4 -2
  34. package/dist/plugins/cache-flight-codec.d.ts +19 -0
  35. package/dist/plugins/cache-flight-codec.js +68 -0
  36. package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
  37. package/dist/plugins/commonjs-esm-facade.js +80 -0
  38. package/dist/plugins/commonjs-syntax.d.ts +16 -0
  39. package/dist/plugins/commonjs-syntax.js +22 -0
  40. package/dist/plugins/fonts.d.ts +8 -11
  41. package/dist/plugins/fonts.js +71 -34
  42. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  43. package/dist/plugins/ignore-dynamic-requests.js +54 -3
  44. package/dist/plugins/import-meta-url.js +6 -6
  45. package/dist/plugins/og-asset-ownership.d.ts +2 -0
  46. package/dist/plugins/og-asset-ownership.js +24 -13
  47. package/dist/plugins/og-assets.d.ts +18 -0
  48. package/dist/plugins/og-assets.js +50 -8
  49. package/dist/plugins/og-harfbuzz.js +38 -27
  50. package/dist/plugins/optimize-imports.js +2 -1
  51. package/dist/plugins/require-context.d.ts +1 -0
  52. package/dist/plugins/require-context.js +28 -1
  53. package/dist/plugins/scan-build-css.d.ts +12 -0
  54. package/dist/plugins/scan-build-css.js +39 -0
  55. package/dist/plugins/strip-server-exports.d.ts +2 -0
  56. package/dist/plugins/strip-server-exports.js +3 -1
  57. package/dist/plugins/transform-result.d.ts +18 -0
  58. package/dist/plugins/transform-result.js +23 -2
  59. package/dist/plugins/typeof-window.d.ts +10 -0
  60. package/dist/plugins/typeof-window.js +33 -9
  61. package/dist/routing/app-route-graph.d.ts +0 -1
  62. package/dist/routing/app-route-graph.js +2 -4
  63. package/dist/routing/app-route-ids.d.ts +3 -0
  64. package/dist/routing/app-route-ids.js +6 -0
  65. package/dist/routing/file-matcher.d.ts +1 -0
  66. package/dist/routing/file-matcher.js +1 -1
  67. package/dist/server/api-handler.js +17 -7
  68. package/dist/server/app-bfcache-id.d.ts +1 -0
  69. package/dist/server/app-bfcache-id.js +7 -1
  70. package/dist/server/app-bfcache-identity.js +1 -2
  71. package/dist/server/app-browser-entry.js +15 -9
  72. package/dist/server/app-browser-history-controller.d.ts +2 -0
  73. package/dist/server/app-browser-history-controller.js +8 -0
  74. package/dist/server/app-browser-hydration.d.ts +1 -1
  75. package/dist/server/app-browser-hydration.js +2 -2
  76. package/dist/server/app-browser-interception-context.js +26 -2
  77. package/dist/server/app-browser-navigation-controller.d.ts +7 -1
  78. package/dist/server/app-browser-navigation-controller.js +94 -11
  79. package/dist/server/app-browser-state.js +1 -1
  80. package/dist/server/app-browser-stream.d.ts +1 -1
  81. package/dist/server/app-fallback-renderer.d.ts +2 -0
  82. package/dist/server/app-fallback-renderer.js +1 -0
  83. package/dist/server/app-history-state.d.ts +3 -1
  84. package/dist/server/app-history-state.js +9 -5
  85. package/dist/server/app-middleware.js +2 -1
  86. package/dist/server/app-optimistic-routing.js +1 -1
  87. package/dist/server/app-page-boundary-render.d.ts +5 -0
  88. package/dist/server/app-page-boundary-render.js +6 -4
  89. package/dist/server/app-page-cache-finalizer.d.ts +11 -0
  90. package/dist/server/app-page-cache-finalizer.js +41 -7
  91. package/dist/server/app-page-cache-render.d.ts +18 -0
  92. package/dist/server/app-page-cache-render.js +65 -44
  93. package/dist/server/app-page-cache.d.ts +5 -0
  94. package/dist/server/app-page-cache.js +27 -7
  95. package/dist/server/app-page-dispatch.d.ts +9 -1
  96. package/dist/server/app-page-dispatch.js +47 -30
  97. package/dist/server/app-page-element-builder.d.ts +7 -0
  98. package/dist/server/app-page-element-builder.js +27 -42
  99. package/dist/server/app-page-execution.d.ts +15 -12
  100. package/dist/server/app-page-execution.js +30 -40
  101. package/dist/server/app-page-head.d.ts +5 -0
  102. package/dist/server/app-page-head.js +9 -3
  103. package/dist/server/app-page-probe.d.ts +0 -109
  104. package/dist/server/app-page-probe.js +3 -136
  105. package/dist/server/app-page-render-identity.d.ts +0 -1
  106. package/dist/server/app-page-render-identity.js +1 -1
  107. package/dist/server/app-page-render-observation.js +2 -2
  108. package/dist/server/app-page-render.d.ts +13 -5
  109. package/dist/server/app-page-render.js +219 -118
  110. package/dist/server/app-page-request.d.ts +0 -1
  111. package/dist/server/app-page-request.js +1 -2
  112. package/dist/server/app-page-response.d.ts +4 -3
  113. package/dist/server/app-page-response.js +4 -3
  114. package/dist/server/app-page-route-wiring.d.ts +17 -5
  115. package/dist/server/app-page-route-wiring.js +55 -33
  116. package/dist/server/app-page-rsc-render-status.d.ts +48 -0
  117. package/dist/server/app-page-rsc-render-status.js +54 -0
  118. package/dist/server/app-page-search-params-observation.js +1 -1
  119. package/dist/server/app-page-stream.d.ts +15 -8
  120. package/dist/server/app-page-stream.js +7 -1
  121. package/dist/server/app-page-tracing.js +2 -1
  122. package/dist/server/app-pages-bridge.js +3 -2
  123. package/dist/server/app-render-abort-error.d.ts +3 -0
  124. package/dist/server/app-render-abort-error.js +8 -0
  125. package/dist/server/app-request-stage-dispatch.js +1 -1
  126. package/dist/server/app-request-stage-independent-entry.js +8 -11
  127. package/dist/server/app-response-header-provenance.d.ts +2 -0
  128. package/dist/server/app-response-header-provenance.js +10 -4
  129. package/dist/server/app-route-handler-cache.d.ts +2 -1
  130. package/dist/server/app-route-handler-cache.js +11 -7
  131. package/dist/server/app-route-handler-dispatch.js +11 -4
  132. package/dist/server/app-route-handler-execution.d.ts +9 -1
  133. package/dist/server/app-route-handler-execution.js +28 -13
  134. package/dist/server/app-route-handler-policy.js +2 -2
  135. package/dist/server/app-route-handler-response.d.ts +1 -1
  136. package/dist/server/app-route-handler-response.js +14 -5
  137. package/dist/server/app-router-entry.d.ts +2 -1
  138. package/dist/server/app-router-entry.js +8 -12
  139. package/dist/server/app-rsc-errors.d.ts +0 -1
  140. package/dist/server/app-rsc-errors.js +2 -6
  141. package/dist/server/app-rsc-handler.d.ts +5 -0
  142. package/dist/server/app-rsc-handler.js +229 -102
  143. package/dist/server/app-rsc-request-normalization.d.ts +4 -2
  144. package/dist/server/app-rsc-request-normalization.js +7 -4
  145. package/dist/server/app-rsc-response-finalizer.js +4 -1
  146. package/dist/server/app-rsc-response-stage.d.ts +1 -1
  147. package/dist/server/app-rsc-response-stage.js +6 -4
  148. package/dist/server/app-rsc-route-matching.d.ts +9 -1
  149. package/dist/server/app-rsc-route-matching.js +37 -20
  150. package/dist/server/app-server-action-execution.d.ts +2 -1
  151. package/dist/server/app-server-action-execution.js +1 -1
  152. package/dist/server/app-ssr-entry.d.ts +3 -2
  153. package/dist/server/app-ssr-entry.js +9 -7
  154. package/dist/server/app-ssr-search-params-gate.js +1 -1
  155. package/dist/server/app-ssr-stream.d.ts +6 -1
  156. package/dist/server/app-ssr-stream.js +35 -16
  157. package/dist/server/app-worker-stages.d.ts +2 -2
  158. package/dist/server/app-worker-stages.js +3 -3
  159. package/dist/server/cache-control.js +3 -11
  160. package/dist/server/cacheability-request.js +56 -52
  161. package/dist/server/config-headers.js +3 -1
  162. package/dist/server/dev-server.js +23 -5
  163. package/dist/server/headers.d.ts +16 -0
  164. package/dist/server/headers.js +19 -1
  165. package/dist/server/http-error-responses.js +1 -0
  166. package/dist/server/image-optimization.d.ts +16 -0
  167. package/dist/server/image-optimization.js +26 -6
  168. package/dist/server/isr-cache.d.ts +2 -0
  169. package/dist/server/isr-cache.js +8 -3
  170. package/dist/server/metadata-route-response.js +94 -37
  171. package/dist/server/middleware-matcher-pattern.js +8 -4
  172. package/dist/server/middleware-response-headers.js +2 -0
  173. package/dist/server/multi-stage.d.ts +8 -0
  174. package/dist/server/navigation-planner.js +1 -1
  175. package/dist/server/node-response-signal.d.ts +16 -0
  176. package/dist/server/node-response-signal.js +26 -0
  177. package/dist/server/open-redirect.d.ts +47 -0
  178. package/dist/server/open-redirect.js +74 -1
  179. package/dist/server/pages-api-route.js +8 -2
  180. package/dist/server/pages-asset-tags.d.ts +1 -0
  181. package/dist/server/pages-asset-tags.js +73 -22
  182. package/dist/server/pages-client-assets.d.ts +2 -0
  183. package/dist/server/pages-page-data.d.ts +6 -1
  184. package/dist/server/pages-page-data.js +71 -65
  185. package/dist/server/pages-page-handler.js +50 -15
  186. package/dist/server/pages-page-response.js +3 -1
  187. package/dist/server/pages-request-pipeline.d.ts +2 -1
  188. package/dist/server/pages-request-pipeline.js +20 -5
  189. package/dist/server/pages-request-stage-entry.js +14 -8
  190. package/dist/server/prerender-manifest.d.ts +6 -0
  191. package/dist/server/prerender-manifest.js +1 -1
  192. package/dist/server/prod-server.d.ts +8 -7
  193. package/dist/server/prod-server.js +152 -78
  194. package/dist/server/request-pipeline.d.ts +20 -8
  195. package/dist/server/request-pipeline.js +21 -7
  196. package/dist/server/response-compression.d.ts +43 -0
  197. package/dist/server/response-compression.js +111 -0
  198. package/dist/server/response-stage-cacheability.js +1 -1
  199. package/dist/server/seed-cache.js +10 -7
  200. package/dist/server/socket-error-backstop.d.ts +14 -0
  201. package/dist/server/socket-error-backstop.js +27 -4
  202. package/dist/server/worker-revalidation-context.d.ts +2 -1
  203. package/dist/server/worker-revalidation-context.js +1 -0
  204. package/dist/server/workers-tracing.d.ts +17 -0
  205. package/dist/server/workers-tracing.js +48 -8
  206. package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
  207. package/dist/shims/cache-adapter-instantiate.js +118 -0
  208. package/dist/shims/cache-callable-runtime.d.ts +2 -40
  209. package/dist/shims/cache-callable-runtime.js +50 -168
  210. package/dist/shims/cache-flight-arguments.d.ts +22 -0
  211. package/dist/shims/cache-flight-arguments.js +56 -0
  212. package/dist/shims/cache-request-state.d.ts +18 -14
  213. package/dist/shims/cache-request-state.js +33 -21
  214. package/dist/shims/cache-runtime.d.ts +6 -19
  215. package/dist/shims/cache-runtime.js +168 -226
  216. package/dist/shims/cache.d.ts +3 -2
  217. package/dist/shims/cache.js +8 -5
  218. package/dist/shims/cacheability-classification.d.ts +8 -1
  219. package/dist/shims/cacheability-classification.js +2 -2
  220. package/dist/shims/cdn-cache.d.ts +10 -1
  221. package/dist/shims/cdn-cache.js +16 -9
  222. package/dist/shims/error-boundary-navigation.d.ts +7 -0
  223. package/dist/shims/error-boundary-navigation.js +19 -1
  224. package/dist/shims/error-boundary.d.ts +10 -10
  225. package/dist/shims/error-boundary.js +26 -7
  226. package/dist/shims/error.d.ts +4 -18
  227. package/dist/shims/error.js +17 -10
  228. package/dist/shims/error.react-server.d.ts +4 -6
  229. package/dist/shims/error.react-server.js +4 -1
  230. package/dist/shims/fetch-cache.d.ts +6 -0
  231. package/dist/shims/fetch-cache.js +23 -4
  232. package/dist/shims/form.js +1 -1
  233. package/dist/shims/headers.d.ts +19 -69
  234. package/dist/shims/headers.js +82 -183
  235. package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
  236. package/dist/shims/internal/app-page-props-cache-key.js +24 -15
  237. package/dist/shims/internal/cache-context-accessor.d.ts +16 -0
  238. package/dist/shims/internal/cache-context-accessor.js +15 -0
  239. package/dist/shims/internal/headers-state.d.ts +73 -0
  240. package/dist/shims/internal/headers-state.js +157 -0
  241. package/dist/shims/metadata.js +3 -3
  242. package/dist/shims/navigation-errors.d.ts +6 -0
  243. package/dist/shims/navigation-errors.js +11 -1
  244. package/dist/shims/navigation.d.ts +7 -0
  245. package/dist/shims/navigation.js +16 -6
  246. package/dist/shims/request-context.d.ts +9 -0
  247. package/dist/shims/request-state-types.d.ts +2 -1
  248. package/dist/shims/root-params.js +1 -1
  249. package/dist/shims/server.js +52 -2
  250. package/dist/shims/thenable-params.d.ts +4 -0
  251. package/dist/shims/thenable-params.js +25 -3
  252. package/dist/shims/unified-request-context.d.ts +1 -1
  253. package/dist/shims/unified-request-context.js +1 -0
  254. package/dist/utils/encode-cache-tag.d.ts +1 -0
  255. package/dist/utils/encode-cache-tag.js +11 -1
  256. package/dist/utils/mdx-scan.d.ts +5 -0
  257. package/dist/utils/mdx-scan.js +8 -1
  258. package/dist/utils/regex-safety.d.ts +10 -0
  259. package/dist/utils/regex-safety.js +70 -18
  260. package/dist/utils/vite-cli-invocation.js +8 -1
  261. package/package.json +8 -4
  262. package/dist/server/metadata-route-cache-policy.d.ts +0 -5
  263. package/dist/server/metadata-route-cache-policy.js +0 -6
@@ -1,4 +1,5 @@
1
- import { consumeDynamicUsage, consumeInvalidDynamicUsageError, isRenderDynamicLatched } from "../shims/headers.js";
1
+ import { isRenderDynamicLatched } from "../shims/internal/headers-state.js";
2
+ import { consumeDynamicUsage, consumeInvalidDynamicUsageError } from "../shims/headers.js";
2
3
  import { _consumeRequestScopedCacheLife } from "../shims/cache-request-state.js";
3
4
  import { getCollectedFetchTags } from "../shims/fetch-cache.js";
4
5
  import { readStreamAsText } from "../utils/text-stream.js";
@@ -25,34 +26,49 @@ async function renderAppPageCacheArtifactsImpl(options, renderSpan) {
25
26
  const rscCapture = teeAppPageRscStreamForCapture(rscStream, options.captureRscData);
26
27
  const capturedRscDataRef = { value: null };
27
28
  const fontPreloads = options.getFontPreloads();
28
- const htmlResult = await (await options.loadSsrHandler()).handleSsr(rscCapture.ssrStream, options.getNavigationContext(), {
29
- links: options.getFontLinks(),
30
- styles: options.getFontStyles(),
31
- preloads: fontPreloads
32
- }, {
33
- basePath: options.basePath,
34
- clientTraceMetadata: options.clientTraceMetadata,
35
- reactMaxHeadersLength: options.reactMaxHeadersLength,
36
- rootParams: options.rootParams,
37
- waitForAllReady: options.waitForAllReady,
38
- isStaticGeneration: true,
39
- isForceStatic: options.isForceStatic,
40
- onSsrError: options.onSsrError && options.isCapturedRscError ? createAppPageSsrErrorHandler((error) => {
41
- recordAppPageRenderError(renderSpan, error);
42
- return options.onSsrError?.(error);
43
- }, options.isCapturedRscError) : options.onSsrError ? (error) => {
44
- recordAppPageRenderError(renderSpan, error);
45
- return options.onSsrError?.(error);
46
- } : void 0,
47
- ...rscCapture.sideStream ? {
48
- sideStream: rscCapture.sideStream,
49
- capturedRscDataRef
50
- } : {}
51
- });
52
- const htmlStream = isAppSsrRenderResult(htmlResult) ? htmlResult.htmlStream : htmlResult;
53
- const reactLinkHeader = isAppSsrRenderResult(htmlResult) ? htmlResult.linkHeader : void 0;
54
- const linkHeader = buildAppPageLinkHeader(reactLinkHeader, buildAppPageFontLinkHeader(fontPreloads), options.reactMaxHeadersLength);
55
- const html = await readStreamAsText(htmlStream);
29
+ const ssrHandler = await options.loadSsrHandler();
30
+ let htmlResult = null;
31
+ let specialErrorDocument = null;
32
+ try {
33
+ htmlResult = await ssrHandler.handleSsr(rscCapture.ssrStream, options.getNavigationContext(), {
34
+ links: options.getFontLinks(),
35
+ styles: options.getFontStyles(),
36
+ preloads: fontPreloads
37
+ }, {
38
+ basePath: options.basePath,
39
+ clientTraceMetadata: options.clientTraceMetadata,
40
+ reactMaxHeadersLength: options.reactMaxHeadersLength,
41
+ rootParams: options.rootParams,
42
+ waitForAllReady: options.waitForAllReady,
43
+ mirrorNextFlight: options.mirrorNextFlight,
44
+ isStaticGeneration: true,
45
+ isForceStatic: options.isForceStatic,
46
+ onSsrError: options.onSsrError && options.isCapturedRscError ? createAppPageSsrErrorHandler((error) => {
47
+ recordAppPageRenderError(renderSpan, error);
48
+ return options.onSsrError?.(error);
49
+ }, options.isCapturedRscError) : options.onSsrError ? (error) => {
50
+ recordAppPageRenderError(renderSpan, error);
51
+ return options.onSsrError?.(error);
52
+ } : void 0,
53
+ ...rscCapture.sideStream ? {
54
+ sideStream: rscCapture.sideStream,
55
+ capturedRscDataRef
56
+ } : {}
57
+ });
58
+ } catch (error) {
59
+ if (!options.renderShellSpecialError) throw error;
60
+ await capturedRscDataRef.value?.catch(() => {});
61
+ specialErrorDocument = await options.renderShellSpecialError(error);
62
+ if (!specialErrorDocument) throw error;
63
+ }
64
+ let html = specialErrorDocument?.html ?? "";
65
+ let linkHeader = specialErrorDocument?.linkHeader;
66
+ if (htmlResult) {
67
+ const htmlStream = isAppSsrRenderResult(htmlResult) ? htmlResult.htmlStream : htmlResult;
68
+ const reactLinkHeader = isAppSsrRenderResult(htmlResult) ? htmlResult.linkHeader : void 0;
69
+ linkHeader = buildAppPageLinkHeader(reactLinkHeader, buildAppPageFontLinkHeader(fontPreloads), options.reactMaxHeadersLength);
70
+ html = await readStreamAsText(htmlStream);
71
+ }
56
72
  let rscData;
57
73
  if (options.captureRscData) {
58
74
  const capturedPromise = capturedRscDataRef.value;
@@ -64,24 +80,29 @@ async function renderAppPageCacheArtifactsImpl(options, renderSpan) {
64
80
  const observationState = consumeAppPageRenderObservationState();
65
81
  consumeInvalidDynamicUsageError();
66
82
  const usedDynamicApi = consumeDynamicUsage() || isRenderDynamicLatched();
83
+ const htmlRenderObservation = createAppPageRenderObservation({
84
+ boundaryOutcome: { kind: "success" },
85
+ cacheability: "public",
86
+ cacheTags: tags,
87
+ cleanPathname: options.cleanPathname,
88
+ completeness: "complete",
89
+ output: createAppPageHtmlOutputScope({
90
+ element: options.element,
91
+ renderEpoch: null,
92
+ rootBoundaryId: null,
93
+ routePattern: options.route.pattern
94
+ }),
95
+ params: options.navigationParams,
96
+ state: observationState
97
+ });
67
98
  const result = {
68
99
  html,
69
- htmlRenderObservation: createAppPageRenderObservation({
70
- boundaryOutcome: { kind: "success" },
71
- cacheability: "public",
72
- cacheTags: tags,
73
- cleanPathname: options.cleanPathname,
74
- completeness: "complete",
75
- output: createAppPageHtmlOutputScope({
76
- element: options.element,
77
- renderEpoch: null,
78
- rootBoundaryId: null,
79
- routePattern: options.route.pattern
80
- }),
81
- params: options.navigationParams,
82
- state: observationState
83
- }),
100
+ htmlRenderObservation,
84
101
  ...linkHeader ? { linkHeader } : {},
102
+ ...specialErrorDocument ? {
103
+ headers: specialErrorDocument.headers,
104
+ status: specialErrorDocument.status
105
+ } : {},
85
106
  tags,
86
107
  usedDynamicApi,
87
108
  cacheControl: typeof cacheLife?.revalidate === "number" ? {
@@ -21,11 +21,15 @@ export type AppPageCacheOutcomeMetric = Readonly<{
21
21
  type AppPageCacheOutcomeRecorder = (metric: AppPageCacheOutcomeMetric) => void;
22
22
  type AppPageCacheRenderResult = {
23
23
  cacheControl?: CacheControlMetadata;
24
+ /** Response headers stored with both entries, such as a redirect's `location`. */
25
+ headers?: Record<string, string>;
24
26
  html: string;
25
27
  htmlRenderObservation: RenderObservation;
26
28
  linkHeader?: string;
27
29
  rscData: ArrayBuffer;
28
30
  rscRenderObservation: RenderObservation;
31
+ /** The status of a render whose shell ended in a special error. */
32
+ status?: number;
29
33
  /**
30
34
  * The route-level revalidate of the route this render regenerated, or null
31
35
  * when it has none and the render's cacheLife sets it. Undefined keeps the
@@ -40,6 +44,7 @@ type BuildAppPageCachedResponseOptions = {
40
44
  cacheState: "HIT" | "STALE";
41
45
  expireSeconds?: number;
42
46
  isEdgeRuntime?: boolean;
47
+ isRoutePPREnabled?: boolean;
43
48
  isRscRequest: boolean;
44
49
  middlewareHeaders?: Headers | null;
45
50
  middlewareStatus?: number | null;
@@ -1,5 +1,5 @@
1
1
  import { VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_RSC_VARY_HEADER } from "./app-rsc-vary.js";
2
- import { VINEXT_PARAMS_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER } from "./headers.js";
2
+ import { VINEXT_PARAMS_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_SPECIAL_ERROR_STATUS_HEADER } from "./headers.js";
3
3
  import { applyCdnResponseHeaders } from "./cache-control.js";
4
4
  import { decideIsr } from "./isr-decision.js";
5
5
  import { buildAppPageCacheValue, isrCacheControl, resolveRouteExpireSeconds } from "./isr-cache.js";
@@ -53,6 +53,10 @@ function buildAppPageCachedHeaders(options) {
53
53
  if (options.params && Object.keys(options.params).length > 0) headers.set(VINEXT_PARAMS_HEADER, encodeURIComponent(JSON.stringify(options.params)));
54
54
  if (options.mountedSlotsHeader) headers.set(VINEXT_MOUNTED_SLOTS_HEADER, options.mountedSlotsHeader);
55
55
  applyClientStaleTimeHeader(headers, options.staleTimeSeconds);
56
+ for (const [name, value] of Object.entries(options.storedHeaders ?? {})) {
57
+ if (name.toLowerCase() === "link") continue;
58
+ for (const item of Array.isArray(value) ? value : [value]) headers.append(name, item);
59
+ }
56
60
  mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders ?? null);
57
61
  if (options.linkHeader) {
58
62
  if (Array.isArray(options.linkHeader)) for (const value of options.linkHeader) headers.append("Link", value);
@@ -88,8 +92,15 @@ function resolveRegenerationFailureCacheControl(previous) {
88
92
  ...previous.stale === void 0 ? {} : { stale: previous.stale }
89
93
  };
90
94
  }
95
+ function isRedirectStatus(status) {
96
+ return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
97
+ }
91
98
  function buildAppPageCachedResponse(cachedValue, options) {
92
- const status = options.middlewareStatus ?? (cachedValue.status || 200);
99
+ const storedStatus = cachedValue.status || 200;
100
+ const isRedirect = isRedirectStatus(storedStatus);
101
+ const isHttpErrorFallbackStatus = storedStatus === 401 || storedStatus === 403 || storedStatus === 404;
102
+ const replayStatus = options.isRscRequest && (isRedirect || options.isRoutePPREnabled === true) ? 200 : storedStatus;
103
+ const status = isRedirect || isHttpErrorFallbackStatus ? replayStatus : options.middlewareStatus ?? replayStatus;
93
104
  const { cacheControl } = decideIsr({
94
105
  cacheState: options.cacheState,
95
106
  kind: "app-page",
@@ -108,17 +119,19 @@ function buildAppPageCachedResponse(cachedValue, options) {
108
119
  middlewareHeaders: options.middlewareHeaders,
109
120
  mountedSlotsHeader: options.mountedSlotsHeader,
110
121
  params: options.params,
111
- staleTimeSeconds
122
+ staleTimeSeconds,
123
+ storedHeaders: cachedValue.headers
112
124
  });
113
125
  if (options.renderedPathAndSearch) rscHeaders.set(VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, encodeURIComponent(options.renderedPathAndSearch));
114
126
  applyRscCompatibilityIdHeader(rscHeaders);
115
127
  applyRscDeploymentIdHeader(rscHeaders);
128
+ if (isHttpErrorFallbackStatus && status === storedStatus) rscHeaders.set(VINEXT_SPECIAL_ERROR_STATUS_HEADER, String(storedStatus));
116
129
  return new Response(cachedValue.rscData, {
117
130
  status,
118
131
  headers: rscHeaders
119
132
  });
120
133
  }
121
- if (typeof cachedValue.html !== "string" || cachedValue.html.length === 0) return null;
134
+ if (typeof cachedValue.html !== "string" || cachedValue.html.length === 0 && !isRedirect) return null;
122
135
  const htmlHeaders = buildAppPageCachedHeaders({
123
136
  cacheControl,
124
137
  cacheState: options.cacheState,
@@ -126,7 +139,8 @@ function buildAppPageCachedResponse(cachedValue, options) {
126
139
  isEdgeRuntime: options.isEdgeRuntime,
127
140
  linkHeader: cachedValue.headers?.link,
128
141
  middlewareHeaders: options.middlewareHeaders,
129
- staleTimeSeconds
142
+ staleTimeSeconds,
143
+ storedHeaders: cachedValue.headers
130
144
  });
131
145
  const response = new Response(cachedValue.html, {
132
146
  status,
@@ -218,6 +232,7 @@ async function readAppPageCacheResponse(options) {
218
232
  cacheControl: cached?.value.cacheControl,
219
233
  expireSeconds: options.expireSeconds,
220
234
  isEdgeRuntime: options.isEdgeRuntime,
235
+ isRoutePPREnabled: options.isRoutePPREnabled,
221
236
  isRscRequest: options.isRscRequest,
222
237
  middlewareHeaders: options.middlewareHeaders,
223
238
  middlewareStatus: options.middlewareStatus,
@@ -287,9 +302,13 @@ see more here https://nextjs.org/docs/messages/app-static-to-dynamic-error`);
287
302
  return false;
288
303
  }
289
304
  };
290
- if (!await store(rscKey, buildAppPageCacheValue("", revalidatedPage.rscData, 200, revalidatedPage.rscRenderObservation))) return;
305
+ const status = revalidatedPage.status ?? 200;
306
+ if (!await store(rscKey, buildAppPageCacheValue("", revalidatedPage.rscData, status, revalidatedPage.rscRenderObservation, revalidatedPage.headers))) return;
291
307
  if (!options.isRscRequest) {
292
- if (!await store(isrKey, buildAppPageCacheValue(revalidatedPage.html, void 0, 200, revalidatedPage.htmlRenderObservation, revalidatedPage.linkHeader ? { link: revalidatedPage.linkHeader } : void 0))) return;
308
+ if (!await store(isrKey, buildAppPageCacheValue(revalidatedPage.html, void 0, status, revalidatedPage.htmlRenderObservation, revalidatedPage.linkHeader ? {
309
+ ...revalidatedPage.headers,
310
+ link: revalidatedPage.linkHeader
311
+ } : revalidatedPage.headers))) return;
293
312
  }
294
313
  options.isrDebug?.("regen complete", options.cleanPathname);
295
314
  };
@@ -306,6 +325,7 @@ see more here https://nextjs.org/docs/messages/app-static-to-dynamic-error`);
306
325
  cacheControl: cached.value.cacheControl,
307
326
  expireSeconds: options.expireSeconds,
308
327
  isEdgeRuntime: options.isEdgeRuntime,
328
+ isRoutePPREnabled: options.isRoutePPREnabled,
309
329
  isRscRequest: options.isRscRequest,
310
330
  middlewareHeaders: options.middlewareHeaders,
311
331
  middlewareStatus: options.middlewareStatus,
@@ -142,6 +142,7 @@ export type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
142
142
  observeMetadataSearchParamsAccess?: boolean;
143
143
  observePageSearchParamsAccess?: boolean;
144
144
  serveStreamingMetadata?: boolean;
145
+ placeStreamedMetadataInHead?: boolean;
145
146
  }) => Promise<AppPageElement>;
146
147
  clientReuseManifest?: ClientReuseManifestParseResult;
147
148
  cleanPathname: string;
@@ -221,13 +222,14 @@ export type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
221
222
  staticParamsValidationParams?: AppPageParams;
222
223
  rootParams?: RootParams;
223
224
  probeLayoutAt: (layoutIndex: number, layoutParamAccess?: AppLayoutParamAccessTracker) => unknown;
224
- probePage: (searchParams?: URLSearchParams) => unknown;
225
225
  expireSeconds?: number;
226
226
  renderErrorBoundaryPage: (error: unknown, errorOrigin?: "rsc" | "ssr") => Promise<Response | null>;
227
227
  renderHttpAccessFallbackPage: (statusCode: number, opts: {
228
228
  boundaryComponent?: unknown;
229
229
  boundaryModule?: AppPageModule | null;
230
230
  intercept?: AppPageDispatchInterceptOptions | null;
231
+ /** The document may be stored, so it must not carry the request's query. */
232
+ isCacheCandidate?: boolean;
231
233
  layouts?: readonly AppPageModule[];
232
234
  matchedParams: AppPageParams;
233
235
  }, middlewareContext: AppPageMiddlewareContext | null) => Promise<Response | null>;
@@ -268,6 +270,12 @@ export type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
268
270
  searchParams: URLSearchParams;
269
271
  }) => void;
270
272
  renderMode?: AppRscRenderMode;
273
+ /**
274
+ * Render the document whole before its first byte, with streamed metadata in
275
+ * `<head>`, as a background regeneration does. The adapter sets this for a
276
+ * render no client is waiting on, such as its regeneration or a warm-up.
277
+ */
278
+ renderWholeDocument?: boolean;
271
279
  };
272
280
  export declare function shouldReadAppPageCache(options: {
273
281
  isProgressiveActionRender: boolean;
@@ -5,27 +5,28 @@ import { VINEXT_INTERCEPTION_ID_HEADER, VINEXT_RSC_VARY_HEADER } from "./app-rsc
5
5
  import "./headers.js";
6
6
  import { beginRouteCacheability, isRouteCacheabilityIdentityProbe, isRouteCacheabilityProbe, markRouteCacheabilityPatternDynamic, readRouteCacheabilityState } from "../shims/cacheability-classification.js";
7
7
  import { APP_RSC_RENDER_MODE_PREFETCH_DYNAMIC_SHELL } from "./app-rsc-render-mode.js";
8
- import { AppElementsWire } from "./app-elements-wire.js";
9
- import "./app-elements.js";
10
8
  import { consumeDynamicUsage, consumeInvalidDynamicUsageError, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersContext, isDraftModeRequest, peekDynamicUsage, peekRenderRequestApiUsage, runWithIsolatedDynamicUsage, setHeadersContext } from "../shims/headers.js";
11
9
  import { _captureRequestScopedCacheLifeAccessors } from "../shims/cache-request-state.js";
12
10
  import { ensureFetchPatch, getCollectedFetchTags, peekDynamicFetchObservations, runWithFetchDedupe, setCurrentFetchCacheMode, setCurrentFetchRevalidate, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault, setRefreshStaleFetchesInForeground } from "../shims/fetch-cache.js";
13
11
  import { cacheabilityManifestPageState } from "./cacheability-manifest.js";
12
+ import { isAppPageStaticEligible } from "./app-segment-config.js";
13
+ import { AppElementsWire } from "./app-elements-wire.js";
14
+ import "./app-elements.js";
14
15
  import { VINEXT_RSC_CONTENT_TYPE, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader } from "./app-rsc-cache-busting.js";
15
16
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
17
+ import { getFrameworkLinkHeader } from "./app-response-header-provenance.js";
16
18
  import { resolveUncacheableCacheControl } from "./app-page-response.js";
17
19
  import { buildRscRedirectFlightStream } from "./app-rsc-redirect-flight.js";
18
- import { buildAppPageSpecialErrorResponse, probeAppPageThrownError, resolveAppPageSpecialError } from "./app-page-execution.js";
20
+ import { buildAppPageSpecialErrorResponse, resolveAppPageShellSpecialError, resolveAppPageSpecialError, resolveAppPageSpecialErrorStoredHeaders } from "./app-page-execution.js";
19
21
  import { resolveAppPageTraceOperation } from "./app-page-tracing.js";
20
22
  import { createAppPageTreePath } from "./app-page-route-wiring.js";
21
23
  import { traceResponseStart } from "./response-start-tracing.js";
22
24
  import { buildAppPageTags } from "./implicit-tags.js";
23
25
  import { consumeAppPageRenderObservationState, discardAppPageRenderState } from "./app-page-render-observation.js";
24
- import { isAppPageStaticEligible } from "./app-segment-config.js";
26
+ import { createAppPageRscErrorTracker } from "./app-page-stream.js";
25
27
  import { resolveAppPageParentHttpAccessBoundary, resolveAppPageParentHttpAccessBoundaryModule } from "./app-page-boundary.js";
26
28
  import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
27
29
  import { resolveAppPageNavigationParams } from "./app-page-element-builder.js";
28
- import { createAppPageRscErrorTracker } from "./app-page-stream.js";
29
30
  import { createAppLayoutParamAccessTracker, isAppLayoutObservationUnsafeForStaticReuse } from "./app-layout-param-observation.js";
30
31
  import { resolveAppPageMethodResponse } from "./app-page-method.js";
31
32
  import { buildAppPageElement, resolveAppPageIntercept, resolveAppPageInterceptionRerenderTarget, validateAppPageDynamicParams } from "./app-page-request.js";
@@ -255,7 +256,6 @@ async function dispatchAppPageInner(options) {
255
256
  const pageSearchParams = shouldUseEmptySearchParams ? new URLSearchParams() : options.searchParams;
256
257
  const layoutParamAccess = createAppLayoutParamAccessTracker();
257
258
  const activeLoadingTreePositions = getActiveLoadingTreePositions(route);
258
- const hasActiveLoadingBoundary = activeLoadingTreePositions.length > 0;
259
259
  setCurrentFetchSoftTags(buildAppPageTags(options.cleanPathname, [], route.routeSegments));
260
260
  setCurrentFetchCacheMode(options.fetchCache ?? null);
261
261
  setCurrentFetchRevalidate(currentRevalidateSeconds);
@@ -396,14 +396,16 @@ async function dispatchAppPageInner(options) {
396
396
  isForceStatic: revalidationDynamicConfig === "force-static",
397
397
  observeMetadataSearchParamsAccess: revalidationDynamicConfig !== "force-static",
398
398
  observePageSearchParamsAccess: revalidationDynamicConfig !== "force-static",
399
- serveStreamingMetadata: false
399
+ serveStreamingMetadata: placeGeneratedMetadataInBody,
400
+ placeStreamedMetadataInHead: true
400
401
  });
401
402
  const baseRevalidatedOnError = options.createRscOnErrorHandler(options.cleanPathname, revalidationTarget.route.pattern, { revalidateReason: "stale" });
402
403
  const baseRevalidatedOnSsrError = options.createRscOnErrorHandler(options.cleanPathname, revalidationTarget.route.pattern, {
403
404
  renderSource: "server-rendering",
404
405
  revalidateReason: "stale"
405
406
  });
406
- revalidationRscErrorTracker = createAppPageRscErrorTracker(baseRevalidatedOnError);
407
+ const rscErrorTracker = createAppPageRscErrorTracker(baseRevalidatedOnError);
408
+ revalidationRscErrorTracker = rscErrorTracker;
407
409
  const rendered = await renderAppPageCacheArtifacts({
408
410
  basePath: options.basePath,
409
411
  captureRscData: true,
@@ -416,14 +418,36 @@ async function dispatchAppPageInner(options) {
416
418
  getNavigationContext: options.getNavigationContext,
417
419
  loadSsrHandler: options.loadSsrHandler,
418
420
  mountedSlotsHeader: options.mountedSlotsHeader,
421
+ mirrorNextFlight: () => rscErrorTracker.getCapturedSpecialError() !== null,
419
422
  navigationParams: revalidationTarget.navigationParams,
420
- isCapturedRscError: revalidationRscErrorTracker.isCapturedError,
421
- onError: revalidationRscErrorTracker.onRenderError,
423
+ isCapturedRscError: rscErrorTracker.isCapturedError,
424
+ onError: rscErrorTracker.onRenderError,
422
425
  onSsrError(error) {
423
426
  reportedSsrRevalidationErrors.add(error);
424
427
  return baseRevalidatedOnSsrError(error, void 0, void 0);
425
428
  },
426
429
  reactMaxHeadersLength: options.reactMaxHeadersLength,
430
+ async renderShellSpecialError(error) {
431
+ const specialError = resolveAppPageShellSpecialError(error, rscErrorTracker.getCapturedSpecialErrors(error));
432
+ if (!specialError) return null;
433
+ if (options.isRscRequest) {
434
+ if (specialError.fromMetadata === true) return null;
435
+ return {
436
+ headers: resolveAppPageSpecialErrorStoredHeaders(specialError, options.basePath),
437
+ html: "",
438
+ status: specialError.statusCode
439
+ };
440
+ }
441
+ if (revalidationTarget.route !== route) return null;
442
+ const document = await renderPageSpecialError(options, specialError, false, revalidationTarget.interceptOpts, true);
443
+ if (document.status !== specialError.statusCode) return null;
444
+ return {
445
+ headers: resolveAppPageSpecialErrorStoredHeaders(specialError, options.basePath),
446
+ html: await document.text(),
447
+ linkHeader: getFrameworkLinkHeader(document.headers) ?? void 0,
448
+ status: specialError.statusCode
449
+ };
450
+ },
427
451
  renderToReadableStream: options.renderToReadableStream,
428
452
  rootParams: options.rootParams,
429
453
  route: revalidationTarget.route,
@@ -432,6 +456,7 @@ async function dispatchAppPageInner(options) {
432
456
  });
433
457
  options.clearRequestContext();
434
458
  return {
459
+ headers: rendered.headers,
435
460
  html: rendered.html,
436
461
  htmlRenderObservation: rendered.htmlRenderObservation,
437
462
  linkHeader: rendered.linkHeader,
@@ -440,6 +465,7 @@ async function dispatchAppPageInner(options) {
440
465
  tags: rendered.tags,
441
466
  cacheControl: rendered.cacheControl,
442
467
  revalidateSeconds: revalidationRouteRevalidateSeconds,
468
+ status: rendered.status,
443
469
  usedDynamicApi: rendered.usedDynamicApi
444
470
  };
445
471
  });
@@ -465,6 +491,7 @@ async function dispatchAppPageInner(options) {
465
491
  if (dynamicParamsResponse) {
466
492
  const renderedNotFound = await options.renderHttpAccessFallbackPage(404, { matchedParams: options.params }, options.middlewareContext);
467
493
  const cachePolicy = {
494
+ dynamicStaleTimeSeconds: options.dynamicStaleTimeSeconds,
468
495
  isDraftMode,
469
496
  isDynamicError,
470
497
  isForceDynamic,
@@ -510,7 +537,8 @@ async function dispatchAppPageInner(options) {
510
537
  isForceStatic: sourceDynamicConfig === "force-static",
511
538
  observeMetadataSearchParamsAccess: sourceDynamicConfig !== "force-static",
512
539
  observePageSearchParamsAccess: sourceDynamicConfig !== "force-static",
513
- serveStreamingMetadata: placeGeneratedMetadataInBody
540
+ serveStreamingMetadata: placeGeneratedMetadataInBody,
541
+ placeStreamedMetadataInHead: options.renderWholeDocument === true
514
542
  });
515
543
  },
516
544
  cleanPathname: options.cleanPathname,
@@ -565,19 +593,10 @@ async function dispatchAppPageInner(options) {
565
593
  isForceStatic,
566
594
  observeMetadataSearchParamsAccess: !isForceStatic,
567
595
  observePageSearchParamsAccess: !isForceStatic,
568
- serveStreamingMetadata: placeGeneratedMetadataInBody
596
+ serveStreamingMetadata: placeGeneratedMetadataInBody,
597
+ placeStreamedMetadataInHead: options.renderWholeDocument === true
569
598
  });
570
599
  },
571
- async probePageSpecialError() {
572
- if (hasActiveLoadingBoundary) return null;
573
- const pageError = await probeAppPageThrownError({
574
- probePage: () => options.probePage(pageSearchParams),
575
- runWithSuppressedHookWarning(probe) {
576
- return options.runWithSuppressedHookWarning(probe);
577
- }
578
- });
579
- return resolveAppPageSpecialError(pageError);
580
- },
581
600
  renderErrorBoundaryPage(buildError) {
582
601
  return options.renderErrorBoundaryPage(buildError);
583
602
  },
@@ -645,7 +664,6 @@ async function dispatchAppPageInner(options) {
645
664
  return requestCacheLife.peek();
646
665
  },
647
666
  handlerStart: options.handlerStart,
648
- hasLoadingBoundary: hasActiveLoadingBoundary,
649
667
  omitPendingDynamicCacheState: hasRequestSearchParams && !(isCacheCandidate && !options.isRscRequest),
650
668
  formState: options.formState ?? null,
651
669
  isProgressiveActionRender: options.isProgressiveActionRender === true,
@@ -657,7 +675,9 @@ async function dispatchAppPageInner(options) {
657
675
  isStaticEligible,
658
676
  isCacheCandidate,
659
677
  isPrerender,
678
+ isRoutePPREnabled: options.pprRuntime !== void 0,
660
679
  isSpeculativePrerender,
680
+ renderWholeDocument: options.renderWholeDocument === true && !options.isRscRequest,
661
681
  isProduction: options.isProduction,
662
682
  isRscRequest: options.isRscRequest,
663
683
  traceOperation,
@@ -690,10 +710,6 @@ async function dispatchAppPageInner(options) {
690
710
  probeLayoutAt(layoutIndex) {
691
711
  return options.probeLayoutAt(layoutIndex, layoutParamAccess);
692
712
  },
693
- probePage() {
694
- return options.probePage(pageSearchParams);
695
- },
696
- probePageBeforeRender: options.isRscRequest,
697
713
  classification: {
698
714
  getLayoutId(index) {
699
715
  const treePosition = route.layoutTreePositions?.[index] ?? 0;
@@ -719,8 +735,8 @@ async function dispatchAppPageInner(options) {
719
735
  renderLayoutSpecialError(specialError, layoutIndex) {
720
736
  return renderLayoutSpecialError(options, specialError, layoutIndex, serveStreamingMetadata);
721
737
  },
722
- renderPageSpecialError(specialError) {
723
- return renderPageSpecialError(options, specialError, serveStreamingMetadata, interceptResult.interceptOpts);
738
+ renderPageSpecialError(specialError, renderOptions) {
739
+ return renderPageSpecialError(options, specialError, serveStreamingMetadata, interceptResult.interceptOpts, renderOptions?.isCacheCandidate === true);
724
740
  },
725
741
  renderToReadableStream: options.renderToReadableStream,
726
742
  hasCustomGlobalError: options.hasCustomGlobalError,
@@ -773,7 +789,7 @@ async function renderLayoutSpecialError(options, specialError, layoutIndex, serv
773
789
  specialError
774
790
  });
775
791
  }
776
- async function renderPageSpecialError(options, specialError, serveStreamingMetadata, intercept) {
792
+ async function renderPageSpecialError(options, specialError, serveStreamingMetadata, intercept, isCacheCandidate = false) {
777
793
  return buildAppPageSpecialErrorResponse({
778
794
  basePath: options.basePath,
779
795
  buildRscRedirectFlightStream: (rscOptions) => buildRscRedirectFlightStream({
@@ -802,6 +818,7 @@ async function renderPageSpecialError(options, specialError, serveStreamingMetad
802
818
  const useLayoutAlignedBoundary = boundaryLayoutIndex !== null && (routeBoundaryModule === null || routeBoundaryModule === parentBoundaryModule);
803
819
  const fallbackOptions = {
804
820
  intercept,
821
+ ...isCacheCandidate ? { isCacheCandidate } : {},
805
822
  matchedParams: options.params
806
823
  };
807
824
  if (useLayoutAlignedBoundary && boundaryLayoutIndex !== null) {
@@ -61,6 +61,13 @@ export type AppPagePageRequest<TModule extends AppPageModule = AppPageModule> =
61
61
  observeMetadataSearchParamsAccess?: boolean;
62
62
  /** Whether generated metadata may stream into the response body. */
63
63
  serveStreamingMetadata?: boolean;
64
+ /**
65
+ * Wait for streamed metadata in `<head>`, for a document rendered whole
66
+ * before it's written, such as a background regeneration. Next.js does this
67
+ * for every static or ISR render. Its errors still reach the route's
68
+ * boundaries through the outlet.
69
+ */
70
+ placeStreamedMetadataInHead?: boolean;
64
71
  /** Whether streamed render errors must be sanitized for client transport. */
65
72
  isProduction?: boolean;
66
73
  };