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.
- package/THIRD_PARTY_LICENSES.md +26 -0
- package/dist/build/lifecycle.js +10 -10
- package/dist/build/pages-client-assets-module.js +6 -1
- package/dist/build/precompress.js +1 -1
- package/dist/build/prerender-paths.js +3 -7
- package/dist/build/prerender.d.ts +8 -1
- package/dist/build/prerender.js +134 -38
- package/dist/build/run-prerender.js +4 -3
- package/dist/build/server-entry.d.ts +2 -0
- package/dist/build/server-entry.js +7 -1
- package/dist/client/browser-globals.d.ts +4 -0
- package/dist/client/browser-globals.js +5 -0
- package/dist/client/navigation-runtime.d.ts +0 -1
- package/dist/client/navigation-runtime.js +2 -2
- package/dist/config/dotenv.js +14 -3
- package/dist/entries/app-rsc-entry.js +3 -2
- package/dist/index.js +142 -71
- package/dist/init-cloudflare.d.ts +1 -1
- package/dist/init-cloudflare.js +6 -6
- package/dist/init-platform.js +1 -1
- package/dist/init.js +4 -2
- package/dist/plugins/commonjs-syntax.d.ts +16 -0
- package/dist/plugins/commonjs-syntax.js +22 -0
- package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
- package/dist/plugins/ignore-dynamic-requests.js +54 -3
- package/dist/plugins/import-meta-url.js +6 -6
- package/dist/plugins/og-asset-ownership.d.ts +2 -0
- package/dist/plugins/og-asset-ownership.js +24 -13
- package/dist/plugins/og-assets.d.ts +18 -0
- package/dist/plugins/og-assets.js +50 -8
- package/dist/plugins/og-harfbuzz.js +38 -27
- package/dist/plugins/optimize-imports.js +2 -1
- package/dist/plugins/require-context.d.ts +1 -0
- package/dist/plugins/require-context.js +28 -1
- package/dist/plugins/scan-build-css.d.ts +12 -0
- package/dist/plugins/scan-build-css.js +39 -0
- package/dist/plugins/strip-server-exports.d.ts +2 -0
- package/dist/plugins/strip-server-exports.js +3 -1
- package/dist/plugins/transform-result.d.ts +18 -0
- package/dist/plugins/transform-result.js +23 -2
- package/dist/plugins/typeof-window.d.ts +10 -0
- package/dist/plugins/typeof-window.js +33 -9
- package/dist/routing/app-route-graph.d.ts +0 -1
- package/dist/routing/app-route-graph.js +2 -4
- package/dist/routing/app-route-ids.d.ts +3 -0
- package/dist/routing/app-route-ids.js +6 -0
- package/dist/server/app-bfcache-id.d.ts +1 -0
- package/dist/server/app-bfcache-id.js +7 -1
- package/dist/server/app-bfcache-identity.js +1 -2
- package/dist/server/app-browser-entry.js +4 -2
- package/dist/server/app-browser-hydration.d.ts +1 -1
- package/dist/server/app-browser-hydration.js +2 -2
- package/dist/server/app-browser-navigation-controller.js +1 -1
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-stream.d.ts +1 -1
- package/dist/server/app-history-state.d.ts +0 -1
- package/dist/server/app-history-state.js +2 -5
- package/dist/server/app-page-cache-render.js +2 -1
- package/dist/server/app-page-render.js +2 -1
- package/dist/server/app-page-search-params-observation.js +1 -1
- package/dist/server/app-page-stream.js +1 -1
- package/dist/server/app-page-tracing.js +2 -1
- package/dist/server/app-pages-bridge.js +3 -2
- package/dist/server/app-render-abort-error.d.ts +3 -0
- package/dist/server/app-render-abort-error.js +8 -0
- package/dist/server/app-request-stage-independent-entry.js +4 -7
- package/dist/server/app-route-handler-cache.d.ts +2 -1
- package/dist/server/app-route-handler-cache.js +11 -7
- package/dist/server/app-route-handler-dispatch.js +10 -3
- package/dist/server/app-route-handler-execution.d.ts +9 -1
- package/dist/server/app-route-handler-execution.js +28 -13
- package/dist/server/app-route-handler-policy.js +2 -2
- package/dist/server/app-route-handler-response.d.ts +1 -1
- package/dist/server/app-route-handler-response.js +14 -5
- package/dist/server/app-router-entry.d.ts +2 -1
- package/dist/server/app-router-entry.js +5 -9
- package/dist/server/app-rsc-errors.d.ts +0 -1
- package/dist/server/app-rsc-errors.js +2 -6
- package/dist/server/app-rsc-handler.d.ts +1 -0
- package/dist/server/app-rsc-handler.js +18 -7
- package/dist/server/app-rsc-request-normalization.d.ts +1 -1
- package/dist/server/app-rsc-request-normalization.js +3 -2
- package/dist/server/app-rsc-response-finalizer.js +4 -1
- package/dist/server/app-rsc-route-matching.js +1 -1
- package/dist/server/app-server-action-execution.d.ts +2 -1
- package/dist/server/app-ssr-entry.js +3 -3
- package/dist/server/app-ssr-search-params-gate.js +1 -1
- package/dist/server/app-ssr-stream.js +1 -1
- package/dist/server/cache-control.js +3 -11
- package/dist/server/cacheability-request.js +49 -49
- package/dist/server/config-headers.js +1 -1
- package/dist/server/dev-server.js +11 -3
- package/dist/server/headers.d.ts +2 -0
- package/dist/server/headers.js +5 -1
- package/dist/server/http-error-responses.js +1 -0
- package/dist/server/isr-cache.d.ts +2 -0
- package/dist/server/isr-cache.js +6 -1
- package/dist/server/metadata-route-response.js +94 -37
- package/dist/server/pages-api-route.js +8 -2
- package/dist/server/pages-asset-tags.d.ts +1 -0
- package/dist/server/pages-asset-tags.js +73 -22
- package/dist/server/pages-client-assets.d.ts +2 -0
- package/dist/server/pages-page-data.d.ts +6 -1
- package/dist/server/pages-page-data.js +71 -65
- package/dist/server/pages-page-handler.js +29 -11
- package/dist/server/pages-page-response.js +3 -1
- package/dist/server/pages-request-pipeline.d.ts +2 -1
- package/dist/server/pages-request-pipeline.js +20 -5
- package/dist/server/pages-request-stage-entry.js +6 -4
- package/dist/server/prerender-manifest.d.ts +6 -0
- package/dist/server/prerender-manifest.js +1 -1
- package/dist/server/prod-server.js +3 -13
- package/dist/server/response-stage-cacheability.js +1 -1
- package/dist/server/worker-revalidation-context.d.ts +2 -1
- package/dist/server/worker-revalidation-context.js +1 -0
- package/dist/server/workers-tracing.d.ts +17 -0
- package/dist/server/workers-tracing.js +48 -8
- package/dist/shims/cache-request-state.d.ts +3 -14
- package/dist/shims/cache-request-state.js +2 -13
- package/dist/shims/cache-runtime.js +4 -2
- package/dist/shims/cache.d.ts +2 -1
- package/dist/shims/cache.js +4 -2
- package/dist/shims/cacheability-classification.d.ts +1 -1
- package/dist/shims/cacheability-classification.js +2 -2
- package/dist/shims/cdn-cache.d.ts +10 -1
- package/dist/shims/cdn-cache.js +16 -9
- package/dist/shims/error.d.ts +4 -18
- package/dist/shims/error.js +17 -10
- package/dist/shims/error.react-server.d.ts +4 -6
- package/dist/shims/error.react-server.js +4 -1
- package/dist/shims/fetch-cache.js +4 -3
- package/dist/shims/headers.d.ts +6 -69
- package/dist/shims/headers.js +37 -181
- package/dist/shims/internal/cache-context-accessor.d.ts +16 -0
- package/dist/shims/internal/cache-context-accessor.js +15 -0
- package/dist/shims/internal/headers-state.d.ts +74 -0
- package/dist/shims/internal/headers-state.js +157 -0
- package/dist/shims/navigation.js +2 -2
- package/dist/shims/request-state-types.d.ts +2 -1
- package/dist/shims/root-params.js +1 -1
- package/dist/shims/server.js +52 -2
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/utils/encode-cache-tag.d.ts +1 -0
- package/dist/utils/encode-cache-tag.js +11 -1
- package/dist/utils/vite-cli-invocation.js +8 -1
- package/package.json +6 -2
- package/dist/server/metadata-route-cache-policy.d.ts +0 -5
- 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
|
|
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
|
|
33
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
132
|
-
|
|
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
|
-
|
|
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
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
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:
|
|
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
|
|
511
|
+
let previousCacheEntry;
|
|
495
512
|
const previewData = options.isOnDemandRevalidate ? false : options.previewData ?? false;
|
|
496
|
-
if (
|
|
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:
|
|
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
|
-
|
|
520
|
-
if (!
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
10
|
-
import {
|
|
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,
|
|
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
|
-
|
|
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 ?
|
|
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 {
|
|
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
|
|
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;
|