vinext 1.3.1 → 1.4.1

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 (271) hide show
  1. package/README.md +25 -22
  2. package/THIRD_PARTY_LICENSES.md +47 -0
  3. package/dist/_virtual/_rolldown/runtime.js +3 -2
  4. package/dist/build/prerender.js +4 -3
  5. package/dist/build/report.d.ts +0 -14
  6. package/dist/build/report.js +1 -51
  7. package/dist/check.js +4 -7
  8. package/dist/cli.js +3 -0
  9. package/dist/client/dev-error-overlay-store.d.ts +1 -0
  10. package/dist/client/dev-error-overlay.d.ts +2 -0
  11. package/dist/client/dev-error-overlay.js +20 -4
  12. package/dist/client/navigation-runtime.d.ts +13 -1
  13. package/dist/client/navigation-runtime.js +1 -1
  14. package/dist/config/config-matchers.js +2 -0
  15. package/dist/config/destination-params.d.ts +2 -1
  16. package/dist/config/destination-params.js +52 -2
  17. package/dist/config/next-config.d.ts +25 -0
  18. package/dist/config/next-config.js +82 -4
  19. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-codec.js +327 -0
  20. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-data.js +123 -0
  21. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/index.js +29 -0
  22. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/internal.js +134 -0
  23. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-codec.js +50 -0
  24. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data-generated.js +455 -0
  25. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data.js +147 -0
  26. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/big5-added.json.js +169 -0
  27. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp936.json.js +2584 -0
  28. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp949.json.js +2220 -0
  29. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp950.json.js +227 -0
  30. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/eucjp.json.js +425 -0
  31. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gb18030-ranges.json.js +427 -0
  32. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gbk-added.json.js +229 -0
  33. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/shiftjis.json.js +292 -0
  34. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf16.js +106 -0
  35. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf7.js +182 -0
  36. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/bom-handling.js +42 -0
  37. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/extend-node.js +147 -0
  38. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/index.js +94 -0
  39. package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/streams.js +95 -0
  40. package/dist/deps/.pnpm/safer-buffer@2.1.2/deps/safer-buffer/safer.js +45 -0
  41. package/dist/entries/app-rsc-entry.js +17 -49
  42. package/dist/entries/app-rsc-manifest.js +3 -4
  43. package/dist/entries/app-ssr-entry.js +1 -0
  44. package/dist/entries/pages-server-entry.js +36 -9
  45. package/dist/index.js +112 -90
  46. package/dist/init-cloudflare.d.ts +1 -3
  47. package/dist/init-cloudflare.js +10 -48
  48. package/dist/init-platform.d.ts +2 -0
  49. package/dist/init-platform.js +4 -0
  50. package/dist/plugins/extensionless-dynamic-import.js +6 -2
  51. package/dist/plugins/next-intl-catalog.d.ts +12 -0
  52. package/dist/plugins/next-intl-catalog.js +85 -0
  53. package/dist/plugins/pages-node-externals.d.ts +1 -0
  54. package/dist/plugins/pages-node-externals.js +1 -1
  55. package/dist/plugins/strip-server-exports.js +2 -1
  56. package/dist/plugins/use-cache-callable.d.ts +1 -1
  57. package/dist/plugins/use-cache-callable.js +136 -94
  58. package/dist/routing/app-route-graph.d.ts +6 -0
  59. package/dist/routing/app-route-graph.js +9 -1
  60. package/dist/server/api-handler.js +21 -5
  61. package/dist/server/app-bfcache-identity.js +1 -1
  62. package/dist/server/app-browser-entry.js +86 -66
  63. package/dist/server/app-browser-history-controller.d.ts +5 -4
  64. package/dist/server/app-browser-history-controller.js +93 -15
  65. package/dist/server/app-browser-navigation-controller.d.ts +2 -2
  66. package/dist/server/app-browser-navigation-controller.js +1 -2
  67. package/dist/server/app-browser-rsc-redirect.js +7 -7
  68. package/dist/server/app-browser-server-action-client.d.ts +2 -0
  69. package/dist/server/app-browser-server-action-client.js +5 -4
  70. package/dist/server/app-browser-state.d.ts +2 -4
  71. package/dist/server/app-browser-state.js +9 -4
  72. package/dist/server/app-browser-supplemental-refresh.js +16 -1
  73. package/dist/server/app-browser-visible-commit.d.ts +1 -1
  74. package/dist/server/app-browser-visible-commit.js +4 -14
  75. package/dist/server/app-elements-wire.d.ts +6 -38
  76. package/dist/server/app-elements-wire.js +4 -41
  77. package/dist/server/app-elements.d.ts +2 -2
  78. package/dist/server/app-elements.js +2 -2
  79. package/dist/server/app-history-state.d.ts +2 -2
  80. package/dist/server/app-history-state.js +5 -2
  81. package/dist/server/app-mounted-layouts.d.ts +21 -0
  82. package/dist/server/app-mounted-layouts.js +67 -0
  83. package/dist/server/app-optimistic-routing.d.ts +19 -1
  84. package/dist/server/app-optimistic-routing.js +43 -4
  85. package/dist/server/app-page-boundary-render.js +10 -14
  86. package/dist/server/app-page-boundary.js +2 -2
  87. package/dist/server/app-page-cache-finalizer.d.ts +12 -1
  88. package/dist/server/app-page-cache-finalizer.js +70 -29
  89. package/dist/server/app-page-cache.d.ts +13 -1
  90. package/dist/server/app-page-cache.js +31 -9
  91. package/dist/server/app-page-dispatch.d.ts +5 -11
  92. package/dist/server/app-page-dispatch.js +84 -155
  93. package/dist/server/app-page-element-builder.d.ts +2 -2
  94. package/dist/server/app-page-element-builder.js +13 -12
  95. package/dist/server/app-page-execution.d.ts +17 -52
  96. package/dist/server/app-page-execution.js +102 -95
  97. package/dist/server/app-page-head.d.ts +13 -0
  98. package/dist/server/app-page-head.js +44 -16
  99. package/dist/server/app-page-http-access-fallback-metadata.d.ts +1 -0
  100. package/dist/server/app-page-http-access-fallback-metadata.js +2 -2
  101. package/dist/server/app-page-layout-gate.d.ts +35 -0
  102. package/dist/server/app-page-layout-gate.js +50 -0
  103. package/dist/server/app-page-params.d.ts +0 -1
  104. package/dist/server/app-page-params.js +1 -14
  105. package/dist/server/app-page-probe.d.ts +3 -21
  106. package/dist/server/app-page-probe.js +4 -37
  107. package/dist/server/app-page-render.d.ts +2 -13
  108. package/dist/server/app-page-render.js +103 -234
  109. package/dist/server/app-page-request.d.ts +1 -3
  110. package/dist/server/app-page-request.js +1 -1
  111. package/dist/server/app-page-response.js +3 -3
  112. package/dist/server/app-page-route-wiring.d.ts +13 -6
  113. package/dist/server/app-page-route-wiring.js +86 -63
  114. package/dist/server/app-page-rsc-render-status.d.ts +27 -1
  115. package/dist/server/app-page-rsc-render-status.js +121 -13
  116. package/dist/server/app-page-stream.d.ts +12 -8
  117. package/dist/server/app-page-stream.js +4 -3
  118. package/dist/server/app-pages-bridge.d.ts +4 -0
  119. package/dist/server/app-pages-bridge.js +7 -3
  120. package/dist/server/app-render-dependency.d.ts +11 -4
  121. package/dist/server/app-render-dependency.js +86 -38
  122. package/dist/server/app-request-stage-dispatch.js +1 -1
  123. package/dist/server/app-request-stage-independent-entry.js +1 -1
  124. package/dist/server/app-route-handler-cache.js +2 -2
  125. package/dist/server/app-route-handler-dispatch.js +14 -9
  126. package/dist/server/app-route-handler-execution.js +11 -5
  127. package/dist/server/app-route-handler-policy.d.ts +1 -1
  128. package/dist/server/app-route-handler-policy.js +3 -3
  129. package/dist/server/app-route-handler-response.js +1 -1
  130. package/dist/server/app-route-handler-runtime.d.ts +1 -1
  131. package/dist/server/app-route-handler-runtime.js +28 -11
  132. package/dist/server/app-router-entry.js +1 -1
  133. package/dist/server/app-rsc-cache-busting.d.ts +12 -12
  134. package/dist/server/app-rsc-cache-busting.js +31 -72
  135. package/dist/server/app-rsc-error-handler.d.ts +2 -1
  136. package/dist/server/app-rsc-error-handler.js +10 -2
  137. package/dist/server/app-rsc-errors.d.ts +8 -0
  138. package/dist/server/app-rsc-errors.js +11 -1
  139. package/dist/server/app-rsc-handler.d.ts +5 -5
  140. package/dist/server/app-rsc-handler.js +80 -83
  141. package/dist/server/app-rsc-request-normalization.d.ts +10 -16
  142. package/dist/server/app-rsc-request-normalization.js +12 -18
  143. package/dist/server/app-rsc-response-finalizer.js +2 -2
  144. package/dist/server/app-rsc-response-stage.js +9 -15
  145. package/dist/server/app-server-action-execution.d.ts +3 -1
  146. package/dist/server/app-server-action-execution.js +15 -8
  147. package/dist/server/app-ssr-entry.d.ts +8 -0
  148. package/dist/server/app-ssr-entry.js +22 -16
  149. package/dist/server/app-ssr-stream.js +1 -1
  150. package/dist/server/app-visited-response-cache.d.ts +36 -1
  151. package/dist/server/app-visited-response-cache.js +46 -5
  152. package/dist/server/app-worker-stages.d.ts +37 -6
  153. package/dist/server/app-worker-stages.js +81 -9
  154. package/dist/server/artifact-compatibility.d.ts +0 -1
  155. package/dist/server/artifact-compatibility.js +1 -10
  156. package/dist/server/bfcache-identity.d.ts +7 -0
  157. package/dist/server/bfcache-identity.js +10 -1
  158. package/dist/server/cache-proof.d.ts +1 -115
  159. package/dist/server/cache-proof.js +1 -544
  160. package/dist/server/cacheability-manifest.js +1 -2
  161. package/dist/server/cacheability-request.js +13 -8
  162. package/dist/server/dev-origin-check.d.ts +2 -1
  163. package/dist/server/dev-origin-check.js +2 -1
  164. package/dist/server/dev-server.js +6 -4
  165. package/dist/server/headers.d.ts +6 -3
  166. package/dist/server/headers.js +9 -5
  167. package/dist/server/image-optimization.d.ts +5 -0
  168. package/dist/server/image-optimization.js +6 -1
  169. package/dist/server/isr-cache.d.ts +8 -2
  170. package/dist/server/isr-cache.js +30 -2
  171. package/dist/server/metadata-route-response.js +32 -15
  172. package/dist/server/middleware-matcher.js +19 -6
  173. package/dist/server/middleware-runtime.js +6 -2
  174. package/dist/server/multi-stage.d.ts +57 -12
  175. package/dist/server/multi-stage.js +13 -1
  176. package/dist/server/navigation-planner.js +1 -1
  177. package/dist/server/pages-api-route.js +28 -19
  178. package/dist/server/pages-media-type.d.ts +21 -1
  179. package/dist/server/pages-media-type.js +69 -5
  180. package/dist/server/pages-node-compat.d.ts +1 -1
  181. package/dist/server/pages-node-compat.js +54 -27
  182. package/dist/server/pages-page-data.js +2 -1
  183. package/dist/server/pages-page-handler.js +28 -26
  184. package/dist/server/pages-page-response.d.ts +9 -0
  185. package/dist/server/pages-page-response.js +18 -4
  186. package/dist/server/pages-request-pipeline.d.ts +8 -0
  187. package/dist/server/pages-request-pipeline.js +2 -2
  188. package/dist/server/pages-request-stage-entry.js +36 -14
  189. package/dist/server/pages-response-stage-entry.js +9 -3
  190. package/dist/server/pages-router-entry.js +3 -2
  191. package/dist/server/prod-server.d.ts +2 -2
  192. package/dist/server/prod-server.js +47 -9
  193. package/dist/server/request-error-log.d.ts +9 -0
  194. package/dist/server/request-error-log.js +13 -0
  195. package/dist/server/request-pipeline.d.ts +15 -4
  196. package/dist/server/request-pipeline.js +43 -15
  197. package/dist/server/rsc-completion-metadata.js +3 -0
  198. package/dist/server/shared-cache-identity.d.ts +23 -0
  199. package/dist/server/shared-cache-identity.js +36 -0
  200. package/dist/server/static-file-cache.d.ts +9 -0
  201. package/dist/server/static-file-cache.js +13 -2
  202. package/dist/server/worker-stages.d.ts +16 -3
  203. package/dist/server/worker-stages.js +23 -4
  204. package/dist/shims/cache-handler.js +2 -2
  205. package/dist/shims/cache-request-state.d.ts +23 -26
  206. package/dist/shims/cache-request-state.js +22 -57
  207. package/dist/shims/cache-runtime.d.ts +3 -1
  208. package/dist/shims/cache-runtime.js +94 -48
  209. package/dist/shims/cache.d.ts +16 -10
  210. package/dist/shims/cache.js +47 -36
  211. package/dist/shims/cacheability-classification.d.ts +2 -0
  212. package/dist/shims/cdn-cache.d.ts +22 -5
  213. package/dist/shims/client-hook-error.d.ts +2 -0
  214. package/dist/shims/client-hook-error.js +16 -1
  215. package/dist/shims/client-page-root.js +2 -2
  216. package/dist/shims/dynamic.js +9 -6
  217. package/dist/shims/error-boundary.js +2 -2
  218. package/dist/shims/fetch-cache-state.d.ts +5 -1
  219. package/dist/shims/fetch-cache-state.js +1 -3
  220. package/dist/shims/fetch-cache.d.ts +2 -1
  221. package/dist/shims/fetch-cache.js +39 -25
  222. package/dist/shims/form.js +2 -2
  223. package/dist/shims/headers.d.ts +10 -24
  224. package/dist/shims/headers.js +22 -70
  225. package/dist/shims/internal/cache-context-accessor.d.ts +1 -1
  226. package/dist/shims/internal/navigation-untracked.js +1 -1
  227. package/dist/shims/link.js +8 -11
  228. package/dist/shims/metadata.d.ts +23 -21
  229. package/dist/shims/metadata.js +62 -24
  230. package/dist/shims/navigation-server.js +1 -1
  231. package/dist/shims/navigation.d.ts +74 -7
  232. package/dist/shims/navigation.js +184 -31
  233. package/dist/shims/navigation.react-server.js +2 -2
  234. package/dist/shims/request-state-types.d.ts +3 -2
  235. package/dist/shims/slot.d.ts +16 -0
  236. package/dist/shims/slot.js +44 -9
  237. package/dist/shims/unified-request-context.d.ts +7 -1
  238. package/dist/shims/unified-request-context.js +3 -3
  239. package/dist/utils/cache-control-metadata.d.ts +5 -0
  240. package/dist/utils/cache-control-metadata.js +9 -1
  241. package/dist/utils/cache-life-profiles.d.ts +33 -0
  242. package/dist/utils/cache-life-profiles.js +111 -0
  243. package/dist/utils/middleware-request-headers.d.ts +14 -3
  244. package/dist/utils/middleware-request-headers.js +54 -7
  245. package/dist/utils/project.d.ts +2 -2
  246. package/dist/utils/project.js +3 -16
  247. package/dist/utils/regex.d.ts +5 -0
  248. package/dist/utils/regex.js +11 -1
  249. package/dist/utils/text-stream.d.ts +10 -5
  250. package/dist/utils/text-stream.js +6 -6
  251. package/package.json +2 -1
  252. package/dist/build/layout-classification-types.d.ts +0 -60
  253. package/dist/build/layout-classification-types.js +0 -1
  254. package/dist/build/layout-classification.d.ts +0 -62
  255. package/dist/build/layout-classification.js +0 -98
  256. package/dist/build/route-classification-injector.d.ts +0 -33
  257. package/dist/build/route-classification-injector.js +0 -59
  258. package/dist/build/route-classification-manifest.d.ts +0 -54
  259. package/dist/build/route-classification-manifest.js +0 -143
  260. package/dist/server/app-browser-client-reuse-manifest.d.ts +0 -11
  261. package/dist/server/app-browser-client-reuse-manifest.js +0 -101
  262. package/dist/server/app-layout-param-observation.d.ts +0 -42
  263. package/dist/server/app-layout-param-observation.js +0 -168
  264. package/dist/server/client-reuse-manifest.d.ts +0 -103
  265. package/dist/server/client-reuse-manifest.js +0 -209
  266. package/dist/server/skip-cache-proof.d.ts +0 -60
  267. package/dist/server/skip-cache-proof.js +0 -168
  268. package/dist/server/static-layout-client-reuse-proof.d.ts +0 -14
  269. package/dist/server/static-layout-client-reuse-proof.js +0 -33
  270. package/dist/utils/sorted-array.d.ts +0 -8
  271. package/dist/utils/sorted-array.js +0 -20
