vinext 1.0.0 → 1.0.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 (148) hide show
  1. package/THIRD_PARTY_LICENSES.md +26 -0
  2. package/dist/build/lifecycle.js +10 -10
  3. package/dist/build/pages-client-assets-module.js +6 -1
  4. package/dist/build/precompress.js +1 -1
  5. package/dist/build/prerender-paths.js +3 -7
  6. package/dist/build/prerender.d.ts +8 -1
  7. package/dist/build/prerender.js +134 -38
  8. package/dist/build/run-prerender.js +4 -3
  9. package/dist/build/server-entry.d.ts +2 -0
  10. package/dist/build/server-entry.js +7 -1
  11. package/dist/client/browser-globals.d.ts +4 -0
  12. package/dist/client/browser-globals.js +5 -0
  13. package/dist/client/navigation-runtime.d.ts +0 -1
  14. package/dist/client/navigation-runtime.js +2 -2
  15. package/dist/config/dotenv.js +14 -3
  16. package/dist/entries/app-rsc-entry.js +3 -2
  17. package/dist/index.js +142 -71
  18. package/dist/init-cloudflare.d.ts +1 -1
  19. package/dist/init-cloudflare.js +6 -6
  20. package/dist/init-platform.js +1 -1
  21. package/dist/init.js +4 -2
  22. package/dist/plugins/commonjs-syntax.d.ts +16 -0
  23. package/dist/plugins/commonjs-syntax.js +22 -0
  24. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  25. package/dist/plugins/ignore-dynamic-requests.js +54 -3
  26. package/dist/plugins/import-meta-url.js +6 -6
  27. package/dist/plugins/og-asset-ownership.d.ts +2 -0
  28. package/dist/plugins/og-asset-ownership.js +24 -13
  29. package/dist/plugins/og-assets.d.ts +18 -0
  30. package/dist/plugins/og-assets.js +50 -8
  31. package/dist/plugins/og-harfbuzz.js +38 -27
  32. package/dist/plugins/optimize-imports.js +2 -1
  33. package/dist/plugins/require-context.d.ts +1 -0
  34. package/dist/plugins/require-context.js +28 -1
  35. package/dist/plugins/scan-build-css.d.ts +12 -0
  36. package/dist/plugins/scan-build-css.js +39 -0
  37. package/dist/plugins/strip-server-exports.d.ts +2 -0
  38. package/dist/plugins/strip-server-exports.js +3 -1
  39. package/dist/plugins/transform-result.d.ts +18 -0
  40. package/dist/plugins/transform-result.js +23 -2
  41. package/dist/plugins/typeof-window.d.ts +10 -0
  42. package/dist/plugins/typeof-window.js +33 -9
  43. package/dist/routing/app-route-graph.d.ts +0 -1
  44. package/dist/routing/app-route-graph.js +2 -4
  45. package/dist/routing/app-route-ids.d.ts +3 -0
  46. package/dist/routing/app-route-ids.js +6 -0
  47. package/dist/server/app-bfcache-id.d.ts +1 -0
  48. package/dist/server/app-bfcache-id.js +7 -1
  49. package/dist/server/app-bfcache-identity.js +1 -2
  50. package/dist/server/app-browser-entry.js +4 -2
  51. package/dist/server/app-browser-hydration.d.ts +1 -1
  52. package/dist/server/app-browser-hydration.js +2 -2
  53. package/dist/server/app-browser-navigation-controller.js +1 -1
  54. package/dist/server/app-browser-state.js +1 -1
  55. package/dist/server/app-browser-stream.d.ts +1 -1
  56. package/dist/server/app-history-state.d.ts +0 -1
  57. package/dist/server/app-history-state.js +2 -5
  58. package/dist/server/app-page-cache-render.js +2 -1
  59. package/dist/server/app-page-render.js +2 -1
  60. package/dist/server/app-page-search-params-observation.js +1 -1
  61. package/dist/server/app-page-stream.js +1 -1
  62. package/dist/server/app-page-tracing.js +2 -1
  63. package/dist/server/app-pages-bridge.js +3 -2
  64. package/dist/server/app-render-abort-error.d.ts +3 -0
  65. package/dist/server/app-render-abort-error.js +8 -0
  66. package/dist/server/app-request-stage-independent-entry.js +4 -7
  67. package/dist/server/app-route-handler-cache.d.ts +2 -1
  68. package/dist/server/app-route-handler-cache.js +11 -7
  69. package/dist/server/app-route-handler-dispatch.js +10 -3
  70. package/dist/server/app-route-handler-execution.d.ts +9 -1
  71. package/dist/server/app-route-handler-execution.js +28 -13
  72. package/dist/server/app-route-handler-policy.js +2 -2
  73. package/dist/server/app-route-handler-response.d.ts +1 -1
  74. package/dist/server/app-route-handler-response.js +14 -5
  75. package/dist/server/app-router-entry.d.ts +2 -1
  76. package/dist/server/app-router-entry.js +5 -9
  77. package/dist/server/app-rsc-errors.d.ts +0 -1
  78. package/dist/server/app-rsc-errors.js +2 -6
  79. package/dist/server/app-rsc-handler.d.ts +1 -0
  80. package/dist/server/app-rsc-handler.js +18 -7
  81. package/dist/server/app-rsc-request-normalization.d.ts +1 -1
  82. package/dist/server/app-rsc-request-normalization.js +3 -2
  83. package/dist/server/app-rsc-response-finalizer.js +4 -1
  84. package/dist/server/app-rsc-route-matching.js +1 -1
  85. package/dist/server/app-server-action-execution.d.ts +2 -1
  86. package/dist/server/app-ssr-entry.js +3 -3
  87. package/dist/server/app-ssr-search-params-gate.js +1 -1
  88. package/dist/server/app-ssr-stream.js +1 -1
  89. package/dist/server/cache-control.js +3 -11
  90. package/dist/server/cacheability-request.js +49 -49
  91. package/dist/server/config-headers.js +1 -1
  92. package/dist/server/dev-server.js +11 -3
  93. package/dist/server/headers.d.ts +2 -0
  94. package/dist/server/headers.js +5 -1
  95. package/dist/server/http-error-responses.js +1 -0
  96. package/dist/server/isr-cache.d.ts +2 -0
  97. package/dist/server/isr-cache.js +6 -1
  98. package/dist/server/metadata-route-response.js +94 -37
  99. package/dist/server/pages-api-route.js +8 -2
  100. package/dist/server/pages-asset-tags.d.ts +1 -0
  101. package/dist/server/pages-asset-tags.js +73 -22
  102. package/dist/server/pages-client-assets.d.ts +2 -0
  103. package/dist/server/pages-page-data.d.ts +6 -1
  104. package/dist/server/pages-page-data.js +71 -65
  105. package/dist/server/pages-page-handler.js +29 -11
  106. package/dist/server/pages-page-response.js +3 -1
  107. package/dist/server/pages-request-pipeline.d.ts +2 -1
  108. package/dist/server/pages-request-pipeline.js +20 -5
  109. package/dist/server/pages-request-stage-entry.js +6 -4
  110. package/dist/server/prerender-manifest.d.ts +6 -0
  111. package/dist/server/prerender-manifest.js +1 -1
  112. package/dist/server/prod-server.js +3 -13
  113. package/dist/server/response-stage-cacheability.js +1 -1
  114. package/dist/server/worker-revalidation-context.d.ts +2 -1
  115. package/dist/server/worker-revalidation-context.js +1 -0
  116. package/dist/server/workers-tracing.d.ts +17 -0
  117. package/dist/server/workers-tracing.js +48 -8
  118. package/dist/shims/cache-request-state.d.ts +3 -14
  119. package/dist/shims/cache-request-state.js +2 -13
  120. package/dist/shims/cache-runtime.js +4 -2
  121. package/dist/shims/cache.d.ts +2 -1
  122. package/dist/shims/cache.js +4 -2
  123. package/dist/shims/cacheability-classification.d.ts +1 -1
  124. package/dist/shims/cacheability-classification.js +2 -2
  125. package/dist/shims/cdn-cache.d.ts +10 -1
  126. package/dist/shims/cdn-cache.js +16 -9
  127. package/dist/shims/error.d.ts +4 -18
  128. package/dist/shims/error.js +17 -10
  129. package/dist/shims/error.react-server.d.ts +4 -6
  130. package/dist/shims/error.react-server.js +4 -1
  131. package/dist/shims/fetch-cache.js +4 -3
  132. package/dist/shims/headers.d.ts +6 -69
  133. package/dist/shims/headers.js +37 -181
  134. package/dist/shims/internal/cache-context-accessor.d.ts +16 -0
  135. package/dist/shims/internal/cache-context-accessor.js +15 -0
  136. package/dist/shims/internal/headers-state.d.ts +74 -0
  137. package/dist/shims/internal/headers-state.js +157 -0
  138. package/dist/shims/navigation.js +2 -2
  139. package/dist/shims/request-state-types.d.ts +2 -1
  140. package/dist/shims/root-params.js +1 -1
  141. package/dist/shims/server.js +52 -2
  142. package/dist/shims/unified-request-context.d.ts +1 -1
  143. package/dist/utils/encode-cache-tag.d.ts +1 -0
  144. package/dist/utils/encode-cache-tag.js +11 -1
  145. package/dist/utils/vite-cli-invocation.js +8 -1
  146. package/package.json +6 -2
  147. package/dist/server/metadata-route-cache-policy.d.ts +0 -5
  148. package/dist/server/metadata-route-cache-policy.js +0 -6
