vinext 1.1.0 → 1.2.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 (234) hide show
  1. package/README.md +21 -9
  2. package/dist/build/client-build-config.d.ts +10 -0
  3. package/dist/build/client-build-config.js +18 -2
  4. package/dist/build/pages-client-assets-module.d.ts +8 -0
  5. package/dist/build/pages-client-assets-module.js +21 -1
  6. package/dist/build/prerender-paths.js +5 -3
  7. package/dist/build/run-prerender.js +1 -1
  8. package/dist/build/ssr-manifest.d.ts +2 -0
  9. package/dist/build/ssr-manifest.js +6 -2
  10. package/dist/check.js +7 -6
  11. package/dist/cli.js +2 -1
  12. package/dist/client/client-redirect-matcher.d.ts +14 -0
  13. package/dist/client/client-redirect-matcher.js +37 -0
  14. package/dist/client/client-redirects.d.ts +27 -0
  15. package/dist/client/client-redirects.js +28 -0
  16. package/dist/client/client-rewrites.d.ts +2 -1
  17. package/dist/client/client-rewrites.js +1 -1
  18. package/dist/config/config-matchers.d.ts +26 -11
  19. package/dist/config/config-matchers.js +78 -81
  20. package/dist/config/destination-params.d.ts +47 -0
  21. package/dist/config/destination-params.js +116 -0
  22. package/dist/config/next-config.d.ts +7 -0
  23. package/dist/config/next-config.js +3 -0
  24. package/dist/entries/app-rsc-entry.d.ts +4 -0
  25. package/dist/entries/app-rsc-entry.js +20 -6
  26. package/dist/entries/pages-client-entry.js +3 -1
  27. package/dist/entries/pages-server-entry.js +13 -37
  28. package/dist/index.d.ts +3 -1
  29. package/dist/index.js +134 -43
  30. package/dist/init-cloudflare.d.ts +9 -0
  31. package/dist/init-cloudflare.js +107 -31
  32. package/dist/init-platform.d.ts +4 -0
  33. package/dist/init-platform.js +27 -2
  34. package/dist/init.d.ts +1 -0
  35. package/dist/init.js +67 -3
  36. package/dist/plugins/ast-scope.d.ts +7 -0
  37. package/dist/plugins/ast-scope.js +59 -3
  38. package/dist/plugins/cache-flight-codec.d.ts +1 -1
  39. package/dist/plugins/dynamic-preload-metadata.d.ts +1 -1
  40. package/dist/plugins/dynamic-preload-metadata.js +9 -8
  41. package/dist/plugins/ignore-dynamic-requests.d.ts +1 -1
  42. package/dist/plugins/ignore-dynamic-requests.js +3 -4
  43. package/dist/plugins/middleware-server-only.d.ts +5 -4
  44. package/dist/plugins/middleware-server-only.js +8 -5
  45. package/dist/plugins/pages-node-externals.js +1 -1
  46. package/dist/plugins/rsc-scan-glob-imports.d.ts +19 -0
  47. package/dist/plugins/rsc-scan-glob-imports.js +50 -0
  48. package/dist/plugins/strip-server-exports.js +262 -98
  49. package/dist/plugins/transform-result.d.ts +9 -5
  50. package/dist/plugins/transitive-externals.js +1 -1
  51. package/dist/plugins/typeof-window.d.ts +2 -2
  52. package/dist/plugins/use-cache-callable.js +8 -2
  53. package/dist/plugins/worker-server-only-imports.d.ts +20 -0
  54. package/dist/plugins/worker-server-only-imports.js +31 -0
  55. package/dist/plugins/worker-use-server.d.ts +25 -0
  56. package/dist/plugins/worker-use-server.js +129 -0
  57. package/dist/server/api-handler.d.ts +1 -0
  58. package/dist/server/api-handler.js +2 -1
  59. package/dist/server/app-browser-action-result.d.ts +1 -1
  60. package/dist/server/app-browser-action-result.js +9 -2
  61. package/dist/server/app-browser-navigation-controller.js +1 -1
  62. package/dist/server/app-browser-server-action-client.js +1 -1
  63. package/dist/server/app-middleware.d.ts +11 -0
  64. package/dist/server/app-middleware.js +17 -2
  65. package/dist/server/app-page-cache.d.ts +1 -1
  66. package/dist/server/app-page-cache.js +1 -1
  67. package/dist/server/app-page-dispatch.d.ts +3 -1
  68. package/dist/server/app-page-dispatch.js +4 -3
  69. package/dist/server/app-page-ppr-runtime.js +1 -1
  70. package/dist/server/app-page-render-observation.js +1 -1
  71. package/dist/server/app-page-request.js +53 -15
  72. package/dist/server/app-page-route-wiring.js +2 -2
  73. package/dist/server/app-pages-bridge.d.ts +1 -1
  74. package/dist/server/app-pages-bridge.js +2 -3
  75. package/dist/server/app-prerender-endpoints.js +9 -6
  76. package/dist/server/app-request-stage-dispatch.js +6 -2
  77. package/dist/server/app-request-stage-independent-entry.js +25 -5
  78. package/dist/server/app-response-stage-entry.js +10 -2
  79. package/dist/server/app-route-handler-cache.d.ts +1 -0
  80. package/dist/server/app-route-handler-cache.js +1 -0
  81. package/dist/server/app-route-handler-dispatch.d.ts +1 -0
  82. package/dist/server/app-route-handler-dispatch.js +5 -2
  83. package/dist/server/app-route-handler-execution.d.ts +1 -0
  84. package/dist/server/app-route-handler-execution.js +1 -0
  85. package/dist/server/app-route-handler-runtime.d.ts +4 -1
  86. package/dist/server/app-route-handler-runtime.js +45 -24
  87. package/dist/server/app-router-entry.js +24 -5
  88. package/dist/server/app-rsc-cache-busting.js +1 -1
  89. package/dist/server/app-rsc-errors.js +20 -16
  90. package/dist/server/app-rsc-handler.d.ts +7 -0
  91. package/dist/server/app-rsc-handler.js +85 -35
  92. package/dist/server/app-rsc-response-stage.js +4 -2
  93. package/dist/server/app-segment-config.d.ts +2 -1
  94. package/dist/server/app-server-action-execution.d.ts +2 -1
  95. package/dist/server/app-server-action-execution.js +61 -22
  96. package/dist/server/app-ssr-entry.js +2 -1
  97. package/dist/server/app-worker-stages.d.ts +5 -0
  98. package/dist/server/app-worker-stages.js +1 -1
  99. package/dist/server/cacheability-request.js +2 -2
  100. package/dist/server/client-build-files.d.ts +16 -0
  101. package/dist/server/client-build-files.js +36 -0
  102. package/dist/server/client-reuse-manifest.js +1 -1
  103. package/dist/server/dev-server.js +38 -27
  104. package/dist/server/dev-stack-sourcemap.js +18 -23
  105. package/dist/server/document-initial-head.d.ts +0 -11
  106. package/dist/server/document-initial-head.js +1 -1
  107. package/dist/server/forwarded-middleware-context.d.ts +5 -0
  108. package/dist/server/forwarded-middleware-context.js +22 -0
  109. package/dist/server/headers.d.ts +4 -1
  110. package/dist/server/headers.js +4 -1
  111. package/dist/server/http-conditional.d.ts +11 -0
  112. package/dist/server/http-conditional.js +10 -1
  113. package/dist/server/http-error-responses.d.ts +1 -1
  114. package/dist/server/image-optimization.d.ts +38 -0
  115. package/dist/server/image-optimization.js +93 -4
  116. package/dist/server/isr-cache.d.ts +10 -0
  117. package/dist/server/isr-cache.js +41 -6
  118. package/dist/server/metadata-route-response.js +9 -8
  119. package/dist/server/middleware-matcher.d.ts +2 -0
  120. package/dist/server/middleware-matcher.js +23 -2
  121. package/dist/server/middleware-runtime.d.ts +13 -0
  122. package/dist/server/middleware-runtime.js +33 -20
  123. package/dist/server/middleware.d.ts +1 -1
  124. package/dist/server/middleware.js +3 -1
  125. package/dist/server/multi-stage.d.ts +11 -0
  126. package/dist/server/normalize-path.d.ts +0 -13
  127. package/dist/server/normalize-path.js +1 -34
  128. package/dist/server/pages-api-route.d.ts +3 -2
  129. package/dist/server/pages-api-route.js +4 -3
  130. package/dist/server/pages-cache-tag.d.ts +12 -0
  131. package/dist/server/pages-cache-tag.js +19 -0
  132. package/dist/server/pages-client-assets.d.ts +2 -0
  133. package/dist/server/pages-data-route.d.ts +10 -0
  134. package/dist/server/pages-data-route.js +19 -2
  135. package/dist/server/pages-document-asset-props.d.ts +5 -1
  136. package/dist/server/pages-document-asset-props.js +13 -5
  137. package/dist/server/pages-document-splice.d.ts +19 -0
  138. package/dist/server/pages-document-splice.js +55 -0
  139. package/dist/server/pages-i18n.d.ts +12 -1
  140. package/dist/server/pages-i18n.js +18 -4
  141. package/dist/server/pages-node-compat.d.ts +16 -5
  142. package/dist/server/pages-node-compat.js +20 -12
  143. package/dist/server/pages-page-data.d.ts +32 -24
  144. package/dist/server/pages-page-data.js +50 -120
  145. package/dist/server/pages-page-handler.d.ts +0 -6
  146. package/dist/server/pages-page-handler.js +188 -126
  147. package/dist/server/pages-page-response.d.ts +12 -6
  148. package/dist/server/pages-page-response.js +41 -34
  149. package/dist/server/pages-request-pipeline.d.ts +10 -2
  150. package/dist/server/pages-request-pipeline.js +37 -18
  151. package/dist/server/pages-request-stage-entry.d.ts +6 -0
  152. package/dist/server/pages-request-stage-entry.js +71 -12
  153. package/dist/server/pages-response-stage-entry.js +4 -0
  154. package/dist/server/pages-revalidate.js +1 -1
  155. package/dist/server/pages-router-entry.js +4 -3
  156. package/dist/server/prerender-manifest.d.ts +3 -3
  157. package/dist/server/prerender-manifest.js +4 -3
  158. package/dist/server/prerender-work-unit-setup.js +4 -0
  159. package/dist/server/prod-server.d.ts +12 -0
  160. package/dist/server/prod-server.js +199 -69
  161. package/dist/server/proper-error.d.ts +4 -0
  162. package/dist/server/proper-error.js +31 -0
  163. package/dist/server/request-pipeline.d.ts +4 -1
  164. package/dist/server/request-pipeline.js +3 -2
  165. package/dist/server/revalidation-request.d.ts +1 -0
  166. package/dist/server/revalidation-request.js +1 -1
  167. package/dist/server/rsc-stream-hints.js +31 -2
  168. package/dist/server/seed-cache.d.ts +1 -0
  169. package/dist/server/seed-cache.js +5 -4
  170. package/dist/server/server-reference-loader.d.ts +4 -0
  171. package/dist/server/server-reference-loader.js +29 -0
  172. package/dist/server/socket-error-backstop.d.ts +9 -1
  173. package/dist/server/socket-error-backstop.js +46 -17
  174. package/dist/server/static-file-signal.d.ts +15 -4
  175. package/dist/server/static-file-signal.js +46 -12
  176. package/dist/server/worker-image-optimization.d.ts +34 -0
  177. package/dist/server/worker-image-optimization.js +86 -0
  178. package/dist/server/worker-stages.d.ts +1 -1
  179. package/dist/server/worker-stages.js +2 -2
  180. package/dist/server/worker-utils.d.ts +8 -3
  181. package/dist/server/worker-utils.js +12 -7
  182. package/dist/shims/app-router-scroll.js +4 -1
  183. package/dist/shims/app-router-tree-context.d.ts +5 -0
  184. package/dist/shims/app-router-tree-context.js +27 -0
  185. package/dist/shims/cache-callable-runtime.d.ts +4 -2
  186. package/dist/shims/cache-callable-runtime.js +21 -12
  187. package/dist/shims/cache-handler.js +1 -9
  188. package/dist/shims/cache-runtime.d.ts +6 -1
  189. package/dist/shims/cache-runtime.js +2 -1
  190. package/dist/shims/cache.d.ts +2 -2
  191. package/dist/shims/cache.js +40 -13
  192. package/dist/shims/cdn-cache.d.ts +8 -0
  193. package/dist/shims/cdn-cache.js +17 -1
  194. package/dist/shims/disable-smooth-scroll.d.ts +3 -0
  195. package/dist/shims/disable-smooth-scroll.js +36 -0
  196. package/dist/shims/document-placeholders.d.ts +19 -0
  197. package/dist/shims/document-placeholders.js +45 -0
  198. package/dist/shims/document.js +21 -5
  199. package/dist/shims/dynamic-preload-chunks.d.ts +1 -0
  200. package/dist/shims/dynamic-preload-chunks.js +13 -9
  201. package/dist/shims/dynamic.d.ts +1 -1
  202. package/dist/shims/dynamic.js +60 -8
  203. package/dist/shims/fetch-cache-state.d.ts +66 -0
  204. package/dist/shims/fetch-cache-state.js +92 -0
  205. package/dist/shims/fetch-cache.d.ts +3 -67
  206. package/dist/shims/fetch-cache.js +160 -125
  207. package/dist/shims/head.d.ts +10 -6
  208. package/dist/shims/head.js +15 -13
  209. package/dist/shims/image.js +2 -1
  210. package/dist/shims/internal/work-store-scope.d.ts +5 -0
  211. package/dist/shims/internal/work-store-scope.js +24 -0
  212. package/dist/shims/navigation.js +31 -5
  213. package/dist/shims/request-context.d.ts +2 -0
  214. package/dist/shims/request-state-types.d.ts +2 -1
  215. package/dist/shims/router.js +12 -20
  216. package/dist/shims/server.d.ts +16 -0
  217. package/dist/shims/server.js +24 -4
  218. package/dist/shims/unified-request-context.d.ts +1 -1
  219. package/dist/shims/url-utils.d.ts +2 -0
  220. package/dist/shims/url-utils.js +3 -1
  221. package/dist/utils/client-runtime-metadata.js +1 -1
  222. package/dist/utils/hash.d.ts +7 -0
  223. package/dist/utils/hash.js +11 -1
  224. package/dist/utils/package-name.d.ts +6 -0
  225. package/dist/utils/package-name.js +12 -1
  226. package/dist/utils/plugin-rsc-version.d.ts +4 -0
  227. package/dist/utils/plugin-rsc-version.js +15 -0
  228. package/dist/utils/prerender-output-paths.js +15 -4
  229. package/dist/utils/public-file-path.d.ts +10 -2
  230. package/dist/utils/public-file-path.js +13 -9
  231. package/dist/utils/public-routes.js +2 -2
  232. package/dist/utils/react-version.d.ts +3 -0
  233. package/dist/utils/react-version.js +1 -1
  234. package/package.json +7 -3
