vinext 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -1
- package/THIRD_PARTY_LICENSES.md +26 -0
- package/dist/build/app-page-static-eligibility.d.ts +15 -0
- package/dist/build/app-page-static-eligibility.js +82 -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 +6 -85
- package/dist/build/prerender.d.ts +8 -1
- package/dist/build/prerender.js +167 -46
- 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/build/server-manifest.d.ts +7 -0
- package/dist/build/server-manifest.js +11 -1
- package/dist/cache/cache-adapters-virtual.d.ts +7 -1
- package/dist/cache/cache-adapters-virtual.js +3 -3
- package/dist/client/browser-globals.d.ts +4 -0
- package/dist/client/browser-globals.js +5 -0
- package/dist/client/navigation-runtime.d.ts +11 -1
- package/dist/client/navigation-runtime.js +3 -3
- package/dist/config/config-matchers.js +3 -1
- package/dist/config/dotenv.js +14 -3
- package/dist/config/next-config.d.ts +7 -0
- package/dist/config/next-config.js +18 -3
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +67 -45
- package/dist/index.d.ts +4 -1
- package/dist/index.js +200 -100
- 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/cache-flight-codec.d.ts +19 -0
- package/dist/plugins/cache-flight-codec.js +68 -0
- package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
- package/dist/plugins/commonjs-esm-facade.js +80 -0
- package/dist/plugins/commonjs-syntax.d.ts +16 -0
- package/dist/plugins/commonjs-syntax.js +22 -0
- package/dist/plugins/fonts.d.ts +8 -11
- package/dist/plugins/fonts.js +71 -34
- 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/routing/file-matcher.d.ts +1 -0
- package/dist/routing/file-matcher.js +1 -1
- package/dist/server/api-handler.js +17 -7
- 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 +15 -9
- package/dist/server/app-browser-history-controller.d.ts +2 -0
- package/dist/server/app-browser-history-controller.js +8 -0
- package/dist/server/app-browser-hydration.d.ts +1 -1
- package/dist/server/app-browser-hydration.js +2 -2
- package/dist/server/app-browser-interception-context.js +26 -2
- package/dist/server/app-browser-navigation-controller.d.ts +7 -1
- package/dist/server/app-browser-navigation-controller.js +94 -11
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-stream.d.ts +1 -1
- package/dist/server/app-fallback-renderer.d.ts +2 -0
- package/dist/server/app-fallback-renderer.js +1 -0
- package/dist/server/app-history-state.d.ts +3 -1
- package/dist/server/app-history-state.js +9 -5
- package/dist/server/app-middleware.js +2 -1
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-boundary-render.d.ts +5 -0
- package/dist/server/app-page-boundary-render.js +6 -4
- package/dist/server/app-page-cache-finalizer.d.ts +11 -0
- package/dist/server/app-page-cache-finalizer.js +41 -7
- package/dist/server/app-page-cache-render.d.ts +18 -0
- package/dist/server/app-page-cache-render.js +65 -44
- package/dist/server/app-page-cache.d.ts +5 -0
- package/dist/server/app-page-cache.js +27 -7
- package/dist/server/app-page-dispatch.d.ts +9 -1
- package/dist/server/app-page-dispatch.js +47 -30
- package/dist/server/app-page-element-builder.d.ts +7 -0
- package/dist/server/app-page-element-builder.js +27 -42
- package/dist/server/app-page-execution.d.ts +15 -12
- package/dist/server/app-page-execution.js +30 -40
- package/dist/server/app-page-head.d.ts +5 -0
- package/dist/server/app-page-head.js +9 -3
- package/dist/server/app-page-probe.d.ts +0 -109
- package/dist/server/app-page-probe.js +3 -136
- package/dist/server/app-page-render-identity.d.ts +0 -1
- package/dist/server/app-page-render-identity.js +1 -1
- package/dist/server/app-page-render-observation.js +2 -2
- package/dist/server/app-page-render.d.ts +13 -5
- package/dist/server/app-page-render.js +219 -118
- package/dist/server/app-page-request.d.ts +0 -1
- package/dist/server/app-page-request.js +1 -2
- package/dist/server/app-page-response.d.ts +4 -3
- package/dist/server/app-page-response.js +4 -3
- package/dist/server/app-page-route-wiring.d.ts +17 -5
- package/dist/server/app-page-route-wiring.js +55 -33
- package/dist/server/app-page-rsc-render-status.d.ts +48 -0
- package/dist/server/app-page-rsc-render-status.js +54 -0
- package/dist/server/app-page-search-params-observation.js +1 -1
- package/dist/server/app-page-stream.d.ts +15 -8
- package/dist/server/app-page-stream.js +7 -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-dispatch.js +1 -1
- package/dist/server/app-request-stage-independent-entry.js +8 -11
- package/dist/server/app-response-header-provenance.d.ts +2 -0
- package/dist/server/app-response-header-provenance.js +10 -4
- 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 +11 -4
- 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 +8 -12
- 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 +5 -0
- package/dist/server/app-rsc-handler.js +229 -102
- package/dist/server/app-rsc-request-normalization.d.ts +4 -2
- package/dist/server/app-rsc-request-normalization.js +7 -4
- package/dist/server/app-rsc-response-finalizer.js +4 -1
- package/dist/server/app-rsc-response-stage.d.ts +1 -1
- package/dist/server/app-rsc-response-stage.js +6 -4
- package/dist/server/app-rsc-route-matching.d.ts +9 -1
- package/dist/server/app-rsc-route-matching.js +37 -20
- package/dist/server/app-server-action-execution.d.ts +2 -1
- package/dist/server/app-server-action-execution.js +1 -1
- package/dist/server/app-ssr-entry.d.ts +3 -2
- package/dist/server/app-ssr-entry.js +9 -7
- package/dist/server/app-ssr-search-params-gate.js +1 -1
- package/dist/server/app-ssr-stream.d.ts +6 -1
- package/dist/server/app-ssr-stream.js +35 -16
- package/dist/server/app-worker-stages.d.ts +2 -2
- package/dist/server/app-worker-stages.js +3 -3
- package/dist/server/cache-control.js +3 -11
- package/dist/server/cacheability-request.js +56 -52
- package/dist/server/config-headers.js +3 -1
- package/dist/server/dev-server.js +23 -5
- package/dist/server/headers.d.ts +16 -0
- package/dist/server/headers.js +19 -1
- package/dist/server/http-error-responses.js +1 -0
- package/dist/server/image-optimization.d.ts +16 -0
- package/dist/server/image-optimization.js +26 -6
- package/dist/server/isr-cache.d.ts +2 -0
- package/dist/server/isr-cache.js +8 -3
- package/dist/server/metadata-route-response.js +94 -37
- package/dist/server/middleware-matcher-pattern.js +8 -4
- package/dist/server/middleware-response-headers.js +2 -0
- package/dist/server/multi-stage.d.ts +8 -0
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/node-response-signal.d.ts +16 -0
- package/dist/server/node-response-signal.js +26 -0
- package/dist/server/open-redirect.d.ts +47 -0
- package/dist/server/open-redirect.js +74 -1
- 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 +50 -15
- 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 +14 -8
- package/dist/server/prerender-manifest.d.ts +6 -0
- package/dist/server/prerender-manifest.js +1 -1
- package/dist/server/prod-server.d.ts +8 -7
- package/dist/server/prod-server.js +152 -78
- package/dist/server/request-pipeline.d.ts +20 -8
- package/dist/server/request-pipeline.js +21 -7
- package/dist/server/response-compression.d.ts +43 -0
- package/dist/server/response-compression.js +111 -0
- package/dist/server/response-stage-cacheability.js +1 -1
- package/dist/server/seed-cache.js +10 -7
- package/dist/server/socket-error-backstop.d.ts +14 -0
- package/dist/server/socket-error-backstop.js +27 -4
- 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-adapter-instantiate.d.ts +50 -0
- package/dist/shims/cache-adapter-instantiate.js +118 -0
- package/dist/shims/cache-callable-runtime.d.ts +2 -40
- package/dist/shims/cache-callable-runtime.js +50 -168
- package/dist/shims/cache-flight-arguments.d.ts +22 -0
- package/dist/shims/cache-flight-arguments.js +56 -0
- package/dist/shims/cache-request-state.d.ts +18 -14
- package/dist/shims/cache-request-state.js +33 -21
- package/dist/shims/cache-runtime.d.ts +6 -19
- package/dist/shims/cache-runtime.js +168 -226
- package/dist/shims/cache.d.ts +3 -2
- package/dist/shims/cache.js +8 -5
- package/dist/shims/cacheability-classification.d.ts +8 -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-boundary-navigation.d.ts +7 -0
- package/dist/shims/error-boundary-navigation.js +19 -1
- package/dist/shims/error-boundary.d.ts +10 -10
- package/dist/shims/error-boundary.js +26 -7
- 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.d.ts +6 -0
- package/dist/shims/fetch-cache.js +23 -4
- package/dist/shims/form.js +1 -1
- package/dist/shims/headers.d.ts +19 -69
- package/dist/shims/headers.js +82 -183
- package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
- package/dist/shims/internal/app-page-props-cache-key.js +24 -15
- 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 +73 -0
- package/dist/shims/internal/headers-state.js +157 -0
- package/dist/shims/metadata.js +3 -3
- package/dist/shims/navigation-errors.d.ts +6 -0
- package/dist/shims/navigation-errors.js +11 -1
- package/dist/shims/navigation.d.ts +7 -0
- package/dist/shims/navigation.js +16 -6
- package/dist/shims/request-context.d.ts +9 -0
- 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/thenable-params.d.ts +4 -0
- package/dist/shims/thenable-params.js +25 -3
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/utils/encode-cache-tag.d.ts +1 -0
- package/dist/utils/encode-cache-tag.js +11 -1
- package/dist/utils/mdx-scan.d.ts +5 -0
- package/dist/utils/mdx-scan.js +8 -1
- package/dist/utils/regex-safety.d.ts +10 -0
- package/dist/utils/regex-safety.js +70 -18
- package/dist/utils/vite-cli-invocation.js +8 -1
- package/package.json +8 -4
- 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) {
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { preserveFullyBufferedBodyMetadata } from "./fully-buffered-response.js";
|
|
2
2
|
import { closeAfterResponse, closeAfterResponseWithBody, createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
3
3
|
import { PRERENDER_REVALIDATE_HEADER } from "../utils/protocol-headers.js";
|
|
4
|
+
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
4
5
|
import { patternToNextFormat } from "../routing/route-validation.js";
|
|
5
6
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
6
7
|
import { NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_CACHE_HEADER, VINEXT_REVALIDATED_CACHE_TAG_HEADER } from "./headers.js";
|
|
7
8
|
import { extractLocaleFromUrl, resolvePagesI18nRequest } from "./pages-i18n.js";
|
|
8
9
|
import { reportRequestError } from "./instrumentation.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
10
|
+
import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
|
|
11
|
+
import { beginRouteCacheability, isRouteCacheabilityIdentityProbe, isRouteCacheabilityProbe, markRouteCacheabilityExplicitResponsePolicy, recordRouteCacheability } from "../shims/cacheability-classification.js";
|
|
12
|
+
import { BROWSER_REVALIDATE_CACHE_CONTROL, NEVER_CACHE_CONTROL, STATIC_CACHE_CONTROL, applyCdnResponseHeaders, hasCdnResponsePolicy, hasExplicitNonCacheableResponsePolicy, shouldUseNextDeployCacheControl } from "./cache-control.js";
|
|
11
13
|
import { buildMissIsrCacheControl } from "./isr-decision.js";
|
|
12
14
|
import { isOnDemandRevalidateRequest } from "./revalidation-request.js";
|
|
13
|
-
import { coalesceOnDemandRevalidation,
|
|
15
|
+
import { coalesceOnDemandRevalidation, isrGet, isrSet, pagesIsrCacheKey, triggerBackgroundRegeneration } from "./isr-cache.js";
|
|
14
16
|
import { encodeCacheTag } from "../utils/encode-cache-tag.js";
|
|
15
17
|
import { ensureFetchPatch } from "../shims/fetch-cache.js";
|
|
16
18
|
import { mergeRouteParamsIntoQuery, parseQueryString } from "../utils/query.js";
|
|
@@ -91,6 +93,10 @@ function stripPagesNotFoundFramingHeaders(response) {
|
|
|
91
93
|
}
|
|
92
94
|
function applyPagesErrorCachePolicy(response, revalidateSeconds, expireSeconds, cacheTagPathname) {
|
|
93
95
|
const headers = new Headers(response.headers);
|
|
96
|
+
recordRouteCacheability(revalidateSeconds === void 0 ? { cacheable: false } : {
|
|
97
|
+
cacheable: revalidateSeconds !== 0,
|
|
98
|
+
cacheControl: buildMissIsrCacheControl(revalidateSeconds, expireSeconds)
|
|
99
|
+
});
|
|
94
100
|
if (hasExplicitNonCacheableResponsePolicy(headers)) return response;
|
|
95
101
|
if (revalidateSeconds === void 0) applyCdnResponseHeaders(headers, { cacheControl: NEVER_CACHE_CONTROL });
|
|
96
102
|
else {
|
|
@@ -135,8 +141,7 @@ function createPagesPageHandler(opts) {
|
|
|
135
141
|
return errorPageRoute;
|
|
136
142
|
}
|
|
137
143
|
function isrCacheKeyForRequest(i18nCacheVariant) {
|
|
138
|
-
|
|
139
|
-
return (router, pathname) => isrCacheKey(router, pathname + "::i18n=" + encodeURIComponent(i18nCacheVariant), buildId ?? void 0);
|
|
144
|
+
return (_router, pathname) => pagesIsrCacheKey(pathname, buildId ?? void 0, i18nCacheVariant);
|
|
140
145
|
}
|
|
141
146
|
async function renderPage(request, url, manifest, middlewareHeaders, options, initialResponseHeaders) {
|
|
142
147
|
let isDataReq = !!(options && options.isDataReq);
|
|
@@ -183,10 +188,10 @@ function createPagesPageHandler(opts) {
|
|
|
183
188
|
redirectUrl: void 0
|
|
184
189
|
};
|
|
185
190
|
const locale = localeInfo.locale;
|
|
186
|
-
|
|
191
|
+
let routeUrl = localeInfo.url;
|
|
187
192
|
const currentDefaultLocale = i18nConfig ? localeInfo.domainLocale ? localeInfo.domainLocale.defaultLocale : i18nConfig.defaultLocale : void 0;
|
|
188
193
|
const domainLocales = i18nConfig ? i18nConfig.domains : void 0;
|
|
189
|
-
const pageIsrCacheKey = isrCacheKeyForRequest(i18nConfig ? localeInfo.domainLocale ?
|
|
194
|
+
const pageIsrCacheKey = isrCacheKeyForRequest(i18nConfig ? localeInfo.domainLocale ? JSON.stringify([String(localeInfo.domainLocale.domain).toLowerCase(), locale]) : "locale:" + String(locale) : null);
|
|
190
195
|
if (localeInfo.redirectUrl) return new Response(null, {
|
|
191
196
|
status: 307,
|
|
192
197
|
headers: { Location: localeInfo.redirectUrl }
|
|
@@ -212,6 +217,22 @@ function createPagesPageHandler(opts) {
|
|
|
212
217
|
renderAsPath = routeUrl;
|
|
213
218
|
} else return buildDefaultPagesNotFoundResponse();
|
|
214
219
|
}
|
|
220
|
+
const routePathname = routeUrl.split("?")[0];
|
|
221
|
+
const cachePathname = normalizePathnameForRouteMatch(routePathname);
|
|
222
|
+
let cacheIdentityDiverges = false;
|
|
223
|
+
if (!isRouteMissErrorRender && options?.__forcedRoute === void 0 && cachePathname !== routePathname) {
|
|
224
|
+
const cachePathRoute = matchRoute(cachePathname, pageRoutes)?.route;
|
|
225
|
+
if (cachePathRoute !== match.route) {
|
|
226
|
+
const cachePathModule = cachePathRoute?.module;
|
|
227
|
+
if (match.route.isDynamic && typeof match.route.module.getStaticProps === "function" && cachePathRoute && !cachePathRoute.isDynamic && typeof cachePathModule?.getStaticProps === "function" && typeof cachePathModule.getServerSideProps !== "function" && getPagesPreviewState(request.headers.get("cookie"), { isOnDemandRevalidate: isOnDemandRevalidateRequest(request.headers.get("x-prerender-revalidate")) }).data === false) {
|
|
228
|
+
match = {
|
|
229
|
+
route: cachePathRoute,
|
|
230
|
+
params: {}
|
|
231
|
+
};
|
|
232
|
+
routeUrl = cachePathname + routeUrl.slice(routePathname.length);
|
|
233
|
+
} else cacheIdentityDiverges = true;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
215
236
|
const { route, params } = match;
|
|
216
237
|
const pageModule = traceFindPageComponents(route.pattern, () => route.module);
|
|
217
238
|
const isStaticPropsRoute = typeof pageModule.getStaticProps === "function";
|
|
@@ -228,11 +249,12 @@ function createPagesPageHandler(opts) {
|
|
|
228
249
|
cacheable: true,
|
|
229
250
|
cacheControl: STATIC_CACHE_CONTROL
|
|
230
251
|
});
|
|
252
|
+
else recordRouteCacheability({ cacheable: false });
|
|
231
253
|
}
|
|
232
|
-
const routeIsrGet = isCacheabilityProbe ? async () => null : isrGet;
|
|
233
|
-
const routeIsrSet = isCacheabilityProbe ? async () => {} : isrSet;
|
|
254
|
+
const routeIsrGet = isCacheabilityProbe || cacheIdentityDiverges ? async () => null : isrGet;
|
|
255
|
+
const routeIsrSet = isCacheabilityProbe || cacheIdentityDiverges ? async () => {} : isrSet;
|
|
234
256
|
const isStaticPropsRender = isStaticPropsRoute && typeof pageModule.getServerSideProps !== "function";
|
|
235
|
-
if (!options?.__skipOnDemandCoalesce && !options?.__forcedRoute && isStaticPropsRoute && isOnDemandRevalidateRequest(request.headers.get("x-prerender-revalidate"))) {
|
|
257
|
+
if (!options?.__skipOnDemandCoalesce && !options?.__forcedRoute && !cacheIdentityDiverges && isStaticPropsRoute && isOnDemandRevalidateRequest(request.headers.get("x-prerender-revalidate"))) {
|
|
236
258
|
const cacheKey = pageIsrCacheKey("pages", routeUrl.split("?")[0]);
|
|
237
259
|
const snapshot = await coalesceOnDemandRevalidation(cacheKey, async () => {
|
|
238
260
|
const response = await renderPage(request, url, manifest, middlewareHeaders, {
|
|
@@ -262,7 +284,7 @@ function createPagesPageHandler(opts) {
|
|
|
262
284
|
const routePattern = patternToNextFormat(route.pattern);
|
|
263
285
|
setFrameworkRequestRoute(routePattern);
|
|
264
286
|
const renderStatusCode = renderStatusCodeOverride ?? (routePattern === "/404" ? 404 : void 0);
|
|
265
|
-
const isrCachePathname = isStaticPropsRender && (routePattern === "/404" || routePattern === "/500" || routePattern === "/_error") ? routePattern : renderRouteUrl.split("?")[0];
|
|
287
|
+
const isrCachePathname = (isStaticPropsRender || pagesReadiness.autoExport) && (routePattern === "/404" || routePattern === "/500" || routePattern === "/_error") ? routePattern === "/_error" && renderStatusCode === 404 ? "/404" : routePattern : renderRouteUrl.split("?")[0];
|
|
266
288
|
const isNotFoundErrorRender = routePattern === "/404" || routePattern === "/_error" && renderStatusCode === 404;
|
|
267
289
|
const isStatusErrorRender = isNotFoundErrorRender || routePattern === "/500" || routePattern === "/_error" && renderStatusCode === 500;
|
|
268
290
|
const errorPageRevalidateSeconds = isNotFoundErrorRender ? options?.__notFoundRevalidateSeconds : void 0;
|
|
@@ -327,6 +349,11 @@ function createPagesPageHandler(opts) {
|
|
|
327
349
|
}
|
|
328
350
|
};
|
|
329
351
|
const scriptNonce = getScriptNonceFromHeaderSources(request.headers, middlewareHeaders);
|
|
352
|
+
const browserCacheControl = isStaticPropsRoute && !scriptNonce ? (initialResponseHeaders ?? middlewareHeaders)?.get("Cache-Control") : null;
|
|
353
|
+
const withBrowserPolicy = (response) => {
|
|
354
|
+
if (browserCacheControl) response.headers.set("Cache-Control", browserCacheControl);
|
|
355
|
+
return response;
|
|
356
|
+
};
|
|
330
357
|
const shouldApplyErrorResponsePolicy = previewData === false && !scriptNonce && isStatusErrorRender && (isStaticPropsRoute || isRouteMissErrorRender || options?.__forcedRoute !== void 0);
|
|
331
358
|
let fontLinkHeader = "";
|
|
332
359
|
let allFontPreloads = [];
|
|
@@ -366,8 +393,10 @@ function createPagesPageHandler(opts) {
|
|
|
366
393
|
},
|
|
367
394
|
fontLinkHeader,
|
|
368
395
|
i18n: buildI18nRenderContext(i18nConfig, locale, currentDefaultLocale, domainLocales),
|
|
396
|
+
staticPathsDefaultLocale: i18nConfig?.defaultLocale,
|
|
369
397
|
isrCacheKey: pageIsrCacheKey,
|
|
370
398
|
isrGet: routeIsrGet,
|
|
399
|
+
hasPrerenderedPages: getCdnCacheAdapter().hasPrerenderedPages,
|
|
371
400
|
isrSet: routeIsrSet,
|
|
372
401
|
expireSeconds: vinextConfig.expireTime,
|
|
373
402
|
isBuildTimePrerendering: typeof process !== "undefined" && process.env && process.env.VINEXT_PRERENDER === "1",
|
|
@@ -403,6 +432,7 @@ function createPagesPageHandler(opts) {
|
|
|
403
432
|
sanitizeDestination,
|
|
404
433
|
scriptNonce,
|
|
405
434
|
statusCode: renderStatusCode,
|
|
435
|
+
notFoundSourceHeaders: options?.__notFoundSourceHeaders,
|
|
406
436
|
triggerBackgroundRegeneration,
|
|
407
437
|
vinext: serializedPagesNextData.__vinext,
|
|
408
438
|
nextData: serializedPagesNextData,
|
|
@@ -427,12 +457,12 @@ function createPagesPageHandler(opts) {
|
|
|
427
457
|
notFoundResponse = stripPagesNotFoundFramingHeaders(notFoundResponse);
|
|
428
458
|
if (isOnDemandRevalidate) notFoundResponse = withPagesCacheState(notFoundResponse, "REVALIDATED", isrCachePathname);
|
|
429
459
|
else if (pageDataResult.cacheState) notFoundResponse = withPagesCacheState(notFoundResponse, pageDataResult.cacheState);
|
|
430
|
-
return finalizePagesPreviewResponse(notFoundResponse, preview);
|
|
460
|
+
return finalizePagesPreviewResponse(withBrowserPolicy(notFoundResponse), preview);
|
|
431
461
|
}
|
|
432
462
|
if (pageDataResult.kind === "response") {
|
|
433
463
|
let response = isOnDemandRevalidate && pageDataResult.onDemandRevalidateSuccess !== false ? withPagesCacheState(pageDataResult.response, "REVALIDATED", isrCachePathname) : pageDataResult.response;
|
|
434
464
|
if (shouldApplyErrorResponsePolicy) response = applyPagesErrorCachePolicy(response, errorPageRevalidateSeconds, errorPageExpireSeconds, errorResponseCachePathname);
|
|
435
|
-
return finalizePagesPreviewResponse(response, preview);
|
|
465
|
+
return finalizePagesPreviewResponse(withBrowserPolicy(response), preview);
|
|
436
466
|
}
|
|
437
467
|
let pageProps = pageDataResult.pageProps;
|
|
438
468
|
let renderProps = pageDataResult.props;
|
|
@@ -453,6 +483,10 @@ function createPagesPageHandler(opts) {
|
|
|
453
483
|
const gsspRes = pageDataResult.gsspRes;
|
|
454
484
|
const documentReqRes = serializedPagesNextData.autoExport === true && !options?.__notFoundSourceHeaders ? null : pageDataResult.documentReqRes ?? createPageReqRes();
|
|
455
485
|
const isrRevalidateSeconds = pageDataResult.isrRevalidateSeconds;
|
|
486
|
+
if (isStaticPropsRoute && preview.data === false && !preview.shouldClear && isrRevalidateSeconds !== null) recordRouteCacheability({
|
|
487
|
+
cacheable: isrRevalidateSeconds !== 0,
|
|
488
|
+
cacheControl: buildMissIsrCacheControl(isrRevalidateSeconds, vinextConfig.expireTime)
|
|
489
|
+
});
|
|
456
490
|
const isrExpireSeconds = pageDataResult.isrExpireSeconds;
|
|
457
491
|
const isFallbackRender = pageDataResult.isFallback === true;
|
|
458
492
|
if (isFallbackRender) applySSRContext({
|
|
@@ -472,6 +506,7 @@ function createPagesPageHandler(opts) {
|
|
|
472
506
|
else headers.set(k, Array.isArray(v) ? v.join(", ") : String(v));
|
|
473
507
|
}
|
|
474
508
|
}
|
|
509
|
+
if (hasCdnResponsePolicy(headers)) markRouteCacheabilityExplicitResponsePolicy();
|
|
475
510
|
if (gsspRes) {
|
|
476
511
|
if (!headers.has("Cache-Control")) headers.set("Cache-Control", NEVER_CACHE_CONTROL);
|
|
477
512
|
} else if (isStaticPropsRoute) {
|
|
@@ -487,7 +522,7 @@ function createPagesPageHandler(opts) {
|
|
|
487
522
|
const deploymentId = process.env.__VINEXT_DEPLOYMENT_ID || process.env.NEXT_DEPLOYMENT_ID;
|
|
488
523
|
if (deploymentId) headers.set(NEXTJS_DEPLOYMENT_ID_HEADER, deploymentId);
|
|
489
524
|
}
|
|
490
|
-
return finalizePagesPreviewResponse(buildNextDataPropsJsonResponse(renderProps, safeJsonStringify, { headers }), preview);
|
|
525
|
+
return finalizePagesPreviewResponse(withBrowserPolicy(buildNextDataPropsJsonResponse(renderProps, safeJsonStringify, { headers })), preview);
|
|
491
526
|
}
|
|
492
527
|
const pageModuleIds = [];
|
|
493
528
|
if (appAssetPath) pageModuleIds.push(appAssetPath);
|
|
@@ -561,7 +596,7 @@ function createPagesPageHandler(opts) {
|
|
|
561
596
|
requestCacheControl: request.headers.get("cache-control") ?? void 0
|
|
562
597
|
});
|
|
563
598
|
if (shouldApplyErrorResponsePolicy) pageResponse = applyPagesErrorCachePolicy(pageResponse, errorPageRevalidateSeconds, errorPageExpireSeconds, errorResponseCachePathname);
|
|
564
|
-
return finalizePagesPreviewResponse(pageResponse, preview);
|
|
599
|
+
return finalizePagesPreviewResponse(withBrowserPolicy(pageResponse), preview);
|
|
565
600
|
} catch (e) {
|
|
566
601
|
console.error("[vinext] SSR error:", e);
|
|
567
602
|
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;
|