@@ -13,12 +13,73 @@ import { getPagesClientAssets } from "./pages-client-assets.js";
13
13
  * unit-testable and lives in a normal typed module rather than a codegen
14
14
  * template string.
15
15
  */
16
+ const nonEmptyManifests = /* @__PURE__ */ new WeakMap();
17
+ const moduleKeyOrder = /* @__PURE__ */ new WeakMap();
18
+ const sharedChunkFiles = /* @__PURE__ */ new WeakMap();
19
+ const lazyChunkSets = /* @__PURE__ */ new WeakMap();
20
+ function findModuleKey(manifest, moduleId) {
21
+ if (manifest[moduleId]) return moduleId;
22
+ let uniqueKey = null;
23
+ let candidate = moduleId;
24
+ while (true) {
25
+ if (Object.prototype.propertyIsEnumerable.call(manifest, candidate)) {
26
+ if (uniqueKey !== null) {
27
+ uniqueKey = null;
28
+ break;
29
+ }
30
+ uniqueKey = candidate;
31
+ }
32
+ const slash = candidate.indexOf("/");
33
+ if (slash === -1) break;
34
+ candidate = candidate.slice(slash + 1);
35
+ }
36
+ if (uniqueKey !== null) return uniqueKey;
37
+ let keyOrder = moduleKeyOrder.get(manifest);
38
+ if (!keyOrder) {
39
+ keyOrder = /* @__PURE__ */ new Map();
40
+ for (const key in manifest) keyOrder.set(key, keyOrder.size);
41
+ moduleKeyOrder.set(manifest, keyOrder);
42
+ }
43
+ let matchedKey = null;
44
+ let matchedOrder = Infinity;
45
+ let suffix = moduleId;
46
+ while (true) {
47
+ const order = keyOrder.get(suffix);
48
+ if (order !== void 0 && order < matchedOrder) {
49
+ matchedKey = suffix;
50
+ matchedOrder = order;
51
+ }
52
+ const slash = suffix.indexOf("/");
53
+ if (slash === -1) break;
54
+ suffix = suffix.slice(slash + 1);
55
+ }
56
+ return matchedKey;
57
+ }
58
+ function getSharedChunkFiles(manifest) {
59
+ const cached = sharedChunkFiles.get(manifest);
60
+ if (cached) return cached;
61
+ const files = /* @__PURE__ */ new Set();
62
+ for (const key in manifest) for (const file of manifest[key] ?? []) {
63
+ const basename = file.slice(file.lastIndexOf("/") + 1);
64
+ if (basename.startsWith("framework-") || basename.startsWith("vinext-") || basename.includes("vinext-client-entry") || basename.includes("vinext-app-browser-entry")) files.add(file);
65
+ }
66
+ const result = [...files];
67
+ sharedChunkFiles.set(manifest, result);
68
+ return result;
69
+ }
16
70
  /**
17
71
  * Resolve the effective SSR manifest: prefer the caller-supplied object and
18
72
  * fall back to the registered client build metadata.
19
73
  */
20
74
  function resolveSsrManifest(manifest) {
21
- if (manifest && Object.keys(manifest).length > 0) return manifest;
75
+ if (manifest) {
76
+ let nonEmpty = nonEmptyManifests.get(manifest);
77
+ if (nonEmpty === void 0) {
78
+ nonEmpty = Object.keys(manifest).length > 0;
79
+ nonEmptyManifests.set(manifest, nonEmpty);
80
+ }
81
+ if (nonEmpty) return manifest;
82
+ }
22
83
  return getPagesClientAssets().ssrManifest ?? null;
23
84
  }
24
85
  /**
@@ -29,20 +90,13 @@ function resolveSsrManifest(manifest) {
29
90
  */
30
91
  function getManifestFilesForModule(manifest, moduleId) {
31
92
  if (!manifest || !moduleId) return null;
32
- const files = manifest[moduleId];
33
- if (files) return files;
34
- for (const key in manifest) if (moduleId.endsWith("/" + key) || moduleId === key) return manifest[key];
35
- return null;
93
+ const key = findModuleKey(manifest, moduleId);
94
+ return key === null ? null : manifest[key];
36
95
  }