@@ -6,14 +6,14 @@ import { patternToNextFormat } from "../routing/route-validation.js";
6
6
  import { getRequestExecutionContext } from "../shims/request-context.js";
7
7
  import { NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_CACHE_HEADER, VINEXT_REVALIDATED_CACHE_TAG_HEADER } from "./headers.js";
8
8
  import { extractLocaleFromUrl, resolvePagesI18nRequest } from "./pages-i18n.js";
9
+ import { buildNextDataNotFoundResponse, buildNextDataPropsJsonResponse, normalizePagesDataRequest, parseNextDataPathname } from "./pages-data-route.js";
9
10
  import { reportRequestError } from "./instrumentation.js";
10
11
  import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
11
- import { beginRouteCacheability, isRouteCacheabilityIdentityProbe, isRouteCacheabilityProbe, markRouteCacheabilityExplicitResponsePolicy, recordRouteCacheability } from "../shims/cacheability-classification.js";
12
+ import { beginRouteCacheability, isRouteCacheabilityIdentityProbe, isRouteCacheabilityProbe, markRouteCacheabilityExplicitResponsePolicy, markRouteCacheabilityFinalResponseUncacheable, recordRouteCacheability } from "../shims/cacheability-classification.js";
12
13
  import { BROWSER_REVALIDATE_CACHE_CONTROL, NEVER_CACHE_CONTROL, STATIC_CACHE_CONTROL, applyCdnResponseHeaders, hasCdnResponsePolicy, hasExplicitNonCacheableResponsePolicy, shouldUseNextDeployCacheControl } from "./cache-control.js";