@@ -67,55 +67,79 @@ function applyRscRenderStatus(outcome, renderStatus) {
67
67
  ...renderStatus.headers ? { headers: renderStatus.headers } : {}
68
68
  };
69
69
  }
70
+ /** Hand an adapter the document; its failure never holds back admission. */
71
+ function settleAdmittedDocument(capture, document) {
72
+ try {
73
+ capture?.(document);
74
+ } catch (error) {
75
+ console.error("[vinext] CDN adapter document capture error:", error);
76
+ }
77
+ }
70
78
  function finalizeEvaluatedAppPageResponse(response, options) {
71
79
  if (!isRouteCacheabilityEvaluation()) return null;
72
80
  const complete = deferRouteCacheability();
73
- if (!complete) return response;
81
+ if (!complete) {
82
+ settleAdmittedDocument(options.captureAdmittedDocument, null);
83
+ return response;
84
+ }
74
85
  captureRouteCacheabilityResponsePolicy(captureCdnResponsePolicyHeaders(response.headers));
86
+ const admit = (renderStatus) => {
87
+ const observationState = options.consumeRenderObservationState?.();
88
+ const cacheControl = resolveAppPageCacheControl({
89
+ expireSeconds: options.expireSeconds,
90
+ requestCacheLife: options.getRequestCacheLife?.(),
91
+ revalidateSeconds: options.revalidateSeconds
92
+ });
93
+ const outcome = cacheControl ? {
94
+ cacheable: true,
95
+ cacheControl: appPageCacheControlHeader(cacheControl),
96
+ ...observationState && !observationState.requestApis.includes("searchParams") ? { searchParamsUnread: true } : {},
97
+ ...cacheControl.stale !== void 0 ? { staleTimeSeconds: cacheControl.stale } : {},
98
+ tags: options.getPageTags()
99
+ } : {
100
+ cacheable: false,
101
+ reason: "render did not produce a cache policy"
102
+ };
103
+ const admitted = renderStatus ? applyRscRenderStatus(outcome, renderStatus) : outcome;
104
+ settleAdmittedDocument(options.captureAdmittedDocument, admitted.cacheable && admitted.searchParamsUnread === true && renderStatus?.kind === "page" ? renderStatus.document ?? null : null);
105
+ complete(admitted);
106
+ };
75
107
  let completed = false;
76
108
  const finish = () => {
77
109
  if (completed) return;
78
110
  completed = true;
79
- const observationState = options.consumeRenderObservationState?.();
80
- let outcome;
81
- if (options.capturedDynamicUsageBeforeContextCleanup?.() === true || options.consumeDynamicUsage()) outcome = {
111
+ let ineligible;
112
+ if (options.capturedDynamicUsageBeforeContextCleanup?.() === true || options.consumeDynamicUsage()) ineligible = {
82
113
  cacheable: false,
83
114
  dynamicUsage: true,
84
115
  reason: "dynamic API used during render"
85
116
  };
86
- else if (options.isStaticEligible === false) outcome = {
117
+ else if (options.isStaticEligible === false) ineligible = {
87
118
  cacheable: false,
88
119
  reason: "route is not statically generated"
89
120
  };
90
- else if (response.headers.has("set-cookie") || hasExplicitNonCacheableResponsePolicy(response.headers)) outcome = {
121
+ else if (response.headers.has("set-cookie") || hasExplicitNonCacheableResponsePolicy(response.headers)) ineligible = {
91
122
  cacheable: false,
92
123
  reason: "response explicitly opts out of shared caching"
93
124
  };
94
- else {
95
- const cacheControl = resolveAppPageCacheControl({
96
- expireSeconds: options.expireSeconds,
97
- requestCacheLife: options.getRequestCacheLife?.(),
98
- revalidateSeconds: options.revalidateSeconds
99
- });
100
- outcome = cacheControl ? {
101
- cacheable: true,
102
- cacheControl: appPageCacheControlHeader(cacheControl),
103
- ...observationState && !observationState.requestApis.includes("searchParams") ? { searchParamsUnread: true } : {},
104
- tags: options.getPageTags()
105
- } : {
106
- cacheable: false,
107
- reason: "render did not produce a cache policy"
108
- };
125
+ if (ineligible) {
126
+ options.consumeRenderObservationState?.();
127
+ settleAdmittedDocument(options.captureAdmittedDocument, null);
128
+ complete(ineligible);
129
+ return;
109
130
  }
110
- if (outcome.cacheable && options.resolveRscRenderStatus) {
111
- const cacheableOutcome = outcome;
112
- options.resolveRscRenderStatus().then((renderStatus) => complete(applyRscRenderStatus(cacheableOutcome, renderStatus)), () => complete({
113
- cacheable: false,
114
- reason: "render status could not be resolved"
115
- }));
131
+ if (!options.resolveRscRenderStatus) {
132
+ admit();
116
133
  return;
117
134
  }
118
- complete(outcome);
135
+ options.resolveRscRenderStatus().then(admit, () => {
136
+ options.consumeRenderObservationState?.();
137
+ settleAdmittedDocument(options.captureAdmittedDocument, null);
138
+ complete({
139
+ cacheable: false,
140
+ reason: "render status could not be resolved"
141
+ });
142
+ });
119
143
  };
120
144
  if (!response.body) {
121
145
  finish();
@@ -230,6 +254,7 @@ function finalizeAppPageRscCacheResponse(response, options) {
230
254
  options.capturedRscDataPromise?.catch(() => {});
231
255
  return probeResponse;
232
256
  }
257
+ settleAdmittedDocument(options.captureAdmittedDocument, null);
233
258
  scheduleAppPageRscCacheWrite(options);
234
259
  const isUncacheableVariant = Boolean(options.mountedSlotsHeader) || options.bypassInterceptionContextCache === true;
235
260
  if (options.preserveClientResponseHeaders === true && !isUncacheableVariant) return response;
@@ -253,6 +278,7 @@ function scheduleAppPageRscCacheWrite(options) {
253
278
  options.isrDebug?.("RSC cache write skipped (dynamic usage during render)", rscKey);
254
279
  return;
255
280
  }
281
+ const renderStatus = await options.resolveRscRenderStatus?.() ?? { kind: "page" };
256
282
  const cacheControl = resolveAppPageCacheControl({
257
283
  expireSeconds: options.expireSeconds,
258
284
  requestCacheLife: options.getRequestCacheLife?.(),
@@ -272,7 +298,6 @@ function scheduleAppPageRscCacheWrite(options) {
272
298
  options.isrDebug?.("RSC cache write skipped (searchParams not proven unread)", rscKey);
273
299
  return;
274
300
  }
275
- const renderStatus = await options.resolveRscRenderStatus?.() ?? { kind: "page" };
276
301
  if (renderStatus.kind === "unstorable") {
277
302
  options.isrDebug?.("RSC cache write skipped (unstorable special error)", rscKey);
278
303
  return;
@@ -282,6 +307,22 @@ function scheduleAppPageRscCacheWrite(options) {
282
307
  tags: pageTags
283
308
  });
284
309
  options.isrDebug?.("RSC cache written", rscKey);
310
+ const document = renderStatus.kind === "page" ? renderStatus.document : void 0;
311
+ if (!document || !options.isrHtmlKey || !options.createHtmlRenderObservation) return;
312
+ const htmlKey = options.isrHtmlKey(options.cleanPathname);
313
+ const htmlRenderObservation = options.createHtmlRenderObservation({
314
+ cacheTags: pageTags,
315
+ state: observationState
316
+ });
317
+ if (!hasQueryInvariantRenderProof(htmlRenderObservation)) {
318
+ options.isrDebug?.("HTML cache write skipped (searchParams not proven unread)", htmlKey);
319
+ return;
320
+ }
321
+ await options.isrSet(htmlKey, buildAppPageCacheValue(document.html, void 0, 200, htmlRenderObservation, document.linkHeader ? { link: document.linkHeader } : void 0), {
322
+ cacheControl,
323
+ tags: pageTags
324
+ });
325
+ options.isrDebug?.("HTML cache written", htmlKey);
285
326
  } catch (cacheError) {
286
327
  console.error("[vinext] ISR RSC cache write error:", cacheError);
287
328
  }
@@ -83,7 +83,19 @@ type ReadAppPageCacheResponseOptions = {
83
83
  renderMode?: AppRscRenderMode;
84
84
  expireSeconds?: number;
85
85
  revalidateSeconds: number;
86
- renderFreshPageForCache: () => Promise<AppPageCacheRenderResult>;
86
+ /**
87
+ * Whether this is an RSC request Next.js renders dynamically under PPR (one
88
+ * that is not a prefetch, for a path not generated at build time), and so
89
+ * never regenerates the page's document.
90
+ */
91
+ isDynamicRscRequest?: boolean;
92
+ /**
93
+ * Renders the page for its cache entries. `renderDocument` asks for the
94
+ * document as an HTML request renders it, to be stored beside the RSC payload.
95
+ */
96
+ renderFreshPageForCache: (options: {
97
+ renderDocument: boolean;
98
+ }) => Promise<AppPageCacheRenderResult>;
87
99
  scheduleBackgroundRegeneration: AppPageBackgroundRegenerator;
88
100
  };
89
101
  type ReadAppPageFallbackShellCacheResponseOptions = {
@@ -6,12 +6,12 @@ import { buildAppPageCacheValue, isrCacheControl, resolveRouteExpireSeconds } fr
6
6
  import { resolveClientStaleTimeSeconds } from "../utils/cache-control-metadata.js";
7
7
  import { encodeCacheTag } from "../utils/encode-cache-tag.js";
8
8
  import { setCacheStateHeaders } from "./cache-headers.js";
9
- import { VINEXT_RSC_CONTENT_TYPE, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader } from "./app-rsc-cache-busting.js";
10
- import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
11
9
  import { markFrameworkLinkHeaders } from "./app-response-header-provenance.js";
12
- import { applyClientStaleTimeHeader, applyEdgeRuntimeHeader } from "./app-page-response.js";
10
+ import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
11
+ import { VINEXT_RSC_CONTENT_TYPE, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader } from "./app-rsc-cache-busting.js";
13
12
  import { isAppPprDynamicFallbackShellHtml } from "./app-ppr-fallback-shell.js";
14
13
  import { hasQueryInvariantRenderProof } from "./cache-proof.js";
14
+ import { applyClientStaleTimeHeader, applyEdgeRuntimeHeader } from "./app-page-response.js";
15
15
  import { finalizeAppPageHtmlCacheResponse, finalizeAppPageRscCacheResponse, scheduleAppPageRscCacheWrite } from "./app-page-cache-finalizer.js";
16
16
  import { buildPageCacheTags } from "./implicit-tags.js";
17
17
  //#region src/server/app-page-cache.ts
@@ -92,6 +92,25 @@ function resolveRegenerationFailureCacheControl(previous) {
92
92
  ...previous.stale === void 0 ? {} : { stale: previous.stale }
93
93
  };
94
94
  }
95
+ /**
96
+ * Next.js stamps every prerender with the stale time it collected. A render
97
+ * that made no `cacheLife` claim keeps the `INFINITE_CACHE` sentinel, which
98
+ * resolves to `experimental.staleTimes.static` (`createSelectStaleTime` in
99
+ * `server/app-render/stale-time.ts`, applied by
100
+ * `applyMetadataFromPrerenderResult` in `app-render.tsx`). Its client only
101
+ * caches a navigation response for that long under
102
+ * `experimental.cachedNavigations` (`fetch-server-response.ts`); otherwise the
103
+ * value only dates prefetches. vinext's client reuses navigation responses for
104
+ * any advertised stale time, so the unclaimed value is only advertised when
105
+ * cached navigations are on.
106
+ */
107
+ function resolveUnclaimedPrerenderStaleTimeSeconds(isRoutePPREnabled) {
108
+ if (isRoutePPREnabled !== true) return void 0;
109
+ if (String(process.env.__NEXT_EXPERIMENTAL_CACHED_NAVIGATIONS) !== "true") return void 0;
110
+ const raw = process.env.__NEXT_CLIENT_ROUTER_STATIC_STALETIME;
111
+ const seconds = raw === void 0 || raw === "" ? 300 : Number(raw);
112
+ return Number.isFinite(seconds) && seconds >= 0 ? Math.floor(seconds) : void 0;
113
+ }
95
114
  function isRedirectStatus(status) {
96
115
  return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
97
116
  }
@@ -108,7 +127,7 @@ function buildAppPageCachedResponse(cachedValue, options) {
108
127
  expireSeconds: options.expireSeconds,
109
128
  cacheControlMeta: options.cacheControl
110
129
  });
111
- const staleTimeSeconds = resolveClientStaleTimeSeconds(options.cacheControl);
130
+ const staleTimeSeconds = resolveClientStaleTimeSeconds(options.cacheControl) ?? resolveUnclaimedPrerenderStaleTimeSeconds(options.isRoutePPREnabled);
112
131
  if (options.isRscRequest) {
113
132
  if (!cachedValue.rscData) return null;
114
133
  const rscHeaders = buildAppPageCachedHeaders({
@@ -276,8 +295,10 @@ async function readAppPageCacheResponse(options) {
276
295
  console.error(`[vinext] Failed to keep the previous entry for ${key}:`, storeError);
277
296
  }
278
297
  };
298
+ const regeneratesDocument = !options.isRscRequest || options.isDynamicRscRequest !== true && isrKey === options.isrRscKey(options.cleanPathname, null);
299
+ const htmlKey = options.isRscRequest ? regeneratesDocument ? options.isrHtmlKey(options.cleanPathname) : null : isrKey;
279
300
  const regenerate = async () => {
280
- const revalidatedPage = await options.renderFreshPageForCache();
301
+ const revalidatedPage = await options.renderFreshPageForCache({ renderDocument: regeneratesDocument });
281
302
  const cacheControl = resolveRegeneratedAppPageCacheControl({
282
303
  expireSeconds: options.expireSeconds,
283
304
  renderCacheControl: revalidatedPage.cacheControl,
@@ -285,7 +306,8 @@ async function readAppPageCacheResponse(options) {
285
306
  });
286
307
  if (options.isRoutePPREnabled !== true && (revalidatedPage.usedDynamicApi || cacheControl.revalidate === 0)) throw new Error(`Page changed from static to dynamic at runtime ${options.cleanPathname}
287
308
  see more here https://nextjs.org/docs/messages/app-static-to-dynamic-error`);
288
- if (!hasQueryInvariantRenderProof(revalidatedPage.rscRenderObservation) || !options.isRscRequest && !hasQueryInvariantRenderProof(revalidatedPage.htmlRenderObservation)) {
309
+ const documentKey = options.isRscRequest && revalidatedPage.html === "" ? null : htmlKey;
310
+ if (!hasQueryInvariantRenderProof(revalidatedPage.rscRenderObservation) || documentKey !== null && !hasQueryInvariantRenderProof(revalidatedPage.htmlRenderObservation)) {
289
311
  options.isrDebug?.("regen write skipped (searchParams not proven unread)", isrKey);
290
312
  return;
291
313
  }
@@ -304,15 +326,15 @@ see more here https://nextjs.org/docs/messages/app-static-to-dynamic-error`);
304
326
  };
305
327
  const status = revalidatedPage.status ?? 200;
306
328
  if (!await store(rscKey, buildAppPageCacheValue("", revalidatedPage.rscData, status, revalidatedPage.rscRenderObservation, revalidatedPage.headers))) return;
307
- if (!options.isRscRequest) {
308
- if (!await store(isrKey, buildAppPageCacheValue(revalidatedPage.html, void 0, status, revalidatedPage.htmlRenderObservation, revalidatedPage.linkHeader ? {
329
+ if (documentKey !== null) {
330
+ if (!await store(documentKey, buildAppPageCacheValue(revalidatedPage.html, void 0, status, revalidatedPage.htmlRenderObservation, revalidatedPage.linkHeader ? {
309
331
  ...revalidatedPage.headers,
310
332
  link: revalidatedPage.linkHeader
311
333
  } : revalidatedPage.headers))) return;
312
334
  }
313
335
  options.isrDebug?.("regen complete", options.cleanPathname);
314
336
  };
315
- options.scheduleBackgroundRegeneration(isrKey, async () => {
337
+ options.scheduleBackgroundRegeneration(htmlKey ?? isrKey, async () => {
316
338
  try {
317
339
  await regenerate();
318
340
  } catch (error) {
@@ -1,14 +1,11 @@
1
- import { ClassificationReason } from "../build/layout-classification-types.js";
2
- import { ClientReuseManifestParseResult } from "./client-reuse-manifest.js";
3
1
  import { AppOutgoingElements } from "./app-elements-wire.js";
4
2
  import "./app-elements.js";
5
3
  import { AppRscRenderMode } from "./app-rsc-render-mode.js";
6
4
  import { NavigationContext } from "../shims/navigation-context-state.js";
7
5
  import "../shims/navigation.js";
8
- import { AppPageFontPreload, LayoutClassificationOptions } from "./app-page-execution.js";
6
+ import { AppPageFontPreload } from "./app-page-execution.js";
9
7
  import { AppPageMiddlewareContext } from "./app-page-response.js";
10
8
  import { AppPageFallbackRouteHead, AppPagePreparedRouteHead } from "./app-page-head.js";
11
- import { AppLayoutParamAccessTracker } from "./app-layout-param-observation.js";
12
9
  import { RootParams } from "../shims/root-params.js";
13
10
  import { AppPageSsrHandler } from "./app-page-stream.js";
14
11
  import { AppRenderErrorContextOverrides } from "./app-rsc-error-handler.js";
@@ -107,8 +104,6 @@ type AppPageDispatchSlot = {
107
104
  slotParamNames?: readonly string[] | null;
108
105
  };
109
106
  export type AppPageDispatchRoute = {
110
- __buildTimeClassifications?: LayoutClassificationOptions["buildTimeClassifications"];
111
- __buildTimeReasons?: LayoutClassificationOptions["buildTimeReasons"];
112
107
  error?: AppPageModule | null;
113
108
  errors?: readonly (AppPageModule | null | undefined)[];
114
109
  forbidden?: AppPageModule | null;
@@ -161,9 +156,11 @@ export type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
161
156
  * `next.config`. Undefined falls back to the React default downstream.
162
157
  */
163
158
  reactMaxHeadersLength?: number;
164
- buildPageElement: (route: TRoute, params: AppPageParams, opts: AppPageDispatchInterceptOptions | undefined, searchParams: URLSearchParams, layoutParamAccess?: AppLayoutParamAccessTracker, options?: {
159
+ buildPageElement: (route: TRoute, params: AppPageParams, opts: AppPageDispatchInterceptOptions | undefined, searchParams: URLSearchParams, options?: {
165
160
  isForceStatic?: boolean;
166
161
  isUncacheableRender?: boolean;
162
+ /** Layouts the navigating client holds, which the render may leave out. */
163
+ mountedLayouts?: ReadonlySet<string> | null;
167
164
  observeMetadataSearchParamsAccess?: boolean;
168
165
  observePageSearchParamsAccess?: boolean;
169
166
  serveStreamingMetadata?: boolean;
@@ -171,12 +168,10 @@ export type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
171
168
  /** Receives the route's head once the render starts resolving it. */
172
169
  onHeadPrepared?: (head: AppPagePreparedRouteHead) => void;
173
170
  }) => Promise<AppPageElement>;
174
- clientReuseManifest?: ClientReuseManifestParseResult;
175
171
  cleanPathname: string;
176
172
  displayPathname?: string;
177
173
  clearRequestContext: () => void;
178
174
  createRscOnErrorHandler: (pathname: string, routePath: string, overrides?: AppRenderErrorContextOverrides) => AppPageBoundaryOnError;
179
- debugClassification?: (layoutId: string, reason: ClassificationReason) => void;
180
175
  draftModeSecret: string;
181
176
  dynamicConfig?: string;
182
177
  dynamicStaleTimeSeconds?: number;
@@ -205,7 +200,6 @@ export type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
205
200
  hasGenerateStaticParams: boolean;
206
201
  /** Whether any segment of the route exports `generateStaticParams`. */
207
202
  hasAnyGenerateStaticParams: boolean;
208
- hasCustomGlobalError?: boolean;
209
203
  hasPageDefaultExport: boolean;
210
204
  hasPageModule: boolean;
211
205
  handlerStart: number;
@@ -249,7 +243,7 @@ export type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
249
243
  skipStaticParamsValidation?: boolean;
250
244
  staticParamsValidationParams?: AppPageParams;
251
245
  rootParams?: RootParams;
252
- probeLayoutAt: (layoutIndex: number, layoutParamAccess?: AppLayoutParamAccessTracker) => unknown;
246
+ probeLayoutAt: (layoutIndex: number) => unknown;
253
247
  expireSeconds?: number;
254
248
  renderErrorBoundaryPage: (error: unknown, errorOrigin?: "rsc" | "ssr") => Promise<Response | null>;
255
249
  renderHttpAccessFallbackPage: (statusCode: number, opts: {