37
96
  function collectGraphOrderedCss(graph, moduleIds) {
38
97
  const ordered = [];
39
98
  const emitted = /* @__PURE__ */ new Set();
40
99
  const visited = /* @__PURE__ */ new Set();
41
- function findKey(moduleId) {
42
- if (!moduleId) return void 0;
43
- if (graph[moduleId]) return moduleId;
44
- for (const key in graph) if (moduleId === key || moduleId.endsWith("/" + key)) return key;
45
- }
46
100
  function visit(key) {
47
101
  if (!key || visited.has(key)) return;
48
102
  visited.add(key);
@@ -55,7 +109,7 @@ function collectGraphOrderedCss(graph, moduleIds) {
55
109
  ordered.push(file);
56
110
  }
57
111
  }
58
- for (const moduleId of moduleIds) visit(findKey(moduleId));
112
+ for (const moduleId of moduleIds) if (moduleId) visit(findModuleKey(graph, moduleId));
59
113
  return ordered;
60
114
  }
61
115
  /**
@@ -104,7 +158,11 @@ function collectAssetTags(options) {
104
158
  };
105
159
  const runtimeAssets = getPagesClientAssets();
106
160
  const lazyChunks = runtimeAssets.lazyChunks ?? null;
107
- const lazySet = lazyChunks && lazyChunks.length > 0 ? new Set(lazyChunks) : null;
161
+ let lazySet = lazyChunks ? lazyChunkSets.get(lazyChunks) : void 0;
162
+ if (lazyChunks && !lazySet) {
163
+ lazySet = new Set(lazyChunks);
164
+ lazyChunkSets.set(lazyChunks, lazySet);
165
+ }
108
166
  const clientEntry = runtimeAssets.clientEntry;
109
167
  if (clientEntry) {
110
168
  seen.add(clientEntry);
@@ -128,15 +186,8 @@ function collectAssetTags(options) {
128
186
  const files = getManifestFilesForModule(m, id);
129
187
  if (files) for (let fi = 0; fi < files.length; fi++) allFiles.push(files[fi]);
130
188
  }
131
- for (const key in m) {
132
- const vals = m[key];
133
- if (!vals) continue;
134
- for (let vi = 0; vi < vals.length; vi++) {
135
- const file = vals[vi];
136
- const basename = file.split("/").pop() || "";
137
- if (basename.startsWith("framework-") || basename.startsWith("vinext-") || basename.includes("vinext-client-entry") || basename.includes("vinext-app-browser-entry")) allFiles.push(file);
138
- }
139
- }
189
+ const sharedFiles = m === runtimeAssets.ssrManifest && runtimeAssets.sharedChunks ? runtimeAssets.sharedChunks : getSharedChunkFiles(m);
190
+ for (const file of sharedFiles) allFiles.push(file);
140
191
  } else for (const akey in m) {
141
192
  const avals = m[akey];
142
193
  if (avals) for (let ai = 0; ai < avals.length; ai++) allFiles.push(avals[ai]);
@@ -160,4 +211,4 @@ function collectAssetTags(options) {
160
211
  return tags.join("\n ");
161
212
  }
162
213
  //#endregion
163
- export { collectAssetTags, getManifestFilesForModule, resolveClientModuleUrl, resolveSsrManifest };
214
+ export { collectAssetTags, getManifestFilesForModule, getSharedChunkFiles, resolveClientModuleUrl, resolveSsrManifest };
@@ -4,6 +4,8 @@ export type PagesClientAssets = {
4
4
  clientEntry?: string;
5
5
  appBootstrapPreinitModules?: string[];
6
6
  ssrManifest?: Record<string, string[]>;
7
+ /** Build-time shared file list, valid only for this ssrManifest object. */
8
+ sharedChunks?: string[];
7
9
  cssGraph?: Record<string, {
8
10
  imports?: string[];
9
11
  css?: string[];
@@ -149,8 +149,11 @@ export type ResolvePagesPageDataOptions = {
149
149
  createPageElement: (props: Record<string, unknown>) => ReactNode;
150
150
  fontLinkHeader: string;
151
151
  i18n: PagesI18nRenderContext;
152
+ /** Build-time default locale, which can differ from a domain's render default. */
153
+ staticPathsDefaultLocale?: string;
152
154
  isrCacheKey: (router: string, pathname: string) => string;
153
155
  isrGet: (key: string) => Promise<ISRCacheEntry | null>;
156
+ hasPrerenderedPages?: boolean;
154
157
  isrSet: (key: string, data: CachedPagesValue | CachedRedirectValue | null, policy: IsrWritePolicy) => Promise<void>;
155
158
  expireSeconds?: number;
156
159
  /**
@@ -216,6 +219,8 @@ export type ResolvePagesPageDataOptions = {
216
219
  sanitizeDestination: (destination: string) => string;
217
220
  scriptNonce?: string;
218
221
  statusCode?: number;
222
+ /** Request-local headers inherited when rendering a source page's notFound result. */
223
+ notFoundSourceHeaders?: Record<string, string | number | boolean | string[]>;
219
224
  triggerBackgroundRegeneration: (key: string, renderFn: () => Promise<void>, errorContext?: {
220
225
  routerKind: "Pages Router";
221
226
  routePath: string;
@@ -314,7 +319,7 @@ export type PagesRouteParam = {
314
319
  optional: boolean;
315
320
  };
316
321
  export declare function getPagesRouteParams(routePattern: string): PagesRouteParam[];
317
- export declare function matchesPagesStaticPath(pathEntry: PagesStaticPathsEntry, params: Record<string, unknown>, routeParams: PagesRouteParam[], routeUrl: string): boolean;
322
+ export declare function matchesPagesStaticPath(pathEntry: PagesStaticPathsEntry, params: Record<string, unknown>, routeParams: PagesRouteParam[], routeUrl: string, i18n?: Pick<PagesI18nRenderContext, "locale" | "locales" | "defaultLocale">): boolean;
318
323
  export declare function renderPagesIsrHtml(options: RenderPagesIsrHtmlOptions): Promise<string>;
319
324
  export declare function resolvePagesPageData(options: ResolvePagesPageDataOptions): Promise<ResolvePagesPageDataResult>;
320
325
  //#endregion
@@ -3,6 +3,8 @@ import { isBotUserAgent } from "../utils/html-limited-bots.js";
3
3
  import { normalizePathnameForRouteMatch } from "../routing/utils.js";
4
4
  import { NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER } from "./headers.js";
5
5
  import { isDangerousScheme } from "../shims/url-safety.js";
6
+ import { extractLocaleFromUrl } from "./pages-i18n.js";
7
+ import { recordRouteCacheability } from "../shims/cacheability-classification.js";
6
8
  import { applyCdnResponseHeaders } from "./cache-control.js";
7
9
  import { buildMissIsrCacheControl, decideIsr } from "./isr-decision.js";
8
10
  import { buildPagesCacheValue, isrCacheControl } from "./isr-cache.js";
@@ -102,6 +104,10 @@ function mergePagesNotFoundSourceHeaders(response, sourceHeaders) {
102
104
  }
103
105
  function applyPagesTerminalMissHeaders(response, revalidateSeconds, isrCachePathname, expireSeconds) {
104
106
  const stem = isrCachePathname.endsWith("/") ? isrCachePathname.slice(0, -1) : isrCachePathname;
107
+ recordRouteCacheability({
108
+ cacheable: revalidateSeconds !== 0,
109
+ cacheControl: buildMissIsrCacheControl(revalidateSeconds, expireSeconds)
110
+ });
105
111
  applyCdnResponseHeaders(response.headers, {
106
112
  cacheControl: buildMissIsrCacheControl(revalidateSeconds, expireSeconds),
107
113
  tags: [encodeCacheTag(`_N_T_${stem || "/"}`)]
@@ -117,16 +123,17 @@ function applyCachedPagesRepresentationHeaders(response, cacheState, entry, opti
117
123
  expireSeconds: entry.cacheControl?.expire === void 0 ? void 0 : options.expireSeconds,
118
124
  cacheControlMeta: entry.cacheControl
119
125
  });
126
+ recordRouteCacheability({
127
+ cacheable: true,
128
+ cacheControl
129
+ });
120
130
  applyCdnResponseHeaders(response.headers, { cacheControl });
121
131
  for (const [name, value] of Object.entries(buildCacheStateHeaders(cacheState))) response.headers.set(name, value);
122
132
  return response;
123
133
  }
124
134
  function buildCachedPagesNotFoundResult(options, entry, cacheState) {
125
135
  const result = buildPagesNotFoundResult(options, entry.cacheControl?.revalidate ?? 60, cacheState, entry.cacheControl?.expire);
126
- if (result.kind === "response") return {
127
- kind: "response",
128
- response: applyCachedPagesRepresentationHeaders(result.response, cacheState, entry, options)
129
- };
136
+ if (result.kind === "response") return finalizeCachedPagesResponse(applyCachedPagesRepresentationHeaders(result.response, cacheState, entry, options), options);
130
137
  return result;
131
138
  }
132
139
  function resolvePagesRedirectStatus(redirect) {
@@ -270,7 +277,8 @@ function buildPagesRedirectResponse(redirect, options, props = { pageProps: {} }
270
277
  const headers = new Headers(responseHeaders);
271
278
  headers.set("Location", location);
272
279
  if (resolved.statusCode === 308) headers.set("Refresh", `0;url=${location}`);
273
- return new Response(location, {
280
+ if (options.isBuildTimePrerendering) headers.set("Content-Type", "application/json");
281
+ return new Response(options.isBuildTimePrerendering ? options.safeJsonStringify(redirectProps) : location, {
274
282
  status: resolved.statusCode,
275
283
  headers
276
284
  });
@@ -333,7 +341,19 @@ function getPagesRouteParams(routePattern) {
333
341
  return null;
334
342
  }).filter((param) => param !== null);
335
343
  }
336
- function matchesPagesStaticPath(pathEntry, params, routeParams, routeUrl) {
344
+ function matchesPagesStaticPath(pathEntry, params, routeParams, routeUrl, i18n) {
345
+ if (i18n?.locales && i18n.defaultLocale) {
346
+ let entryLocale = i18n.defaultLocale;
347
+ if (typeof pathEntry === "string") {
348
+ const localized = extractLocaleFromUrl(pathEntry, {
349
+ locales: i18n.locales,
350
+ defaultLocale: i18n.defaultLocale
351
+ });
352
+ pathEntry = localized.url;
353
+ entryLocale = localized.locale;
354
+ } else entryLocale = pathEntry.locale ?? entryLocale;
355
+ if (entryLocale !== (i18n.locale ?? i18n.defaultLocale)) return false;
356
+ }
337
357
  if (typeof pathEntry === "string") return normalizePathnameForRouteMatch(normalizeStaticPathname(pathEntry)) === normalizePathnameForRouteMatch(normalizeStaticPathname(routeUrl));
338
358
  const entryParams = pathEntry.params;
339
359
  if (entryParams === void 0 || entryParams === null) return false;
@@ -364,6 +384,10 @@ function buildPagesCacheResponse(html, cacheState, fontLinkHeader, revalidateSec
364
384
  "Content-Type": "text/html; charset=utf-8",
365
385
  ...buildCacheStateHeaders(cacheState)
366
386
  });
387
+ recordRouteCacheability({
388
+ cacheable: true,
389
+ cacheControl: cacheControlHeader
390
+ });
367
391
  applyCdnResponseHeaders(headers, { cacheControl: cacheControlHeader });
368
392
  if (fontLinkHeader) headers.set("Link", fontLinkHeader);
369
393
  if (cachedHeaders) for (const [name, value] of Object.entries(cachedHeaders)) {
@@ -378,28 +402,21 @@ function buildPagesCacheResponse(html, cacheState, fontLinkHeader, revalidateSec
378
402
  headers
379
403
  });
380
404
  }
381
- /**
382
- * For bot / crawler UAs, attach an ETag to a cached ISR response (HIT or
383
- * STALE) so it is consistent with the fresh-MISS path, then check for a
384
- * matching `If-None-Match`. When the check passes — and the request did NOT
385
- * carry `Cache-Control: no-cache` — returns a 304 response; otherwise returns
386
- * `null` so the caller can return the full response.
387
- *
388
- * Extracted to avoid duplicating the same three-line block across the HIT and
389
- * STALE branches.
390
- */
391
- function applyBotETagAndCheck(cachedResponse, html, options) {
392
- if (!options.userAgent || !isPagesStreamingBot(options.userAgent)) return null;
393
- const etag = generatePagesETag(html);
394
- cachedResponse.headers.set("ETag", etag);
395
- if (!requestsNoCache(options.requestCacheControl) && options.ifNoneMatch && matchesIfNoneMatch(options.ifNoneMatch, etag)) return {
396
- kind: "response",
397
- response: new Response(null, {
405
+ /** Merge source headers before the cached HTML's bot ETag and freshness check. */
406
+ function finalizeCachedPagesResponse(response, options, html) {
407
+ response = mergePagesNotFoundSourceHeaders(response, options.notFoundSourceHeaders);
408
+ if (html !== void 0 && options.userAgent && isPagesStreamingBot(options.userAgent)) {
409
+ const etag = generatePagesETag(html);
410
+ response.headers.set("ETag", etag);
411
+ if (!requestsNoCache(options.requestCacheControl) && options.ifNoneMatch && matchesIfNoneMatch(options.ifNoneMatch, etag)) response = new Response(null, {
398
412
  status: 304,
399
- headers: cachedResponse.headers
400
- })
413
+ headers: response.headers
414
+ });
415
+ }
416
+ return {
417
+ kind: "response",
418
+ response
401
419
  };
402
- return null;
403
420
  }
404
421
  /**
405
422
  * Matches one serialized `next/head` tag. `getSSRHeadHTML()` stamps every tag
@@ -491,17 +508,32 @@ async function resolvePagesPageData(options) {
491
508
  const userFacingParams = options.route.isDynamic ? options.params : null;
492
509
  let isFallback = false;
493
510
  let shouldPersistFallbackData = false;
494
- let onDemandPreviousCacheEntry;
511
+ let previousCacheEntry;
495
512
  const previewData = options.isOnDemandRevalidate ? false : options.previewData ?? false;
496
- if (typeof options.pageModule.getStaticPaths === "function" && options.route.isDynamic) {
513
+ if (options.hasPrerenderedPages && options.nextData?.autoExport && !options.scriptNonce && !options.isOnDemandRevalidate && previewData === false) {
514
+ const cached = await options.isrGet(options.isrCacheKey("pages", options.isrCachePathname ?? options.routeUrl.split("?")[0]));
515
+ const value = cached?.value.value;
516
+ if (cached && !cached.isStale && !cached.isExpired && value?.kind === "PAGES") return finalizeCachedPagesResponse(options.isDataReq ? applyCachedPagesRepresentationHeaders(buildNextDataPropsJsonResponse(normalizePagesRenderProps(value.pageData), options.safeJsonStringify, options.deploymentId ? { headers: { [NEXTJS_DEPLOYMENT_ID_HEADER]: options.deploymentId } } : void 0), "HIT", cached.value, options) : buildPagesCacheResponse(value.html, "HIT", options.fontLinkHeader, void 0, options.expireSeconds, cached.value.cacheControl, options.statusCode ?? value.status, value.headers), options, options.isDataReq ? void 0 : value.html);
517
+ }
518
+ let hasFreshPrerenderedEntry = false;
519
+ if (options.hasPrerenderedPages && options.route.isDynamic && typeof options.pageModule.getStaticProps === "function" && typeof options.pageModule.getServerSideProps !== "function" && !options.isOnDemandRevalidate && previewData === false) {
520
+ previousCacheEntry = await options.isrGet(options.isrCacheKey("pages", options.isrCachePathname ?? options.routeUrl.split("?")[0]));
521
+ const value = previousCacheEntry?.value.value;
522
+ hasFreshPrerenderedEntry = !!previousCacheEntry && !previousCacheEntry.isStale && !previousCacheEntry.isExpired && (value === null || value?.kind === "PAGES" || value?.kind === "REDIRECT");
523
+ }
524
+ if (!hasFreshPrerenderedEntry && typeof options.pageModule.getStaticPaths === "function" && options.route.isDynamic) {
525
+ const staticPathsI18n = {
526
+ ...options.i18n,
527
+ defaultLocale: options.staticPathsDefaultLocale ?? options.i18n.defaultLocale
528
+ };
497
529
  const pathsResult = await options.pageModule.getStaticPaths({
498
530
  locales: options.i18n.locales ?? [],
499
- defaultLocale: options.i18n.defaultLocale ?? ""
531
+ defaultLocale: staticPathsI18n.defaultLocale ?? ""
500
532
  });
501
533
  const fallback = pathsResult?.fallback ?? false;
502
534
  const paths = pathsResult?.paths ?? [];
503
535
  const routeParams = getPagesRouteParams(options.routePattern);
504
- const isValidPath = paths.some((pathEntry) => matchesPagesStaticPath(pathEntry, options.params, routeParams, options.routeUrl));
536
+ const isValidPath = paths.some((pathEntry) => matchesPagesStaticPath(pathEntry, options.params, routeParams, options.routeUrl, staticPathsI18n));
505
537
  if (fallback === false && !isValidPath && previewData === false) {
506
538
  if (options.isOnDemandRevalidate && !options.revalidateOnlyGenerated) return {
507
539
  kind: "response",
@@ -516,8 +548,8 @@ async function resolvePagesPageData(options) {
516
548
  }
517
549
  if (typeof options.pageModule.getStaticProps === "function" && options.isOnDemandRevalidate && options.revalidateOnlyGenerated) {
518
550
  const pathname = options.isrCachePathname ?? options.routeUrl.split("?")[0];
519
- onDemandPreviousCacheEntry = await options.isrGet(options.isrCacheKey("pages", pathname));
520
- if (!onDemandPreviousCacheEntry) return {
551
+ previousCacheEntry = await options.isrGet(options.isrCacheKey("pages", pathname));
552
+ if (!previousCacheEntry) return {
521
553
  kind: "response",
522
554
  response: new Response("This page could not be found", {
523
555
  status: 404,
@@ -616,7 +648,7 @@ async function resolvePagesPageData(options) {
616
648
  if (typeof options.pageModule.getStaticProps === "function") {
617
649
  const pathname = options.isrCachePathname ?? options.routeUrl.split("?")[0];
618
650
  const cacheKey = options.isrCacheKey("pages", pathname);
619
- const cached = onDemandPreviousCacheEntry !== void 0 ? onDemandPreviousCacheEntry : await options.isrGet(cacheKey);
651
+ const cached = previousCacheEntry !== void 0 ? previousCacheEntry : await options.isrGet(cacheKey);
620
652
  const cachedValue = cached?.value.value;
621
653
  const isLegacyCachedNotFound = cachedValue?.kind === "PAGES" && cachedValue.status === 404 && options.routePattern !== "/404" && options.routePattern !== "/_error";
622
654
  const cachedRedirect = getCachedPagesRedirect(cachedValue);
@@ -700,46 +732,20 @@ async function resolvePagesPageData(options) {
700
732
  if (!options.isOnDemandRevalidate && cached && !cached.isStale && !cached.isExpired && previewData === false) {
701
733
  if (cachedValue === null) return buildCachedPagesNotFoundResult(options, cached.value, "HIT");
702
734
  if (isLegacyCachedNotFound) return buildCachedPagesNotFoundResult(options, cached.value, "HIT");
703
- if (cachedRedirect) return {
704
- kind: "response",
705
- response: applyCachedPagesRepresentationHeaders(buildCachedPagesRedirectResponse(cachedRedirect, options), "HIT", cached.value, options)
706
- };
707
- if (options.isDataReq && cachedValue?.kind === "PAGES") return {
708
- kind: "response",
709
- response: applyCachedPagesRepresentationHeaders(buildNextDataPropsJsonResponse(normalizePagesRenderProps(cachedValue.pageData), options.safeJsonStringify, options.deploymentId ? { headers: { [NEXTJS_DEPLOYMENT_ID_HEADER]: options.deploymentId } } : void 0), "HIT", cached.value, options)
710
- };
711
- }
712
- if (!options.isOnDemandRevalidate && cached?.isStale === false && !cached.isExpired && cachedValue?.kind === "PAGES" && !cachedValue.generatedFromDataRequest && cached && !cached.isStale && !options.scriptNonce && !options.isDataReq && previewData === false) {
713
- const hitResponse = buildPagesCacheResponse(cachedValue.html, "HIT", options.fontLinkHeader, void 0, options.expireSeconds, cached.value.cacheControl, cachedValue.status, cachedValue.headers);
714
- const hitBotResult = applyBotETagAndCheck(hitResponse, cachedValue.html, options);
715
- if (hitBotResult) return hitBotResult;
716
- return {
717
- kind: "response",
718
- response: hitResponse
719
- };
735
+ if (cachedRedirect) return finalizeCachedPagesResponse(applyCachedPagesRepresentationHeaders(buildCachedPagesRedirectResponse(cachedRedirect, options), "HIT", cached.value, options), options);
736
+ if (options.isDataReq && cachedValue?.kind === "PAGES") return finalizeCachedPagesResponse(applyCachedPagesRepresentationHeaders(buildNextDataPropsJsonResponse(normalizePagesRenderProps(cachedValue.pageData), options.safeJsonStringify, options.deploymentId ? { headers: { [NEXTJS_DEPLOYMENT_ID_HEADER]: options.deploymentId } } : void 0), "HIT", cached.value, options), options);
720
737
  }
738
+ if (!options.isOnDemandRevalidate && cached?.isStale === false && !cached.isExpired && cachedValue?.kind === "PAGES" && !cachedValue.generatedFromDataRequest && cached && !cached.isStale && !options.scriptNonce && !options.isDataReq && previewData === false) return finalizeCachedPagesResponse(buildPagesCacheResponse(cachedValue.html, "HIT", options.fontLinkHeader, void 0, options.expireSeconds, cached.value.cacheControl, cachedValue.status, cachedValue.headers), options, cachedValue.html);
721
739
  if (!options.isOnDemandRevalidate && cached && cached.isStale && !cached.isExpired && !options.scriptNonce && previewData === false && (cachedValue === null || cachedRedirect !== null || isLegacyCachedNotFound || options.isDataReq)) {
722
740
  scheduleStaleRegeneration();
723
741
  if (cachedValue === null) return buildCachedPagesNotFoundResult(options, cached.value, "STALE");
724
742
  if (isLegacyCachedNotFound) return buildCachedPagesNotFoundResult(options, cached.value, "STALE");
725
- if (cachedRedirect) return {
726
- kind: "response",
727
- response: applyCachedPagesRepresentationHeaders(buildCachedPagesRedirectResponse(cachedRedirect, options), "STALE", cached.value, options)
728
- };
729
- if (cachedValue?.kind === "PAGES") return {
730
- kind: "response",
731
- response: applyCachedPagesRepresentationHeaders(buildNextDataPropsJsonResponse(normalizePagesRenderProps(cachedValue.pageData), options.safeJsonStringify, options.deploymentId ? { headers: { [NEXTJS_DEPLOYMENT_ID_HEADER]: options.deploymentId } } : void 0), "STALE", cached.value, options)
732
- };
743
+ if (cachedRedirect) return finalizeCachedPagesResponse(applyCachedPagesRepresentationHeaders(buildCachedPagesRedirectResponse(cachedRedirect, options), "STALE", cached.value, options), options);
744
+ if (cachedValue?.kind === "PAGES") return finalizeCachedPagesResponse(applyCachedPagesRepresentationHeaders(buildNextDataPropsJsonResponse(normalizePagesRenderProps(cachedValue.pageData), options.safeJsonStringify, options.deploymentId ? { headers: { [NEXTJS_DEPLOYMENT_ID_HEADER]: options.deploymentId } } : void 0), "STALE", cached.value, options), options);
733
745
  }
734
746
  if (!options.isOnDemandRevalidate && cachedValue?.kind === "PAGES" && !cachedValue.generatedFromDataRequest && cached && cached.isStale && !cached.isExpired && !options.scriptNonce && !options.isDataReq && previewData === false) {
735
747
  scheduleStaleRegeneration();
736
- const staleResponse = buildPagesCacheResponse(cachedValue.html, "STALE", options.fontLinkHeader, void 0, options.expireSeconds, cached.value.cacheControl, cachedValue.status, cachedValue.headers);
737
- const staleBotResult = applyBotETagAndCheck(staleResponse, cachedValue.html, options);
738
- if (staleBotResult) return staleBotResult;
739
- return {
740
- kind: "response",
741
- response: staleResponse
742
- };
748
+ return finalizeCachedPagesResponse(buildPagesCacheResponse(cachedValue.html, "STALE", options.fontLinkHeader, void 0, options.expireSeconds, cached.value.cacheControl, cachedValue.status, cachedValue.headers), options, cachedValue.html);
743
749
  }
744
750
  const generatedPageData = !options.isOnDemandRevalidate && previewData === false && cached?.isStale === false && !cached.isExpired && cachedValue?.kind === "PAGES" && cachedValue.generatedFromDataRequest && isUnknownRecord(cachedValue.pageData) ? cachedValue.pageData : null;
745
751
  if (!generatedPageData) {
@@ -6,11 +6,12 @@ import { getRequestExecutionContext } from "../shims/request-context.js";
6
6
  import { NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_CACHE_HEADER, VINEXT_REVALIDATED_CACHE_TAG_HEADER } from "./headers.js";
7
7
  import { extractLocaleFromUrl, resolvePagesI18nRequest } from "./pages-i18n.js";
8
8
  import { reportRequestError } from "./instrumentation.js";
9
- import { beginRouteCacheability, isRouteCacheabilityIdentityProbe, isRouteCacheabilityProbe, recordRouteCacheability } from "../shims/cacheability-classification.js";
10
- import { BROWSER_REVALIDATE_CACHE_CONTROL, NEVER_CACHE_CONTROL, STATIC_CACHE_CONTROL, applyCdnResponseHeaders, hasExplicitNonCacheableResponsePolicy, shouldUseNextDeployCacheControl } from "./cache-control.js";
9
+ import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
10
+ import { beginRouteCacheability, isRouteCacheabilityIdentityProbe, isRouteCacheabilityProbe, markRouteCacheabilityExplicitResponsePolicy, recordRouteCacheability } from "../shims/cacheability-classification.js";
11
+ import { BROWSER_REVALIDATE_CACHE_CONTROL, NEVER_CACHE_CONTROL, STATIC_CACHE_CONTROL, applyCdnResponseHeaders, hasCdnResponsePolicy, hasExplicitNonCacheableResponsePolicy, shouldUseNextDeployCacheControl } from "./cache-control.js";
11
12
  import { buildMissIsrCacheControl } from "./isr-decision.js";
12
13
  import { isOnDemandRevalidateRequest } from "./revalidation-request.js";
13
- import { coalesceOnDemandRevalidation, isrCacheKey, isrGet, isrSet, triggerBackgroundRegeneration } from "./isr-cache.js";
14
+ import { coalesceOnDemandRevalidation, isrGet, isrSet, pagesIsrCacheKey, triggerBackgroundRegeneration } from "./isr-cache.js";
14
15
  import { encodeCacheTag } from "../utils/encode-cache-tag.js";
15
16
  import { ensureFetchPatch } from "../shims/fetch-cache.js";
16
17
  import { mergeRouteParamsIntoQuery, parseQueryString } from "../utils/query.js";
@@ -91,6 +92,10 @@ function stripPagesNotFoundFramingHeaders(response) {
91
92
  }
92
93
  function applyPagesErrorCachePolicy(response, revalidateSeconds, expireSeconds, cacheTagPathname) {
93
94
  const headers = new Headers(response.headers);
95
+ recordRouteCacheability(revalidateSeconds === void 0 ? { cacheable: false } : {
96
+ cacheable: revalidateSeconds !== 0,
97
+ cacheControl: buildMissIsrCacheControl(revalidateSeconds, expireSeconds)
98
+ });
94
99
  if (hasExplicitNonCacheableResponsePolicy(headers)) return response;
95
100
  if (revalidateSeconds === void 0) applyCdnResponseHeaders(headers, { cacheControl: NEVER_CACHE_CONTROL });
96
101
  else {
@@ -135,8 +140,7 @@ function createPagesPageHandler(opts) {
135
140
  return errorPageRoute;
136
141
  }
137
142
  function isrCacheKeyForRequest(i18nCacheVariant) {
138
- if (!i18nCacheVariant) return (router, pathname) => isrCacheKey(router, pathname, buildId ?? void 0);
139
- return (router, pathname) => isrCacheKey(router, pathname + "::i18n=" + encodeURIComponent(i18nCacheVariant), buildId ?? void 0);
143
+ return (_router, pathname) => pagesIsrCacheKey(pathname, buildId ?? void 0, i18nCacheVariant);
140
144
  }
141
145
  async function renderPage(request, url, manifest, middlewareHeaders, options, initialResponseHeaders) {
142
146
  let isDataReq = !!(options && options.isDataReq);
@@ -186,7 +190,7 @@ function createPagesPageHandler(opts) {
186
190
  const routeUrl = localeInfo.url;
187
191
  const currentDefaultLocale = i18nConfig ? localeInfo.domainLocale ? localeInfo.domainLocale.defaultLocale : i18nConfig.defaultLocale : void 0;
188
192
  const domainLocales = i18nConfig ? i18nConfig.domains : void 0;
189
- const pageIsrCacheKey = isrCacheKeyForRequest(i18nConfig ? localeInfo.domainLocale ? "domain:" + String(localeInfo.domainLocale.domain).toLowerCase() : "locale:" + String(locale) : null);
193
+ const pageIsrCacheKey = isrCacheKeyForRequest(i18nConfig ? localeInfo.domainLocale ? JSON.stringify([String(localeInfo.domainLocale.domain).toLowerCase(), locale]) : "locale:" + String(locale) : null);
190
194
  if (localeInfo.redirectUrl) return new Response(null, {
191
195
  status: 307,
192
196
  headers: { Location: localeInfo.redirectUrl }
@@ -228,6 +232,7 @@ function createPagesPageHandler(opts) {
228
232
  cacheable: true,
229
233
  cacheControl: STATIC_CACHE_CONTROL
230
234
  });
235
+ else recordRouteCacheability({ cacheable: false });
231
236
  }
232
237
  const routeIsrGet = isCacheabilityProbe ? async () => null : isrGet;
233
238
  const routeIsrSet = isCacheabilityProbe ? async () => {} : isrSet;
@@ -262,7 +267,7 @@ function createPagesPageHandler(opts) {
262
267
  const routePattern = patternToNextFormat(route.pattern);
263
268
  setFrameworkRequestRoute(routePattern);
264
269
  const renderStatusCode = renderStatusCodeOverride ?? (routePattern === "/404" ? 404 : void 0);
265
- const isrCachePathname = isStaticPropsRender && (routePattern === "/404" || routePattern === "/500" || routePattern === "/_error") ? routePattern : renderRouteUrl.split("?")[0];
270
+ const isrCachePathname = (isStaticPropsRender || pagesReadiness.autoExport) && (routePattern === "/404" || routePattern === "/500" || routePattern === "/_error") ? routePattern === "/_error" && renderStatusCode === 404 ? "/404" : routePattern : renderRouteUrl.split("?")[0];
266
271
  const isNotFoundErrorRender = routePattern === "/404" || routePattern === "/_error" && renderStatusCode === 404;
267
272
  const isStatusErrorRender = isNotFoundErrorRender || routePattern === "/500" || routePattern === "/_error" && renderStatusCode === 500;
268
273
  const errorPageRevalidateSeconds = isNotFoundErrorRender ? options?.__notFoundRevalidateSeconds : void 0;
@@ -327,6 +332,11 @@ function createPagesPageHandler(opts) {
327
332
  }
328
333
  };
329
334
  const scriptNonce = getScriptNonceFromHeaderSources(request.headers, middlewareHeaders);
335
+ const browserCacheControl = isStaticPropsRoute && !scriptNonce ? (initialResponseHeaders ?? middlewareHeaders)?.get("Cache-Control") : null;
336
+ const withBrowserPolicy = (response) => {
337
+ if (browserCacheControl) response.headers.set("Cache-Control", browserCacheControl);
338
+ return response;
339
+ };
330
340
  const shouldApplyErrorResponsePolicy = previewData === false && !scriptNonce && isStatusErrorRender && (isStaticPropsRoute || isRouteMissErrorRender || options?.__forcedRoute !== void 0);
331
341
  let fontLinkHeader = "";
332
342
  let allFontPreloads = [];
@@ -366,8 +376,10 @@ function createPagesPageHandler(opts) {
366
376
  },
367
377
  fontLinkHeader,
368
378
  i18n: buildI18nRenderContext(i18nConfig, locale, currentDefaultLocale, domainLocales),
379
+ staticPathsDefaultLocale: i18nConfig?.defaultLocale,
369
380
  isrCacheKey: pageIsrCacheKey,
370
381
  isrGet: routeIsrGet,
382
+ hasPrerenderedPages: getCdnCacheAdapter().hasPrerenderedPages,
371
383
  isrSet: routeIsrSet,
372
384
  expireSeconds: vinextConfig.expireTime,
373
385
  isBuildTimePrerendering: typeof process !== "undefined" && process.env && process.env.VINEXT_PRERENDER === "1",
@@ -403,6 +415,7 @@ function createPagesPageHandler(opts) {
403
415
  sanitizeDestination,
404
416
  scriptNonce,
405
417
  statusCode: renderStatusCode,
418
+ notFoundSourceHeaders: options?.__notFoundSourceHeaders,
406
419
  triggerBackgroundRegeneration,
407
420
  vinext: serializedPagesNextData.__vinext,
408
421
  nextData: serializedPagesNextData,
@@ -427,12 +440,12 @@ function createPagesPageHandler(opts) {
427
440
  notFoundResponse = stripPagesNotFoundFramingHeaders(notFoundResponse);
428
441
  if (isOnDemandRevalidate) notFoundResponse = withPagesCacheState(notFoundResponse, "REVALIDATED", isrCachePathname);
429
442
  else if (pageDataResult.cacheState) notFoundResponse = withPagesCacheState(notFoundResponse, pageDataResult.cacheState);
430
- return finalizePagesPreviewResponse(notFoundResponse, preview);
443
+ return finalizePagesPreviewResponse(withBrowserPolicy(notFoundResponse), preview);
431
444
  }
432
445
  if (pageDataResult.kind === "response") {
433
446
  let response = isOnDemandRevalidate && pageDataResult.onDemandRevalidateSuccess !== false ? withPagesCacheState(pageDataResult.response, "REVALIDATED", isrCachePathname) : pageDataResult.response;
434
447
  if (shouldApplyErrorResponsePolicy) response = applyPagesErrorCachePolicy(response, errorPageRevalidateSeconds, errorPageExpireSeconds, errorResponseCachePathname);
435
- return finalizePagesPreviewResponse(response, preview);
448
+ return finalizePagesPreviewResponse(withBrowserPolicy(response), preview);
436
449
  }
437
450
  let pageProps = pageDataResult.pageProps;
438
451
  let renderProps = pageDataResult.props;
@@ -453,6 +466,10 @@ function createPagesPageHandler(opts) {
453
466
  const gsspRes = pageDataResult.gsspRes;
454
467
  const documentReqRes = serializedPagesNextData.autoExport === true && !options?.__notFoundSourceHeaders ? null : pageDataResult.documentReqRes ?? createPageReqRes();
455
468
  const isrRevalidateSeconds = pageDataResult.isrRevalidateSeconds;
469
+ if (isStaticPropsRoute && preview.data === false && !preview.shouldClear && isrRevalidateSeconds !== null) recordRouteCacheability({
470
+ cacheable: isrRevalidateSeconds !== 0,
471
+ cacheControl: buildMissIsrCacheControl(isrRevalidateSeconds, vinextConfig.expireTime)
472
+ });
456
473
  const isrExpireSeconds = pageDataResult.isrExpireSeconds;
457
474
  const isFallbackRender = pageDataResult.isFallback === true;
458
475
  if (isFallbackRender) applySSRContext({
@@ -472,6 +489,7 @@ function createPagesPageHandler(opts) {
472
489
  else headers.set(k, Array.isArray(v) ? v.join(", ") : String(v));
473
490
  }
474
491
  }
492
+ if (hasCdnResponsePolicy(headers)) markRouteCacheabilityExplicitResponsePolicy();
475
493
  if (gsspRes) {
476
494
  if (!headers.has("Cache-Control")) headers.set("Cache-Control", NEVER_CACHE_CONTROL);
477
495
  } else if (isStaticPropsRoute) {
@@ -487,7 +505,7 @@ function createPagesPageHandler(opts) {
487
505
  const deploymentId = process.env.__VINEXT_DEPLOYMENT_ID || process.env.NEXT_DEPLOYMENT_ID;
488
506
  if (deploymentId) headers.set(NEXTJS_DEPLOYMENT_ID_HEADER, deploymentId);
489
507
  }
490
- return finalizePagesPreviewResponse(buildNextDataPropsJsonResponse(renderProps, safeJsonStringify, { headers }), preview);
508
+ return finalizePagesPreviewResponse(withBrowserPolicy(buildNextDataPropsJsonResponse(renderProps, safeJsonStringify, { headers })), preview);
491
509
  }
492
510
  const pageModuleIds = [];
493
511
  if (appAssetPath) pageModuleIds.push(appAssetPath);
@@ -561,7 +579,7 @@ function createPagesPageHandler(opts) {
561
579
  requestCacheControl: request.headers.get("cache-control") ?? void 0
562
580
  });
563
581
  if (shouldApplyErrorResponsePolicy) pageResponse = applyPagesErrorCachePolicy(pageResponse, errorPageRevalidateSeconds, errorPageExpireSeconds, errorResponseCachePathname);
564
- return finalizePagesPreviewResponse(pageResponse, preview);
582
+ return finalizePagesPreviewResponse(withBrowserPolicy(pageResponse), preview);
565
583
  } catch (e) {
566
584
  console.error("[vinext] SSR error:", e);
567
585
  await reportRequestError(e, {
@@ -2,7 +2,8 @@ import { isBotUserAgent } from "../utils/html-limited-bots.js";
2
2
  import { getRequestExecutionContext } from "../shims/request-context.js";
3
3
  import { NEXTJS_CACHE_HEADER, VINEXT_REVALIDATED_CACHE_TAG_HEADER } from "./headers.js";
4
4
  import { reportRequestError } from "./instrumentation.js";
5
- import { BROWSER_REVALIDATE_CACHE_CONTROL, NEVER_CACHE_CONTROL, NO_STORE_CACHE_CONTROL, applyCdnResponseHeaders, shouldUseNextDeployCacheControl } from "./cache-control.js";
5
+ import { markRouteCacheabilityExplicitResponsePolicy } from "../shims/cacheability-classification.js";
6
+ import { BROWSER_REVALIDATE_CACHE_CONTROL, NEVER_CACHE_CONTROL, NO_STORE_CACHE_CONTROL, applyCdnResponseHeaders, hasCdnResponsePolicy, shouldUseNextDeployCacheControl } from "./cache-control.js";
6
7
  import { buildMissIsrCacheControl } from "./isr-decision.js";
7
8
  import { fnv1a52 } from "../utils/hash.js";
8
9
  import { isrCacheControl } from "./isr-cache.js";
@@ -271,6 +272,7 @@ async function renderPagesPageResponse(options) {
271
272
  }
272
273
  const compositeStream = await buildPagesCompositeStream(responseBodyStream, shellPrefix, shellSuffix);
273
274
  const userSetCacheControl = responseHeaders.has("Cache-Control");
275
+ if (hasCdnResponsePolicy(responseHeaders)) markRouteCacheabilityExplicitResponsePolicy();
274
276
  if (options.scriptNonce) responseHeaders.set("Cache-Control", NO_STORE_CACHE_CONTROL);
275
277
  else if (options.isrRevalidateSeconds !== null) {
276
278
  const isrPathname = options.isrCachePathname ?? options.routeUrl.split("?")[0];
@@ -15,7 +15,7 @@ type PageRouteMatch = {
15
15
  dataKind?: PagesRouteDataKind;
16
16
  };
17
17
  };
18
- export declare function fetchWorkerFilesystemRoute(request: Request, requestPathname: string, phase: FilesystemRoutePhase, fetchAsset: (request: Request) => Promise<Response>, publicFiles?: ReadonlySet<string>, isDirectBuildAsset?: boolean): Promise<Response | false>;
18
+ export declare function fetchWorkerFilesystemRoute(request: Request, requestPathname: string, phase: FilesystemRoutePhase, fetchAsset: (request: Request) => Promise<Response>, publicFiles: ReadonlySet<string>, basePath?: string, assetPathPrefix?: string): Promise<Response | false>;
19
19
  export type MiddlewareResult = {
20
20
  continue: boolean;
21
21
  /** The pathname matches middleware, irrespective of request `has`/`missing` conditions. */
@@ -30,6 +30,7 @@ export type MiddlewareResult = {
30
30
  waitUntilPromises?: Promise<unknown>[];
31
31
  };
32
32
  export type PagesPipelineDeps = {
33
+ assetPrefix?: string;
33
34
  basePath: string;
34
35
  trailingSlash: boolean;
35
36
  i18nConfig: NextI18nConfig | null;