13
14
  import { buildMissIsrCacheControl } from "./isr-decision.js";
14
15
  import { isOnDemandRevalidateRequest } from "./revalidation-request.js";
15
16
  import { coalesceOnDemandRevalidation, isrGet, isrSet, pagesIsrCacheKey, triggerBackgroundRegeneration } from "./isr-cache.js";
16
- import { encodeCacheTag } from "../utils/encode-cache-tag.js";
17
17
  import { ensureFetchPatch } from "../shims/fetch-cache.js";
18
18
  import { mergeRouteParamsIntoQuery, parseQueryString } from "../utils/query.js";
19
19
  import { getScriptNonceFromHeaderSources } from "./csp.js";
@@ -21,12 +21,11 @@ import { buildDefaultPagesNotFoundResponse } from "./pages-default-404.js";
21
21
  import { buildPagesReadinessNextData } from "./pages-readiness.js";
22
22
  import { resolvePagesPageMethodResponse } from "./pages-page-method.js";
23
23
  import { setCacheStateHeaders } from "./cache-headers.js";
24
- import { hasUserDocumentGetInitialProps } from "./document-initial-head.js";
24
+ import { pagesPathCacheTag } from "./pages-cache-tag.js";
25
25
  import { renderPagesPageResponse } from "./pages-page-response.js";
26
26
  import { hasPagesGetInitialProps } from "./pages-get-initial-props.js";
27
- import { buildNextDataNotFoundResponse, buildNextDataPropsJsonResponse, normalizePagesDataRequest, parseNextDataPathname } from "./pages-data-route.js";
28
27
  import { traceFindPageComponents, tracePagesDocumentStream } from "./pages-execution-tracing.js";
29
- import { mergePagesNotFoundSourceHeaders, resolvePagesPageData } from "./pages-page-data.js";
28
+ import { mergePagesNotFoundSourceHeaders, resolvePagesPageData, resolvePagesStatusPageRenderPath } from "./pages-page-data.js";
30
29
  import { collectAssetTags, resolveClientModuleUrl } from "./pages-asset-tags.js";
31
30
  import { PAGES_PREVIEW_CACHE_CONTROL, appendPagesPreviewClearCookies, getPagesPreviewState } from "./pages-preview.js";
32
31
  import { createPagesReqRes } from "./pages-node-compat.js";
@@ -69,10 +68,7 @@ function withPagesCacheState(response, state, revalidatedPathname) {
69
68
  if (state === "REVALIDATED") {
70
69
  headers.set(NEXTJS_CACHE_HEADER, state);
71
70
  headers.delete(VINEXT_CACHE_HEADER);
72
- if (revalidatedPathname !== void 0) {
73
- const stem = revalidatedPathname.length > 1 && revalidatedPathname.endsWith("/") ? revalidatedPathname.slice(0, -1) : revalidatedPathname;
74
- headers.set(VINEXT_REVALIDATED_CACHE_TAG_HEADER, encodeCacheTag(`_N_T_${stem || "/"}`));
75
- }
71
+ if (revalidatedPathname !== void 0) headers.set(VINEXT_REVALIDATED_CACHE_TAG_HEADER, encodeURIComponent(pagesPathCacheTag(revalidatedPathname)));
76
72
  } else setCacheStateHeaders(headers, state);
77
73
  return new Response(response.body, {
78
74
  headers,
@@ -99,13 +95,10 @@ function applyPagesErrorCachePolicy(response, revalidateSeconds, expireSeconds,
99
95
  });
100
96
  if (hasExplicitNonCacheableResponsePolicy(headers)) return response;
101
97
  if (revalidateSeconds === void 0) applyCdnResponseHeaders(headers, { cacheControl: NEVER_CACHE_CONTROL });
102
- else {
103
- const stem = cacheTagPathname.endsWith("/") ? cacheTagPathname.slice(0, -1) : cacheTagPathname;
104
- applyCdnResponseHeaders(headers, {
105
- cacheControl: buildMissIsrCacheControl(revalidateSeconds, expireSeconds),
106
- tags: [encodeCacheTag(`_N_T_${stem || "/"}`)]
107
- });
108
- }
98
+ else applyCdnResponseHeaders(headers, {
99
+ cacheControl: buildMissIsrCacheControl(revalidateSeconds, expireSeconds),
100
+ tags: [pagesPathCacheTag(cacheTagPathname)]
101
+ });
109
102
  return new Response(response.body, {
110
103
  headers,
111
104
  status: response.status,
@@ -132,7 +125,7 @@ function buildI18nRenderContext(i18nConfig, locale, currentDefaultLocale, domain
132
125
  * accepts the same options shape the generated entry always passed inline.
133
126
  */
134
127
  function createPagesPageHandler(opts) {
135
- const { pageRoutes, errorPageRoute, matchRoute, i18nConfig, vinextConfig, buildId, hasMiddleware, appAssetPath, hasRewrites, setSSRContext, getPagesNavigationIsReadyFromSerializedState, setI18nContext, wrapWithRouterContext, router, resetSSRHead, getSSRHeadHTML, setDocumentInitialHead, flushPreloads, getFontLinks, getFontStyles, getFontPreloads, renderToReadableStream, renderIsrPassToStringAsync, safeJsonStringify, sanitizeDestination, createPageElement, enhancePageElement, AppComponent, DocumentComponent } = opts;
128
+ const { pageRoutes, errorPageRoute, matchRoute, i18nConfig, vinextConfig, buildId, hasMiddleware, appAssetPath, hasRewrites, setSSRContext, getPagesNavigationIsReadyFromSerializedState, setI18nContext, wrapWithRouterContext, router, resetSSRHead, getSSRHeadHTML, setDocumentInitialHead, flushPreloads, getFontLinks, getFontStyles, getFontPreloads, renderToReadableStream, safeJsonStringify, sanitizeDestination, createPageElement, enhancePageElement, AppComponent, DocumentComponent } = opts;
136
129
  function renderToStringAsync(element) {
137
130
  return renderToReadableStream(element).then((stream) => new Response(stream).text());
138
131
  }
@@ -274,17 +267,39 @@ function createPagesPageHandler(opts) {
274
267
  statusText: snapshot.statusText
275
268
  });
276
269
  }
277
- const renderRouteUrl = isStaticPropsRender ? routeUrl.split("?")[0] : routeUrl;
270
+ const routePattern = patternToNextFormat(route.pattern);
271
+ const renderStatusCode = renderStatusCodeOverride ?? (routePattern === "/404" ? 404 : void 0);
272
+ const isStatusPageIdentity = (isStaticPropsRender || pagesReadiness.autoExport) && (routePattern === "/404" || routePattern === "/500" || routePattern === "/_error");
273
+ const statusPagePathname = routePattern === "/_error" && renderStatusCode === 404 ? "/404" : routePattern;
274
+ const renderRouteUrl = isStaticPropsRender && isStatusPageIdentity ? resolvePagesStatusPageRenderPath(statusPagePathname, vinextConfig.trailingSlash, originalRequestUrl.pathname) : isStaticPropsRender ? routeUrl.split("?")[0] : routeUrl;
278
275
  const routerAsPathSource = isStaticPropsRender ? renderRouteUrl : renderAsPath ?? renderRouteUrl;
279
276
  const routerAsPath = i18nConfig ? extractLocaleFromUrl(routerAsPathSource, i18nConfig, locale).url : routerAsPathSource;
280
277
  const uCtx = createRequestContext({ executionContext: getRequestExecutionContext() });
281
- const response = await runWithRequestContext(uCtx, async () => {
278
+ let pageReqRes = null;
279
+ const pageResponseSent = () => pageReqRes?.res.headersSent === true;
280
+ const sendsEarly = isStaticPropsRoute && !isOnDemandRevalidateRequest(request.headers.get("x-prerender-revalidate"));
281
+ let resolveSentResponse = () => {};
282
+ const sentResponse = new Promise((resolve) => {
283
+ resolveSentResponse = resolve;
284
+ });
285
+ const reportSsrError = async (e) => {
286
+ console.error("[vinext] SSR error:", e);
287
+ await reportRequestError(e, {
288
+ path: url,
289
+ method: request.method,
290
+ headers: Object.fromEntries(request.headers.entries())
291
+ }, {
292
+ routerKind: "Pages Router",
293
+ routePath: route.pattern,
294
+ routeType: "render",
295
+ revalidateReason: isOnDemandRevalidateRequest(request.headers.get("x-prerender-revalidate")) ? "on-demand" : typeof pageModule.getStaticProps === "function" ? "stale" : void 0
296
+ });
297
+ };
298
+ const rendering = runWithRequestContext(uCtx, async () => {
282
299
  ensureFetchPatch();
283
300
  try {
284
- const routePattern = patternToNextFormat(route.pattern);
285
301
  setFrameworkRequestRoute(routePattern);
286
- const renderStatusCode = renderStatusCodeOverride ?? (routePattern === "/404" ? 404 : void 0);
287
- const isrCachePathname = (isStaticPropsRender || pagesReadiness.autoExport) && (routePattern === "/404" || routePattern === "/500" || routePattern === "/_error") ? routePattern === "/_error" && renderStatusCode === 404 ? "/404" : routePattern : renderRouteUrl.split("?")[0];
302
+ const isrCachePathname = isStatusPageIdentity ? statusPagePathname : renderRouteUrl.split("?")[0];
288
303
  const isNotFoundErrorRender = routePattern === "/404" || routePattern === "/_error" && renderStatusCode === 404;
289
304
  const isStatusErrorRender = isNotFoundErrorRender || routePattern === "/500" || routePattern === "/_error" && renderStatusCode === 500;
290
305
  const errorPageRevalidateSeconds = isNotFoundErrorRender ? options?.__notFoundRevalidateSeconds : void 0;
@@ -374,15 +389,109 @@ function createPagesPageHandler(opts) {
374
389
  if (options?.__notFoundSourceHeaders) for (const [name, value] of Object.entries(options.__notFoundSourceHeaders)) reqRes.res.setHeader(name, value);
375
390
  return reqRes;
376
391
  };
392
+ const createForegroundReqRes = () => {
393
+ const reqRes = createPageReqRes();
394
+ pageReqRes = reqRes;
395
+ if (sendsEarly) reqRes.responsePromise.then(resolveSentResponse);
396
+ return reqRes;
397
+ };
398
+ const buildPageResponseOptions = (render) => {
399
+ const pageModuleIds = [];
400
+ if (appAssetPath) pageModuleIds.push(appAssetPath);
401
+ if (route.filePath) pageModuleIds.push(route.filePath);
402
+ const initialStylesheetHrefs = /* @__PURE__ */ new Set();
403
+ return {
404
+ assetTags: collectAssetTags({
405
+ manifest,
406
+ moduleIds: pageModuleIds,
407
+ scriptNonce,
408
+ disableOptimizedLoading: vinextConfig.disableOptimizedLoading,
409
+ basePath: vinextConfig.basePath,
410
+ assetPrefix: vinextConfig.assetPrefix,
411
+ deploymentId: process.env.__VINEXT_DEPLOYMENT_ID || process.env.NEXT_DEPLOYMENT_ID,
412
+ crossOrigin: vinextConfig.crossOrigin,
413
+ initialStylesheetHrefs
414
+ }),
415
+ buildId,
416
+ clearSsrContext() {
417
+ if (typeof setSSRContext === "function") setSSRContext(null);
418
+ },
419
+ createPageElement(currentProps) {
420
+ const el = createPageElement(PageComponent, AppComponent, currentProps);
421
+ return typeof wrapWithRouterContext === "function" ? wrapWithRouterContext(el) : el;
422
+ },
423
+ enhancePageElement(renderPageOpts) {
424
+ const el = enhancePageElement(PageComponent, AppComponent, render.renderProps, renderPageOpts);
425
+ return typeof wrapWithRouterContext === "function" ? wrapWithRouterContext(el) : el;
426
+ },
427
+ DocumentComponent,
428
+ err: err instanceof Error ? err : void 0,
429
+ flushPreloads: typeof flushPreloads === "function" ? flushPreloads : void 0,
430
+ fontLinkHeader,
431
+ fontPreloads: allFontPreloads,
432
+ getFontLinks,
433
+ getFontStyles,
434
+ getSSRHeadHTML: typeof getSSRHeadHTML === "function" ? getSSRHeadHTML : void 0,
435
+ clientTraceMetadata: shouldEmitPagesClientTraceMetadata(pageModule, AppComponent) ? vinextConfig.clientTraceMetadata : void 0,
436
+ documentReqRes: render.documentReqRes,
437
+ gsspRes: render.gsspRes,
438
+ isrCacheKey: pageIsrCacheKey,
439
+ isrCachePathname,
440
+ expireSeconds: render.expireSeconds,
441
+ isrRevalidateSeconds: render.isrRevalidateSeconds,
442
+ isStaticPropsRoute,
443
+ isrSet: routeIsrSet,
444
+ i18n: buildI18nRenderContext(i18nConfig, locale, currentDefaultLocale, domainLocales),
445
+ isFallback: render.isFallback,
446
+ pageProps: render.pageProps,
447
+ props: render.renderProps,
448
+ params,
449
+ query,
450
+ renderDocumentToString(element) {
451
+ return renderToStringAsync(element);
452
+ },
453
+ renderToReadableStream,
454
+ resetSSRHead: typeof resetSSRHead === "function" ? resetSSRHead : void 0,
455
+ setDocumentInitialHead: typeof setDocumentInitialHead === "function" ? setDocumentInitialHead : void 0,
456
+ routePattern,
457
+ routeUrl: renderRouteUrl,
458
+ safeJsonStringify,
459
+ scriptNonce,
460
+ initialStylesheetHrefs,
461
+ crossOrigin: vinextConfig.crossOrigin,
462
+ disableOptimizedLoading: vinextConfig.disableOptimizedLoading,
463
+ statusCode: renderStatusCode,
464
+ nextData: serializedPagesNextData
465
+ };
466
+ };
467
+ const withErrorStatusCode = (pageProps, renderProps) => {
468
+ if (routePattern === "/_error" && typeof renderStatusCode === "number" && renderProps.pageProps !== void 0) {
469
+ const statusPageProps = {
470
+ ...pageProps,
471
+ statusCode: renderStatusCode
472
+ };
473
+ return {
474
+ pageProps: statusPageProps,
475
+ renderProps: {
476
+ ...renderProps,
477
+ pageProps: statusPageProps
478
+ }
479
+ };
480
+ }
481
+ return {
482
+ pageProps,
483
+ renderProps
484
+ };
485
+ };
377
486
  const pageDataResult = await resolvePagesPageData({
378
487
  isDataReq,
379
488
  err: err instanceof Error ? err : void 0,
380
489
  applyRequestContexts: applySSRContext,
381
490
  basePath: vinextConfig.basePath,
382
- buildId,
383
491
  deploymentId: process.env.__VINEXT_DEPLOYMENT_ID || process.env.NEXT_DEPLOYMENT_ID,
384
492
  htmlLimitedBots: vinextConfig.htmlLimitedBots,
385
- createGsspReqRes: createPageReqRes,
493
+ createGsspReqRes: createForegroundReqRes,
494
+ createRegenerationReqRes: createPageReqRes,
386
495
  createAppTree(appTreeProps) {
387
496
  const el = createPageElement(PageComponent, AppComponent, appTreeProps);
388
497
  return typeof wrapWithRouterContext === "function" ? wrapWithRouterContext(el) : el;
@@ -403,6 +512,7 @@ function createPagesPageHandler(opts) {
403
512
  validatePropsSerialization: process.env.NODE_ENV !== "production" || process.env.VINEXT_PRERENDER === "1",
404
513
  isOnDemandRevalidate,
405
514
  revalidateOnlyGenerated,
515
+ regeneratesStoredEntry: getRequestExecutionContext()?.isStoredEntryRegeneration === true,
406
516
  previewData,
407
517
  pageModule,
408
518
  AppComponent,
@@ -411,8 +521,26 @@ function createPagesPageHandler(opts) {
411
521
  query,
412
522
  asPath: routerAsPath,
413
523
  resolvedUrl: pagesResolvedUrl,
414
- renderIsrPassToStringAsync,
415
- collectIsrHeadHTML: getSSRHeadHTML && !hasUserDocumentGetInitialProps(DocumentComponent) ? getSSRHeadHTML : void 0,
524
+ async renderIsrDocument(regeneration) {
525
+ const renderAllReady = async (element) => {
526
+ const stream = await renderToReadableStream(element);
527
+ await stream.allReady;
528
+ return stream;
529
+ };
530
+ await (await renderPagesPageResponse({
531
+ ...buildPageResponseOptions({
532
+ documentReqRes: regeneration.documentReqRes,
533
+ expireSeconds: regeneration.expireSeconds,
534
+ gsspRes: null,
535
+ isFallback: false,
536
+ isrRevalidateSeconds: regeneration.revalidateSeconds,
537
+ ...withErrorStatusCode(regeneration.pageProps, regeneration.props)
538
+ }),
539
+ isStaleRegeneration: true,
540
+ renderDocumentToString: (element) => renderAllReady(element).then((stream) => new Response(stream).text()),
541
+ renderToReadableStream: renderAllReady
542
+ })).body?.cancel();
543
+ },
416
544
  route: { isDynamic: route.isDynamic },
417
545
  routePattern,
418
546
  routeUrl: renderRouteUrl,
@@ -434,10 +562,10 @@ function createPagesPageHandler(opts) {
434
562
  statusCode: renderStatusCode,
435
563
  notFoundSourceHeaders: options?.__notFoundSourceHeaders,
436
564
  triggerBackgroundRegeneration,
437
- vinext: serializedPagesNextData.__vinext,
438
565
  nextData: serializedPagesNextData,
439
566
  userAgent: request.headers.get("user-agent") ?? void 0,
440
567
  ifNoneMatch: request.headers.get("if-none-match") ?? void 0,
568
+ ifModifiedSince: request.headers.get("if-modified-since") ?? void 0,
441
569
  requestCacheControl: request.headers.get("cache-control") ?? void 0
442
570
  });
443
571
  if (pageDataResult.kind === "notFound") {
@@ -460,28 +588,17 @@ function createPagesPageHandler(opts) {
460
588
  return finalizePagesPreviewResponse(withBrowserPolicy(notFoundResponse), preview);
461
589
  }
462
590
  if (pageDataResult.kind === "response") {
591
+ if (sendsEarly && pageResponseSent()) return pageDataResult.response;
463
592
  let response = isOnDemandRevalidate && pageDataResult.onDemandRevalidateSuccess !== false ? withPagesCacheState(pageDataResult.response, "REVALIDATED", isrCachePathname) : pageDataResult.response;
464
593
  if (shouldApplyErrorResponsePolicy) response = applyPagesErrorCachePolicy(response, errorPageRevalidateSeconds, errorPageExpireSeconds, errorResponseCachePathname);
465
594
  return finalizePagesPreviewResponse(withBrowserPolicy(response), preview);
466
595
  }
467
- let pageProps = pageDataResult.pageProps;
468
- let renderProps = pageDataResult.props;
469
- if (previewData !== false) renderProps = {
470
- ...renderProps,
596
+ const { pageProps, renderProps } = withErrorStatusCode(pageDataResult.pageProps, previewData !== false ? {
597
+ ...pageDataResult.props,
471
598
  __N_PREVIEW: true
472
- };
473
- if (routePattern === "/_error" && typeof renderStatusCode === "number" && renderProps.pageProps !== void 0) {
474
- pageProps = {
475
- ...pageProps,
476
- statusCode: renderStatusCode
477
- };
478
- renderProps = {
479
- ...renderProps,
480
- pageProps
481
- };
482
- }
599
+ } : pageDataResult.props);
483
600
  const gsspRes = pageDataResult.gsspRes;
484
- const documentReqRes = serializedPagesNextData.autoExport === true && !options?.__notFoundSourceHeaders ? null : pageDataResult.documentReqRes ?? createPageReqRes();
601
+ const documentReqRes = serializedPagesNextData.autoExport === true && !options?.__notFoundSourceHeaders ? null : pageDataResult.documentReqRes ?? createForegroundReqRes();
485
602
  const isrRevalidateSeconds = pageDataResult.isrRevalidateSeconds;
486
603
  if (isStaticPropsRoute && preview.data === false && !preview.shouldClear && isrRevalidateSeconds !== null) recordRouteCacheability({
487
604
  cacheable: isrRevalidateSeconds !== 0,
@@ -510,13 +627,11 @@ function createPagesPageHandler(opts) {
510
627
  if (gsspRes) {
511
628
  if (!headers.has("Cache-Control")) headers.set("Cache-Control", NEVER_CACHE_CONTROL);
512
629
  } else if (isStaticPropsRoute) {
513
- if (isrRevalidateSeconds !== null) {
514
- const stem = isrCachePathname.endsWith("/") ? isrCachePathname.slice(0, -1) : isrCachePathname;
515
- applyCdnResponseHeaders(headers, {
516
- cacheControl: buildMissIsrCacheControl(isrRevalidateSeconds, vinextConfig.expireTime),
517
- tags: [encodeCacheTag(`_N_T_${stem || "/"}`)]
518
- });
519
- } else if (shouldUseNextDeployCacheControl()) headers.set("Cache-Control", BROWSER_REVALIDATE_CACHE_CONTROL);
630
+ if (isrRevalidateSeconds !== null) applyCdnResponseHeaders(headers, {
631
+ cacheControl: buildMissIsrCacheControl(isrRevalidateSeconds, vinextConfig.expireTime),
632
+ tags: [pagesPathCacheTag(isrCachePathname)]
633
+ });
634
+ else if (shouldUseNextDeployCacheControl()) headers.set("Cache-Control", BROWSER_REVALIDATE_CACHE_CONTROL);
520
635
  }
521
636
  if (routePattern !== "/_error" && routePattern !== "/500") {
522
637
  const deploymentId = process.env.__VINEXT_DEPLOYMENT_ID || process.env.NEXT_DEPLOYMENT_ID;
@@ -524,91 +639,28 @@ function createPagesPageHandler(opts) {
524
639
  }
525
640
  return finalizePagesPreviewResponse(withBrowserPolicy(buildNextDataPropsJsonResponse(renderProps, safeJsonStringify, { headers })), preview);
526
641
  }
527
- const pageModuleIds = [];
528
- if (appAssetPath) pageModuleIds.push(appAssetPath);
529
- if (route.filePath) pageModuleIds.push(route.filePath);
530
- const initialStylesheetHrefs = /* @__PURE__ */ new Set();
531
642
  let pageResponse = await renderTracedPagesPageResponse({
532
- assetTags: collectAssetTags({
533
- manifest,
534
- moduleIds: pageModuleIds,
535
- scriptNonce,
536
- disableOptimizedLoading: vinextConfig.disableOptimizedLoading,
537
- basePath: vinextConfig.basePath,
538
- assetPrefix: vinextConfig.assetPrefix,
539
- deploymentId: process.env.__VINEXT_DEPLOYMENT_ID || process.env.NEXT_DEPLOYMENT_ID,
540
- crossOrigin: vinextConfig.crossOrigin,
541
- initialStylesheetHrefs
643
+ ...buildPageResponseOptions({
644
+ documentReqRes,
645
+ expireSeconds: isrExpireSeconds,
646
+ gsspRes,
647
+ isFallback: isFallbackRender,
648
+ isrRevalidateSeconds,
649
+ pageProps,
650
+ renderProps
542
651
  }),
543
- buildId,
544
- clearSsrContext() {
545
- if (typeof setSSRContext === "function") setSSRContext(null);
546
- },
547
- createPageElement(currentProps) {
548
- const el = createPageElement(PageComponent, AppComponent, currentProps);
549
- return typeof wrapWithRouterContext === "function" ? wrapWithRouterContext(el) : el;
550
- },
551
- enhancePageElement(renderPageOpts) {
552
- const el = enhancePageElement(PageComponent, AppComponent, renderProps, renderPageOpts);
553
- return typeof wrapWithRouterContext === "function" ? wrapWithRouterContext(el) : el;
554
- },
555
- DocumentComponent,
556
- err: err instanceof Error ? err : void 0,
557
- flushPreloads: typeof flushPreloads === "function" ? flushPreloads : void 0,
558
- fontLinkHeader,
559
- fontPreloads: allFontPreloads,
560
- getFontLinks,
561
- getFontStyles,
562
- getSSRHeadHTML: typeof getSSRHeadHTML === "function" ? getSSRHeadHTML : void 0,
563
- clientTraceMetadata: shouldEmitPagesClientTraceMetadata(pageModule, AppComponent) ? vinextConfig.clientTraceMetadata : void 0,
564
- documentReqRes,
565
- gsspRes,
566
- isrCacheKey: pageIsrCacheKey,
567
- isrCachePathname,
568
- expireSeconds: isrExpireSeconds,
569
- isrRevalidateSeconds,
570
652
  isOnDemandRevalidate,
571
- isStaticPropsRoute,
572
- isrSet: routeIsrSet,
573
- i18n: buildI18nRenderContext(i18nConfig, locale, currentDefaultLocale, domainLocales),
574
- isFallback: isFallbackRender,
575
- pageProps,
576
- props: renderProps,
577
- params,
578
- query,
579
- renderDocumentToString(element) {
580
- return renderToStringAsync(element);
581
- },
582
- renderToReadableStream,
583
- resetSSRHead: typeof resetSSRHead === "function" ? resetSSRHead : void 0,
584
- setDocumentInitialHead: typeof setDocumentInitialHead === "function" ? setDocumentInitialHead : void 0,
585
- routePattern,
586
- routeUrl: renderRouteUrl,
587
- safeJsonStringify,
588
- scriptNonce,
589
- initialStylesheetHrefs,
590
- crossOrigin: vinextConfig.crossOrigin,
591
- disableOptimizedLoading: vinextConfig.disableOptimizedLoading,
592
- statusCode: renderStatusCode,
593
- nextData: serializedPagesNextData,
594
653
  userAgent: request.headers.get("user-agent") ?? void 0,
595
654
  ifNoneMatch: request.headers.get("if-none-match") ?? void 0,
655
+ ifModifiedSince: request.headers.get("if-modified-since") ?? void 0,
596
656
  requestCacheControl: request.headers.get("cache-control") ?? void 0
597
657
  });
658
+ if (sendsEarly && pageResponseSent()) return pageResponse;
598
659
  if (shouldApplyErrorResponsePolicy) pageResponse = applyPagesErrorCachePolicy(pageResponse, errorPageRevalidateSeconds, errorPageExpireSeconds, errorResponseCachePathname);
599
660
  return finalizePagesPreviewResponse(withBrowserPolicy(pageResponse), preview);
600
661
  } catch (e) {
601
- console.error("[vinext] SSR error:", e);
602
- await reportRequestError(e, {
603
- path: url,
604
- method: request.method,
605
- headers: Object.fromEntries(request.headers.entries())
606
- }, {
607
- routerKind: "Pages Router",
608
- routePath: route.pattern,
609
- routeType: "render",
610
- revalidateReason: isOnDemandRevalidateRequest(request.headers.get("x-prerender-revalidate")) ? "on-demand" : typeof pageModule.getStaticProps === "function" ? "stale" : void 0
611
- });
662
+ await reportSsrError(e);
663
+ if (sendsEarly && pageResponseSent()) return sentResponse;
612
664
  if (!isInternalErrorRender && !isDataReq) {
613
665
  let errorRoute = null;
614
666
  for (let i = 0; i < pageRoutes.length; i++) if (pageRoutes[i].pattern === "/500") {
@@ -635,7 +687,17 @@ function createPagesPageHandler(opts) {
635
687
  return new Response("Internal Server Error", { status: 500 });
636
688
  }
637
689
  });
638
- return closeAfterResponseWithBody(response, uCtx);
690
+ if (!sendsEarly) return closeAfterResponseWithBody(await rendering, uCtx);
691
+ const settled = await Promise.race([rendering.then((response) => ({
692
+ response,
693
+ rendered: true
694
+ })), sentResponse.then((response) => ({
695
+ response,
696
+ rendered: false
697
+ }))]);
698
+ if (pageResponseSent()) markRouteCacheabilityFinalResponseUncacheable("_app or _document sent the response of a getStaticProps page");
699
+ if (!settled.rendered) getRequestExecutionContext()?.waitUntil(rendering.then(() => void 0, () => void 0));
700
+ return closeAfterResponseWithBody(settled.response, uCtx);
639
701
  }
640
702
  return renderPage;
641
703
  }
@@ -11,13 +11,12 @@ import { ComponentType, ReactNode } from "react";
11
11
  export declare function isPagesStreamingBot(userAgent: string): boolean;
12
12
  export declare function generatePagesETag(payload: string): string;
13
13
  /**
14
- * Returns true when a request `Cache-Control` header asks to bypass the 304
15
- * short-circuit. Mirrors the `fresh` package's check used by Next.js's
16
- * `sendEtagResponse` (`/(?:^|,)\s*?no-cache\s*?(?:,|$)/`). Shared by the
17
- * fresh-MISS bot path here and the ISR HIT/STALE paths in
18
- * `pages-page-data.ts` so the two cannot drift.
14
+ * Whether a render answers a matching If-None-Match with a 304. Next.js stores
15
+ * the page before it evaluates the ETag, so when the CDN adapter stores the
16
+ * completed response, the render returns the page and the adapter sends the 304.
17
+ * A page whose status carries no body has nothing to store.
19
18
  */
20
- export declare function requestsNoCache(cacheControl: string | undefined): boolean;
19
+ export declare function rendersPagesNotModified(status: number): boolean;
21
20
  type PagesFontPreload = {
22
21
  href: string;
23
22
  type: string;
@@ -87,6 +86,8 @@ type RenderPagesPageResponseOptions = {
87
86
  isrRevalidateSeconds: number | false | null;
88
87
  /** Synchronous `res.revalidate()` render; cache persistence must finish before returning. */
89
88
  isOnDemandRevalidate?: boolean;
89
+ /** Background ISR regeneration; the cache write must finish before returning. */
90
+ isStaleRegeneration?: boolean;
90
91
  isStaticPropsRoute?: boolean;
91
92
  isrSet: (key: string, data: CachedPagesValue, policy: IsrWritePolicy) => Promise<void>;
92
93
  i18n: PagesI18nRenderContext;
@@ -133,6 +134,11 @@ type RenderPagesPageResponseOptions = {
133
134
  * Only evaluated on bot/buffered responses that carry an ETag.
134
135
  */
135
136
  ifNoneMatch?: string;
137
+ /**
138
+ * The incoming request's `If-Modified-Since` header value. As in Next.js,
139
+ * which gives a page no Last-Modified, a request with it gets the page.
140
+ */
141
+ ifModifiedSince?: string;
136
142
  /**
137
143
  * The incoming request's `Cache-Control` header value. When the value
138
144
  * contains `no-cache`, the 304 short-circuit is skipped and a full 200