vinext 1.0.0-beta.1 → 1.0.0-beta.3
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 +10 -10
- package/dist/build/client-build-config.js +8 -1
- package/dist/build/report.d.ts +8 -1
- package/dist/build/report.js +12 -2
- package/dist/check.js +19 -2
- package/dist/cli.js +3 -2
- package/dist/config/config-matchers.d.ts +13 -37
- package/dist/config/config-matchers.js +35 -122
- package/dist/config/next-config.d.ts +15 -5
- package/dist/config/next-config.js +7 -1
- package/dist/config/request-context.d.ts +14 -0
- package/dist/config/request-context.js +26 -0
- package/dist/entries/app-browser-entry.d.ts +4 -10
- package/dist/entries/app-browser-entry.js +20 -4
- package/dist/entries/app-rsc-entry.js +30 -9
- package/dist/entries/app-rsc-manifest.js +36 -0
- package/dist/entries/pages-client-entry.js +0 -1
- package/dist/entries/pages-server-entry.js +13 -5
- package/dist/index.js +194 -101
- package/dist/init-cloudflare.d.ts +3 -1
- package/dist/init-cloudflare.js +59 -5
- package/dist/init.d.ts +6 -4
- package/dist/init.js +20 -22
- package/dist/plugins/extensionless-dynamic-import.js +23 -18
- package/dist/plugins/ignore-dynamic-requests.js +3 -1
- package/dist/plugins/import-meta-url.js +17 -6
- package/dist/plugins/og-assets.js +1 -1
- package/dist/plugins/require-context.js +20 -15
- package/dist/plugins/transform-cache.d.ts +19 -0
- package/dist/plugins/transform-cache.js +36 -0
- package/dist/routing/app-route-graph.d.ts +27 -11
- package/dist/routing/app-route-graph.js +158 -22
- package/dist/routing/app-router.js +12 -6
- package/dist/routing/file-matcher.d.ts +11 -22
- package/dist/routing/file-matcher.js +21 -33
- package/dist/routing/pages-router.js +23 -29
- package/dist/routing/route-matching.d.ts +14 -1
- package/dist/routing/route-matching.js +13 -1
- package/dist/routing/route-pattern.d.ts +2 -1
- package/dist/routing/route-pattern.js +7 -4
- package/dist/routing/route-trie.d.ts +5 -1
- package/dist/routing/route-trie.js +5 -2
- package/dist/server/api-handler.d.ts +2 -0
- package/dist/server/api-handler.js +3 -3
- package/dist/server/app-browser-entry.js +110 -37
- package/dist/server/app-browser-history-controller.d.ts +1 -1
- package/dist/server/app-browser-history-controller.js +3 -3
- package/dist/server/app-browser-navigation-controller.d.ts +23 -21
- package/dist/server/app-browser-navigation-controller.js +2 -2
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-visible-commit.js +1 -1
- package/dist/server/app-fallback-renderer.d.ts +3 -0
- package/dist/server/app-fallback-renderer.js +4 -2
- package/dist/server/app-middleware.js +2 -1
- package/dist/server/app-page-boundary-render.d.ts +12 -1
- package/dist/server/app-page-boundary-render.js +84 -2
- package/dist/server/app-page-cache-finalizer.d.ts +1 -1
- package/dist/server/app-page-cache-finalizer.js +1 -1
- package/dist/server/app-page-cache.d.ts +2 -2
- package/dist/server/app-page-cache.js +16 -2
- package/dist/server/app-page-dispatch.d.ts +19 -2
- package/dist/server/app-page-dispatch.js +45 -23
- package/dist/server/app-page-element-builder.d.ts +9 -2
- package/dist/server/app-page-element-builder.js +144 -33
- package/dist/server/app-page-head.d.ts +56 -4
- package/dist/server/app-page-head.js +216 -85
- package/dist/server/app-page-http-access-fallback-metadata.d.ts +29 -0
- package/dist/server/app-page-http-access-fallback-metadata.js +114 -0
- package/dist/server/app-page-probe.d.ts +4 -0
- package/dist/server/app-page-probe.js +6 -2
- package/dist/server/app-page-render.d.ts +2 -2
- package/dist/server/app-page-render.js +1 -1
- package/dist/server/app-page-request.d.ts +15 -0
- package/dist/server/app-page-request.js +134 -14
- package/dist/server/app-page-response.js +1 -1
- package/dist/server/app-page-route-wiring.d.ts +16 -0
- package/dist/server/app-page-route-wiring.js +254 -52
- package/dist/server/app-pages-bridge.d.ts +1 -1
- package/dist/server/app-pages-bridge.js +2 -1
- package/dist/server/app-post-middleware-context.d.ts +1 -1
- package/dist/server/app-post-middleware-context.js +1 -1
- package/dist/server/app-route-handler-cache.js +4 -0
- package/dist/server/app-route-handler-dispatch.js +40 -20
- package/dist/server/app-route-handler-execution.d.ts +6 -1
- package/dist/server/app-route-handler-execution.js +42 -16
- package/dist/server/app-route-handler-policy.d.ts +2 -0
- package/dist/server/app-route-handler-policy.js +3 -3
- package/dist/server/app-route-handler-response.js +1 -1
- package/dist/server/app-route-module-loader.d.ts +9 -1
- package/dist/server/app-route-module-loader.js +4 -0
- package/dist/server/app-router-entry.js +6 -3
- package/dist/server/app-rsc-cache-busting.d.ts +1 -1
- package/dist/server/app-rsc-errors.d.ts +1 -1
- package/dist/server/app-rsc-errors.js +22 -2
- package/dist/server/app-rsc-handler.d.ts +10 -5
- package/dist/server/app-rsc-handler.js +73 -33
- package/dist/server/app-rsc-request-normalization.d.ts +3 -2
- package/dist/server/app-rsc-request-normalization.js +8 -2
- package/dist/server/app-rsc-response-finalizer.d.ts +2 -2
- package/dist/server/app-rsc-response-finalizer.js +5 -11
- package/dist/server/app-rsc-route-matching.d.ts +29 -0
- package/dist/server/app-rsc-route-matching.js +93 -11
- package/dist/server/app-segment-config.js +13 -3
- package/dist/server/app-server-action-execution.d.ts +3 -1
- package/dist/server/app-server-action-execution.js +9 -7
- package/dist/server/app-ssr-entry.js +6 -6
- package/dist/server/app-ssr-stream.d.ts +1 -7
- package/dist/server/app-ssr-stream.js +2 -10
- package/dist/server/cache-control.d.ts +2 -2
- package/dist/server/cache-control.js +2 -1
- package/dist/server/config-headers.d.ts +24 -0
- package/dist/server/config-headers.js +52 -0
- package/dist/server/dev-initial-server-error.d.ts +1 -1
- package/dist/server/dev-server.d.ts +3 -1
- package/dist/server/dev-server.js +170 -321
- package/dist/server/headers.d.ts +2 -2
- package/dist/server/headers.js +4 -3
- package/dist/server/isr-cache.d.ts +11 -34
- package/dist/server/isr-cache.js +33 -43
- package/dist/server/isr-decision.d.ts +2 -2
- package/dist/server/middleware-matcher-pattern.d.ts +22 -0
- package/dist/server/middleware-matcher-pattern.js +219 -0
- package/dist/server/middleware-matcher.d.ts +2 -7
- package/dist/server/middleware-matcher.js +13 -60
- package/dist/server/middleware-path-to-regexp.d.ts +14 -0
- package/dist/server/middleware-path-to-regexp.js +228 -0
- package/dist/server/middleware-runtime.js +4 -3
- package/dist/server/middleware.d.ts +1 -1
- package/dist/server/middleware.js +2 -1
- package/dist/server/pages-api-route.d.ts +2 -0
- package/dist/server/pages-api-route.js +4 -1
- package/dist/server/pages-data-route.d.ts +11 -1
- package/dist/server/pages-data-route.js +16 -1
- package/dist/server/pages-dev-hydration.js +0 -1
- package/dist/server/pages-get-initial-props.d.ts +16 -3
- package/dist/server/pages-get-initial-props.js +17 -10
- package/dist/server/pages-i18n.js +64 -16
- package/dist/server/pages-node-compat.d.ts +2 -0
- package/dist/server/pages-node-compat.js +7 -3
- package/dist/server/pages-page-data.d.ts +64 -10
- package/dist/server/pages-page-data.js +349 -80
- package/dist/server/pages-page-handler.d.ts +9 -3
- package/dist/server/pages-page-handler.js +131 -36
- package/dist/server/pages-page-response.d.ts +5 -3
- package/dist/server/pages-page-response.js +24 -27
- package/dist/server/pages-readiness.d.ts +3 -3
- package/dist/server/pages-request-pipeline.d.ts +8 -0
- package/dist/server/pages-request-pipeline.js +30 -12
- package/dist/server/pages-revalidate.d.ts +1 -1
- package/dist/server/pages-revalidate.js +54 -8
- package/dist/server/pages-router-entry.d.ts +1 -0
- package/dist/server/pages-router-entry.js +16 -4
- package/dist/server/prerender-route-params.js +2 -2
- package/dist/server/prod-server.d.ts +3 -5
- package/dist/server/prod-server.js +72 -35
- package/dist/server/request-pipeline.d.ts +15 -29
- package/dist/server/request-pipeline.js +24 -59
- package/dist/server/revalidation-host.d.ts +11 -0
- package/dist/server/revalidation-host.js +19 -0
- package/dist/server/rsc-stream-hints.js +122 -18
- package/dist/server/worker-revalidation-context.d.ts +13 -0
- package/dist/server/worker-revalidation-context.js +29 -0
- package/dist/shims/app.d.ts +1 -1
- package/dist/shims/cache-handler.d.ts +1 -1
- package/dist/shims/cache-handler.js +10 -7
- package/dist/shims/cache-request-state.d.ts +27 -1
- package/dist/shims/cache-request-state.js +60 -1
- package/dist/shims/cache-runtime.d.ts +18 -1
- package/dist/shims/cache-runtime.js +26 -8
- package/dist/shims/cache.d.ts +5 -5
- package/dist/shims/cache.js +27 -11
- package/dist/shims/document.d.ts +42 -83
- package/dist/shims/document.js +62 -53
- package/dist/shims/dynamic.d.ts +5 -25
- package/dist/shims/dynamic.js +29 -8
- package/dist/shims/error.d.ts +1 -1
- package/dist/shims/error.js +2 -2
- package/dist/shims/fetch-cache.js +13 -4
- package/dist/shims/font-google-base.d.ts +11 -4
- package/dist/shims/font-google-base.js +17 -8
- package/dist/shims/font-local.d.ts +10 -3
- package/dist/shims/font-local.js +41 -10
- package/dist/shims/head.d.ts +13 -2
- package/dist/shims/head.js +3 -3
- package/dist/shims/headers.d.ts +37 -43
- package/dist/shims/headers.js +183 -74
- package/dist/shims/image.d.ts +27 -37
- package/dist/shims/image.js +21 -14
- package/dist/shims/internal/cookie-serialize.d.ts +12 -9
- package/dist/shims/internal/cookie-serialize.js +10 -7
- package/dist/shims/internal/hybrid-client-route-owner.js +3 -1
- package/dist/shims/internal/interpolate-as.d.ts +15 -1
- package/dist/shims/internal/interpolate-as.js +27 -2
- package/dist/shims/internal/utils.d.ts +3 -3
- package/dist/shims/legacy-image.d.ts +3 -37
- package/dist/shims/legacy-image.js +6 -16
- package/dist/shims/link.d.ts +15 -22
- package/dist/shims/link.js +34 -13
- package/dist/shims/metadata.d.ts +7 -17
- package/dist/shims/metadata.js +74 -24
- package/dist/shims/navigation-context-state.d.ts +1 -1
- package/dist/shims/navigation.d.ts +7 -3
- package/dist/shims/navigation.js +25 -14
- package/dist/shims/navigation.react-server.js +1 -1
- package/dist/shims/next-shims-augmentations.d.ts +1 -0
- package/dist/shims/next-shims-public.d.ts +1 -0
- package/dist/shims/public-shim-map.json.js +103 -0
- package/dist/shims/readonly-url-search-params.d.ts +3 -3
- package/dist/shims/readonly-url-search-params.js +3 -3
- package/dist/shims/request-context.d.ts +4 -1
- package/dist/shims/request-state-types.d.ts +1 -1
- package/dist/shims/router.d.ts +55 -21
- package/dist/shims/router.js +180 -44
- package/dist/shims/script.d.ts +6 -10
- package/dist/shims/script.js +7 -4
- package/dist/shims/server.d.ts +50 -26
- package/dist/shims/server.js +193 -55
- package/dist/shims/unified-request-context.d.ts +22 -3
- package/dist/shims/unified-request-context.js +84 -1
- package/dist/shims/url-safety.d.ts +1 -1
- package/dist/shims/url-safety.js +2 -2
- package/dist/typegen.d.ts +8 -2
- package/dist/typegen.js +76 -15
- package/dist/utils/cache-control-metadata.d.ts +2 -1
- package/dist/utils/cache-control-metadata.js +5 -1
- package/dist/utils/domain-locale.d.ts +2 -2
- package/dist/utils/external-url.d.ts +5 -0
- package/dist/utils/external-url.js +7 -0
- package/dist/utils/html-limited-bots.js +1 -1
- package/dist/utils/protocol-headers.d.ts +7 -1
- package/dist/utils/protocol-headers.js +7 -1
- package/dist/utils/regex-safety.d.ts +8 -0
- package/dist/utils/regex-safety.js +737 -0
- package/package.json +13 -2
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
import { createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
1
|
+
import { closeAfterResponse, closeAfterResponseWithBody, createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
2
2
|
import { patternToNextFormat } from "../routing/route-validation.js";
|
|
3
3
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
4
|
-
import {
|
|
4
|
+
import { PRERENDER_REVALIDATE_HEADER } from "../utils/protocol-headers.js";
|
|
5
|
+
import { NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_CACHE_HEADER } from "./headers.js";
|
|
5
6
|
import { reportRequestError } from "./instrumentation.js";
|
|
6
7
|
import { BROWSER_REVALIDATE_CACHE_CONTROL, NEVER_CACHE_CONTROL, applyCdnResponseHeaders, shouldUseNextDeployCacheControl } from "./cache-control.js";
|
|
7
8
|
import { buildMissIsrCacheControl } from "./isr-decision.js";
|
|
8
|
-
import {
|
|
9
|
+
import { coalesceOnDemandRevalidation, isOnDemandRevalidateRequest, isrCacheKey, isrGet, isrSet, triggerBackgroundRegeneration } from "./isr-cache.js";
|
|
10
|
+
import { encodeCacheTag } from "../utils/encode-cache-tag.js";
|
|
9
11
|
import { ensureFetchPatch } from "../shims/fetch-cache.js";
|
|
10
|
-
import { appendAssetDeploymentIdQuery } from "../utils/deployment-id.js";
|
|
11
12
|
import { mergeRouteParamsIntoQuery, parseQueryString } from "../utils/query.js";
|
|
12
13
|
import { getScriptNonceFromHeaderSources } from "./csp.js";
|
|
13
14
|
import { extractLocaleFromUrl, resolvePagesI18nRequest } from "./pages-i18n.js";
|
|
14
15
|
import { buildDefaultPagesNotFoundResponse } from "./pages-default-404.js";
|
|
15
16
|
import { buildPagesReadinessNextData } from "./pages-readiness.js";
|
|
16
17
|
import { resolvePagesPageMethodResponse } from "./pages-page-method.js";
|
|
18
|
+
import { setCacheStateHeaders } from "./cache-headers.js";
|
|
17
19
|
import { renderPagesPageResponse } from "./pages-page-response.js";
|
|
18
20
|
import { hasPagesGetInitialProps } from "./pages-get-initial-props.js";
|
|
19
21
|
import { buildNextDataNotFoundResponse, buildNextDataPropsJsonResponse, normalizePagesDataRequest, parseNextDataPathname } from "./pages-data-route.js";
|
|
@@ -25,7 +27,12 @@ import { createPagesReqRes } from "./pages-node-compat.js";
|
|
|
25
27
|
function finalizePagesPreviewResponse(response, preview) {
|
|
26
28
|
if (preview.data === false && !preview.shouldClear) return response;
|
|
27
29
|
const headers = new Headers(response.headers);
|
|
28
|
-
if (preview.data !== false)
|
|
30
|
+
if (preview.data !== false) {
|
|
31
|
+
headers.set("Cache-Control", PAGES_PREVIEW_CACHE_CONTROL);
|
|
32
|
+
headers.delete("CDN-Cache-Control");
|
|
33
|
+
headers.delete("Cloudflare-CDN-Cache-Control");
|
|
34
|
+
headers.delete("Cache-Tag");
|
|
35
|
+
}
|
|
29
36
|
if (preview.shouldClear) appendPagesPreviewClearCookies(headers);
|
|
30
37
|
return new Response(response.body, {
|
|
31
38
|
headers,
|
|
@@ -33,6 +40,41 @@ function finalizePagesPreviewResponse(response, preview) {
|
|
|
33
40
|
statusText: response.statusText
|
|
34
41
|
});
|
|
35
42
|
}
|
|
43
|
+
function withPagesCacheState(response, state) {
|
|
44
|
+
const headers = new Headers(response.headers);
|
|
45
|
+
if (state === "REVALIDATED") {
|
|
46
|
+
headers.set(NEXTJS_CACHE_HEADER, state);
|
|
47
|
+
headers.delete(VINEXT_CACHE_HEADER);
|
|
48
|
+
} else setCacheStateHeaders(headers, state);
|
|
49
|
+
return new Response(response.body, {
|
|
50
|
+
headers,
|
|
51
|
+
status: response.status,
|
|
52
|
+
statusText: response.statusText
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function applyPagesErrorCachePolicy(response, revalidateSeconds, expireSeconds, cacheTagPathname) {
|
|
56
|
+
const headers = new Headers(response.headers);
|
|
57
|
+
const browserPolicy = headers.get("Cache-Control");
|
|
58
|
+
const sharedPolicies = [headers.get("CDN-Cache-Control"), headers.get("Cloudflare-CDN-Cache-Control")];
|
|
59
|
+
const hasCacheableSharedPolicy = sharedPolicies.some((value) => value && /(?:^|,)\s*s-maxage\s*=/i.test(value));
|
|
60
|
+
if (sharedPolicies.some((value) => value && /(?:private|no-store|no-cache)/i.test(value)) || !hasCacheableSharedPolicy && browserPolicy && /(?:private|no-store|no-cache)/i.test(browserPolicy)) return response;
|
|
61
|
+
headers.delete("CDN-Cache-Control");
|
|
62
|
+
headers.delete("Cloudflare-CDN-Cache-Control");
|
|
63
|
+
headers.delete("Cache-Tag");
|
|
64
|
+
if (revalidateSeconds === void 0) applyCdnResponseHeaders(headers, { cacheControl: NEVER_CACHE_CONTROL });
|
|
65
|
+
else {
|
|
66
|
+
const stem = cacheTagPathname.endsWith("/") ? cacheTagPathname.slice(0, -1) : cacheTagPathname;
|
|
67
|
+
applyCdnResponseHeaders(headers, {
|
|
68
|
+
cacheControl: buildMissIsrCacheControl(revalidateSeconds, expireSeconds),
|
|
69
|
+
tags: [encodeCacheTag(`_N_T_${stem || "/"}`)]
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return new Response(response.body, {
|
|
73
|
+
headers,
|
|
74
|
+
status: response.status,
|
|
75
|
+
statusText: response.statusText
|
|
76
|
+
});
|
|
77
|
+
}
|
|
36
78
|
function shouldEmitPagesClientTraceMetadata(pageModule, appComponent) {
|
|
37
79
|
if (typeof pageModule.getServerSideProps === "function") return true;
|
|
38
80
|
if (typeof pageModule.getStaticProps === "function") return false;
|
|
@@ -53,7 +95,7 @@ function buildI18nRenderContext(i18nConfig, locale, currentDefaultLocale, domain
|
|
|
53
95
|
* accepts the same options shape the generated entry always passed inline.
|
|
54
96
|
*/
|
|
55
97
|
function createPagesPageHandler(opts) {
|
|
56
|
-
const { pageRoutes, errorPageRoute, matchRoute, i18nConfig, vinextConfig, buildId, hasMiddleware, appAssetPath, hasRewrites, setSSRContext, getPagesNavigationIsReadyFromSerializedState, setI18nContext, wrapWithRouterContext, resetSSRHead, getSSRHeadHTML, setDocumentInitialHead, flushPreloads, getFontLinks, getFontStyles, getFontPreloads, renderToReadableStream, renderIsrPassToStringAsync, safeJsonStringify, sanitizeDestination, createPageElement, enhancePageElement, AppComponent, DocumentComponent } = opts;
|
|
98
|
+
const { pageRoutes, errorPageRoute, matchRoute, i18nConfig, vinextConfig, buildId, hasMiddleware, appAssetPath, hasRewrites, setSSRContext, getPagesNavigationIsReadyFromSerializedState, setI18nContext, wrapWithRouterContext, router, resetSSRHead, getSSRHeadHTML, setDocumentInitialHead, flushPreloads, getFontLinks, getFontStyles, getFontPreloads, renderToReadableStream, renderIsrPassToStringAsync, safeJsonStringify, sanitizeDestination, createPageElement, enhancePageElement, AppComponent, DocumentComponent } = opts;
|
|
57
99
|
function renderToStringAsync(element) {
|
|
58
100
|
return renderToReadableStream(element).then((stream) => new Response(stream).text());
|
|
59
101
|
}
|
|
@@ -122,6 +164,7 @@ function createPagesPageHandler(opts) {
|
|
|
122
164
|
route: options.__forcedRoute,
|
|
123
165
|
params: {}
|
|
124
166
|
} : matchRoute(routeUrl, pageRoutes);
|
|
167
|
+
let isRouteMissErrorRender = false;
|
|
125
168
|
let renderStatusCodeOverride = statusCode;
|
|
126
169
|
let renderAsPath = asPath;
|
|
127
170
|
if (!match) {
|
|
@@ -133,21 +176,52 @@ function createPagesPageHandler(opts) {
|
|
|
133
176
|
route: notFoundRoute,
|
|
134
177
|
params: {}
|
|
135
178
|
};
|
|
179
|
+
isRouteMissErrorRender = true;
|
|
136
180
|
renderStatusCodeOverride = 404;
|
|
137
181
|
renderAsPath = routeUrl;
|
|
138
182
|
} else return buildDefaultPagesNotFoundResponse();
|
|
139
183
|
}
|
|
140
184
|
const { route, params } = match;
|
|
141
|
-
const
|
|
142
|
-
|
|
185
|
+
const pageModule = route.module;
|
|
186
|
+
const isStaticPropsRoute = typeof pageModule.getStaticProps === "function";
|
|
187
|
+
const isStaticPropsRender = isStaticPropsRoute && typeof pageModule.getServerSideProps !== "function";
|
|
188
|
+
if (!options?.__skipOnDemandCoalesce && !options?.__forcedRoute && isStaticPropsRoute && isOnDemandRevalidateRequest(request.headers.get("x-prerender-revalidate"))) {
|
|
189
|
+
const snapshot = await coalesceOnDemandRevalidation(pageIsrCacheKey("pages", routeUrl.split("?")[0]), async () => {
|
|
190
|
+
const response = await renderPage(request, url, manifest, middlewareHeaders, {
|
|
191
|
+
...options,
|
|
192
|
+
__skipOnDemandCoalesce: true
|
|
193
|
+
});
|
|
194
|
+
return {
|
|
195
|
+
body: request.method === "HEAD" || response.status === 204 || response.status === 304 ? null : new Uint8Array(await response.arrayBuffer()),
|
|
196
|
+
headers: [...response.headers.entries()],
|
|
197
|
+
status: response.status,
|
|
198
|
+
statusText: response.statusText
|
|
199
|
+
};
|
|
200
|
+
});
|
|
201
|
+
return new Response(snapshot.body?.slice() ?? null, {
|
|
202
|
+
headers: snapshot.headers,
|
|
203
|
+
status: snapshot.status,
|
|
204
|
+
statusText: snapshot.statusText
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
const renderRouteUrl = isStaticPropsRender ? routeUrl.split("?")[0] : routeUrl;
|
|
208
|
+
const routerAsPathSource = isStaticPropsRender ? renderRouteUrl : renderAsPath ?? renderRouteUrl;
|
|
209
|
+
const routerAsPath = i18nConfig ? extractLocaleFromUrl(routerAsPathSource, i18nConfig, locale).url : routerAsPathSource;
|
|
210
|
+
const uCtx = createRequestContext({ executionContext: getRequestExecutionContext() });
|
|
211
|
+
return closeAfterResponseWithBody(await runWithRequestContext(uCtx, async () => {
|
|
143
212
|
ensureFetchPatch();
|
|
144
213
|
try {
|
|
145
214
|
const routePattern = patternToNextFormat(route.pattern);
|
|
146
215
|
const renderStatusCode = renderStatusCodeOverride ?? (routePattern === "/404" ? 404 : void 0);
|
|
147
|
-
const
|
|
148
|
-
const
|
|
149
|
-
const
|
|
216
|
+
const isrCachePathname = isStaticPropsRender && (routePattern === "/404" || routePattern === "/500" || routePattern === "/_error") ? routePattern : renderRouteUrl.split("?")[0];
|
|
217
|
+
const isNotFoundErrorRender = routePattern === "/404" || routePattern === "/_error" && renderStatusCode === 404;
|
|
218
|
+
const isStatusErrorRender = isNotFoundErrorRender || routePattern === "/500" || routePattern === "/_error" && renderStatusCode === 500;
|
|
219
|
+
const errorPageRevalidateSeconds = isNotFoundErrorRender ? options?.__notFoundRevalidateSeconds : void 0;
|
|
220
|
+
const errorPageExpireSeconds = isNotFoundErrorRender ? options?.__notFoundExpireSeconds : void 0;
|
|
221
|
+
const errorResponseCachePathname = options?.__notFoundCachePathname ?? isrCachePathname;
|
|
222
|
+
const query = mergeRouteParamsIntoQuery(parseQueryString(renderRouteUrl), params);
|
|
150
223
|
const isOnDemandRevalidate = isOnDemandRevalidateRequest(request.headers.get(PRERENDER_REVALIDATE_HEADER));
|
|
224
|
+
const revalidateOnlyGenerated = isOnDemandRevalidate && request.headers.has("x-prerender-revalidate-if-generated");
|
|
151
225
|
const preview = isStaticPropsRoute || typeof pageModule.getServerSideProps === "function" ? getPagesPreviewState(request.headers.get("cookie"), { isOnDemandRevalidate }) : {
|
|
152
226
|
data: false,
|
|
153
227
|
shouldClear: false
|
|
@@ -161,7 +235,7 @@ function createPagesPageHandler(opts) {
|
|
|
161
235
|
}),
|
|
162
236
|
...previewData === false ? {} : { isPreview: true }
|
|
163
237
|
};
|
|
164
|
-
const navigationIsReady = typeof getPagesNavigationIsReadyFromSerializedState === "function" ? getPagesNavigationIsReadyFromSerializedState(routePattern,
|
|
238
|
+
const navigationIsReady = isStaticPropsRender ? false : typeof getPagesNavigationIsReadyFromSerializedState === "function" ? getPagesNavigationIsReadyFromSerializedState(routePattern, originalRequestUrl.search, pagesNextData) : true;
|
|
165
239
|
function applySSRContext(extra) {
|
|
166
240
|
if (typeof setSSRContext === "function") setSSRContext({
|
|
167
241
|
pathname: routePattern,
|
|
@@ -204,15 +278,16 @@ function createPagesPageHandler(opts) {
|
|
|
204
278
|
pageModuleUrl,
|
|
205
279
|
appModuleUrl,
|
|
206
280
|
hasMiddleware,
|
|
207
|
-
routeUrl
|
|
281
|
+
routeUrl: renderRouteUrl
|
|
208
282
|
}
|
|
209
283
|
};
|
|
210
284
|
const scriptNonce = getScriptNonceFromHeaderSources(request.headers, middlewareHeaders);
|
|
285
|
+
const shouldApplyErrorResponsePolicy = previewData === false && !scriptNonce && isStatusErrorRender && (isStaticPropsRoute || isRouteMissErrorRender || options?.__forcedRoute !== void 0);
|
|
211
286
|
let fontLinkHeader = "";
|
|
212
287
|
let allFontPreloads = [];
|
|
213
288
|
try {
|
|
214
289
|
allFontPreloads = getFontPreloads();
|
|
215
|
-
if (allFontPreloads.length > 0) fontLinkHeader = allFontPreloads.map((p) => "<" +
|
|
290
|
+
if (allFontPreloads.length > 0) fontLinkHeader = allFontPreloads.map((p) => "<" + p.href + ">; rel=preload; as=font; type=" + p.type + "; crossorigin").join(", ");
|
|
216
291
|
} catch {}
|
|
217
292
|
const pagesResolvedUrl = (new URL(routeUrl, originalRequestUrl).pathname || "/") + originalRequestUrl.search;
|
|
218
293
|
const createPageReqRes = () => {
|
|
@@ -229,6 +304,7 @@ function createPagesPageHandler(opts) {
|
|
|
229
304
|
isDataReq,
|
|
230
305
|
err: err instanceof Error ? err : void 0,
|
|
231
306
|
applyRequestContexts: applySSRContext,
|
|
307
|
+
basePath: vinextConfig.basePath,
|
|
232
308
|
buildId,
|
|
233
309
|
deploymentId: process.env.__VINEXT_DEPLOYMENT_ID || process.env.NEXT_DEPLOYMENT_ID,
|
|
234
310
|
htmlLimitedBots: vinextConfig.htmlLimitedBots,
|
|
@@ -250,9 +326,11 @@ function createPagesPageHandler(opts) {
|
|
|
250
326
|
isBuildTimePrerendering: typeof process !== "undefined" && process.env && process.env.VINEXT_PRERENDER === "1",
|
|
251
327
|
validatePropsSerialization: process.env.NODE_ENV !== "production" || process.env.VINEXT_PRERENDER === "1",
|
|
252
328
|
isOnDemandRevalidate,
|
|
329
|
+
revalidateOnlyGenerated,
|
|
253
330
|
previewData,
|
|
254
331
|
pageModule,
|
|
255
332
|
AppComponent,
|
|
333
|
+
router,
|
|
256
334
|
params,
|
|
257
335
|
query,
|
|
258
336
|
asPath: routerAsPath,
|
|
@@ -260,11 +338,17 @@ function createPagesPageHandler(opts) {
|
|
|
260
338
|
renderIsrPassToStringAsync,
|
|
261
339
|
route: { isDynamic: route.isDynamic },
|
|
262
340
|
routePattern,
|
|
263
|
-
routeUrl,
|
|
341
|
+
routeUrl: renderRouteUrl,
|
|
342
|
+
isrCachePathname,
|
|
264
343
|
runInFreshUnifiedContext(callback) {
|
|
265
|
-
|
|
344
|
+
const revalCtx = createRequestContext({ executionContext: null });
|
|
345
|
+
return runWithRequestContext(revalCtx, async () => {
|
|
266
346
|
ensureFetchPatch();
|
|
267
|
-
|
|
347
|
+
try {
|
|
348
|
+
return await callback();
|
|
349
|
+
} finally {
|
|
350
|
+
await closeAfterResponse(revalCtx);
|
|
351
|
+
}
|
|
268
352
|
});
|
|
269
353
|
},
|
|
270
354
|
safeJsonStringify,
|
|
@@ -280,15 +364,26 @@ function createPagesPageHandler(opts) {
|
|
|
280
364
|
});
|
|
281
365
|
if (pageDataResult.kind === "notFound") {
|
|
282
366
|
const notFoundRoute = findNotFoundRoute();
|
|
283
|
-
|
|
367
|
+
let notFoundResponse;
|
|
368
|
+
if (notFoundRoute && routePattern !== "/404" && routePattern !== "/_error") notFoundResponse = await renderPage(request, url, manifest, middlewareHeaders, {
|
|
284
369
|
statusCode: 404,
|
|
285
370
|
asPath: routerAsPath,
|
|
286
371
|
renderErrorPageOnMiss: false,
|
|
287
|
-
__forcedRoute: notFoundRoute
|
|
288
|
-
|
|
289
|
-
|
|
372
|
+
__forcedRoute: notFoundRoute,
|
|
373
|
+
__notFoundRevalidateSeconds: pageDataResult.revalidateSeconds,
|
|
374
|
+
__notFoundExpireSeconds: pageDataResult.expireSeconds,
|
|
375
|
+
__notFoundCachePathname: isrCachePathname
|
|
376
|
+
});
|
|
377
|
+
else notFoundResponse = buildDefaultPagesNotFoundResponse();
|
|
378
|
+
if (isOnDemandRevalidate) notFoundResponse = withPagesCacheState(notFoundResponse, "REVALIDATED");
|
|
379
|
+
else if (pageDataResult.cacheState) notFoundResponse = withPagesCacheState(notFoundResponse, pageDataResult.cacheState);
|
|
380
|
+
return finalizePagesPreviewResponse(notFoundResponse, preview);
|
|
381
|
+
}
|
|
382
|
+
if (pageDataResult.kind === "response") {
|
|
383
|
+
let response = isOnDemandRevalidate && pageDataResult.onDemandRevalidateSuccess !== false ? withPagesCacheState(pageDataResult.response, "REVALIDATED") : pageDataResult.response;
|
|
384
|
+
if (shouldApplyErrorResponsePolicy) response = applyPagesErrorCachePolicy(response, errorPageRevalidateSeconds, errorPageExpireSeconds, errorResponseCachePathname);
|
|
385
|
+
return finalizePagesPreviewResponse(response, preview);
|
|
290
386
|
}
|
|
291
|
-
if (pageDataResult.kind === "response") return finalizePagesPreviewResponse(pageDataResult.response, preview);
|
|
292
387
|
let pageProps = pageDataResult.pageProps;
|
|
293
388
|
let renderProps = pageDataResult.props;
|
|
294
389
|
if (previewData !== false) renderProps = {
|
|
@@ -308,16 +403,12 @@ function createPagesPageHandler(opts) {
|
|
|
308
403
|
const gsspRes = pageDataResult.gsspRes;
|
|
309
404
|
const documentReqRes = serializedPagesNextData.autoExport === true ? null : pageDataResult.documentReqRes ?? createPageReqRes();
|
|
310
405
|
const isrRevalidateSeconds = pageDataResult.isrRevalidateSeconds;
|
|
406
|
+
const isrExpireSeconds = pageDataResult.isrExpireSeconds;
|
|
311
407
|
const isFallbackRender = pageDataResult.isFallback === true;
|
|
312
|
-
if (isFallbackRender
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
asPath: routerAsPath,
|
|
408
|
+
if (isFallbackRender) applySSRContext({
|
|
409
|
+
query: {},
|
|
410
|
+
asPath: routePattern,
|
|
316
411
|
navigationIsReady: false,
|
|
317
|
-
locale,
|
|
318
|
-
locales: i18nConfig ? i18nConfig.locales : void 0,
|
|
319
|
-
defaultLocale: currentDefaultLocale,
|
|
320
|
-
domainLocales,
|
|
321
412
|
isFallback: true
|
|
322
413
|
});
|
|
323
414
|
if (isDataReq) {
|
|
@@ -338,7 +429,7 @@ function createPagesPageHandler(opts) {
|
|
|
338
429
|
}
|
|
339
430
|
if (!hasUserCacheControl) init.headers["Cache-Control"] = NEVER_CACHE_CONTROL;
|
|
340
431
|
} else if (isStaticPropsRoute) {
|
|
341
|
-
if (isrRevalidateSeconds) {
|
|
432
|
+
if (isrRevalidateSeconds !== null) {
|
|
342
433
|
const headers = new Headers(init.headers);
|
|
343
434
|
applyCdnResponseHeaders(headers, { cacheControl: buildMissIsrCacheControl(isrRevalidateSeconds, vinextConfig.expireTime) });
|
|
344
435
|
for (const [key, value] of headers) init.headers[key] = value;
|
|
@@ -353,7 +444,7 @@ function createPagesPageHandler(opts) {
|
|
|
353
444
|
const pageModuleIds = [];
|
|
354
445
|
if (appAssetPath) pageModuleIds.push(appAssetPath);
|
|
355
446
|
if (route.filePath) pageModuleIds.push(route.filePath);
|
|
356
|
-
|
|
447
|
+
let pageResponse = await renderPagesPageResponse({
|
|
357
448
|
assetTags: collectAssetTags({
|
|
358
449
|
manifest,
|
|
359
450
|
moduleIds: pageModuleIds,
|
|
@@ -387,8 +478,10 @@ function createPagesPageHandler(opts) {
|
|
|
387
478
|
documentReqRes,
|
|
388
479
|
gsspRes,
|
|
389
480
|
isrCacheKey: pageIsrCacheKey,
|
|
390
|
-
|
|
481
|
+
isrCachePathname,
|
|
482
|
+
expireSeconds: isrExpireSeconds,
|
|
391
483
|
isrRevalidateSeconds,
|
|
484
|
+
isOnDemandRevalidate,
|
|
392
485
|
isStaticPropsRoute,
|
|
393
486
|
isrSet,
|
|
394
487
|
i18n: buildI18nRenderContext(i18nConfig, locale, currentDefaultLocale, domainLocales),
|
|
@@ -404,7 +497,7 @@ function createPagesPageHandler(opts) {
|
|
|
404
497
|
resetSSRHead: typeof resetSSRHead === "function" ? resetSSRHead : void 0,
|
|
405
498
|
setDocumentInitialHead: typeof setDocumentInitialHead === "function" ? setDocumentInitialHead : void 0,
|
|
406
499
|
routePattern,
|
|
407
|
-
routeUrl,
|
|
500
|
+
routeUrl: renderRouteUrl,
|
|
408
501
|
safeJsonStringify,
|
|
409
502
|
scriptNonce,
|
|
410
503
|
statusCode: renderStatusCode,
|
|
@@ -412,7 +505,9 @@ function createPagesPageHandler(opts) {
|
|
|
412
505
|
userAgent: request.headers.get("user-agent") ?? void 0,
|
|
413
506
|
ifNoneMatch: request.headers.get("if-none-match") ?? void 0,
|
|
414
507
|
requestCacheControl: request.headers.get("cache-control") ?? void 0
|
|
415
|
-
})
|
|
508
|
+
});
|
|
509
|
+
if (shouldApplyErrorResponsePolicy) pageResponse = applyPagesErrorCachePolicy(pageResponse, errorPageRevalidateSeconds, errorPageExpireSeconds, errorResponseCachePathname);
|
|
510
|
+
return finalizePagesPreviewResponse(pageResponse, preview);
|
|
416
511
|
} catch (e) {
|
|
417
512
|
console.error("[vinext] SSR error:", e);
|
|
418
513
|
reportRequestError(e instanceof Error ? e : new Error(String(e)), {
|
|
@@ -446,7 +541,7 @@ function createPagesPageHandler(opts) {
|
|
|
446
541
|
}
|
|
447
542
|
return new Response("Internal Server Error", { status: 500 });
|
|
448
543
|
}
|
|
449
|
-
});
|
|
544
|
+
}), uCtx);
|
|
450
545
|
}
|
|
451
546
|
return renderPage;
|
|
452
547
|
}
|
|
@@ -88,11 +88,13 @@ type RenderPagesPageResponseOptions = {
|
|
|
88
88
|
setDocumentInitialHead?: ((head: ReactNode[]) => void) | undefined;
|
|
89
89
|
documentReqRes?: PagesDocumentReqRes | null;
|
|
90
90
|
gsspRes: PagesGsspResponse | null;
|
|
91
|
-
isrCacheKey: (router: string, pathname: string) => string;
|
|
91
|
+
isrCacheKey: (router: string, pathname: string) => string; /** Filesystem-route identity used for ISR persistence and cache tags. */
|
|
92
|
+
isrCachePathname?: string;
|
|
92
93
|
expireSeconds?: number;
|
|
93
|
-
isrRevalidateSeconds: number | null;
|
|
94
|
+
isrRevalidateSeconds: number | false | null; /** Synchronous `res.revalidate()` render; cache persistence must finish before returning. */
|
|
95
|
+
isOnDemandRevalidate?: boolean;
|
|
94
96
|
isStaticPropsRoute?: boolean;
|
|
95
|
-
isrSet: (key: string, data: CachedPagesValue, revalidateSeconds: number, tags?: string[], expireSeconds?: number) => Promise<void>;
|
|
97
|
+
isrSet: (key: string, data: CachedPagesValue, revalidateSeconds: number | false, tags?: string[], expireSeconds?: number) => Promise<void>;
|
|
96
98
|
i18n: PagesI18nRenderContext;
|
|
97
99
|
/**
|
|
98
100
|
* True when rendering a `getStaticPaths` fallback shell for a path that
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
2
|
+
import { NEXTJS_CACHE_HEADER } from "./headers.js";
|
|
2
3
|
import { reportRequestError } from "./instrumentation.js";
|
|
3
|
-
import { setCacheStateHeaders } from "./cache-headers.js";
|
|
4
4
|
import { BROWSER_REVALIDATE_CACHE_CONTROL, NEVER_CACHE_CONTROL, NO_STORE_CACHE_CONTROL, applyCdnResponseHeaders, shouldUseNextDeployCacheControl } from "./cache-control.js";
|
|
5
5
|
import { buildMissIsrCacheControl } from "./isr-decision.js";
|
|
6
6
|
import { fnv1a52 } from "../utils/hash.js";
|
|
@@ -9,29 +9,19 @@ import { appendAssetDeploymentIdQuery } from "../utils/deployment-id.js";
|
|
|
9
9
|
import { withScriptNonce } from "../shims/script-nonce-context.js";
|
|
10
10
|
import { createNonceAttribute, escapeHtmlAttr } from "./html.js";
|
|
11
11
|
import { getClientTraceMetadataHTML } from "./client-trace-metadata.js";
|
|
12
|
+
import { setCacheStateHeaders } from "./cache-headers.js";
|
|
12
13
|
import { readStreamAsText } from "../utils/text-stream.js";
|
|
13
14
|
import { loadUserDocumentInitialProps, runDocumentRenderPage } from "./pages-document-initial-props.js";
|
|
14
15
|
import { callDocumentGetInitialProps } from "./document-initial-head.js";
|
|
16
|
+
import { isBotUserAgent } from "../utils/html-limited-bots.js";
|
|
15
17
|
import React from "react";
|
|
16
18
|
//#region src/server/pages-page-response.ts
|
|
17
19
|
/**
|
|
18
|
-
* Crawlers that cannot handle streamed HTML: they read metadata only from
|
|
19
|
-
* the first network chunk, so streaming would give them an incomplete <head>.
|
|
20
|
-
* Pattern sourced from Next.js html-bots.ts (updated to match the canary).
|
|
21
|
-
*/
|
|
22
|
-
const HTML_LIMITED_BOT_UA_RE = /[\w-]+-Google|Google-[\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight/i;
|
|
23
|
-
/**
|
|
24
|
-
* Googlebot (the main search crawler) executes JavaScript via a headless
|
|
25
|
-
* browser, so it too cannot safely handle mid-stream HTML mutations.
|
|
26
|
-
* Matches "Googlebot" but NOT suffixed variants like "Googlebot-Image".
|
|
27
|
-
*/
|
|
28
|
-
const HEADLESS_BROWSER_BOT_UA_RE = /Googlebot(?!-)|Googlebot$/i;
|
|
29
|
-
/**
|
|
30
20
|
* Returns true when the User-Agent belongs to a bot or crawler that cannot
|
|
31
21
|
* reliably consume a streamed HTML response.
|
|
32
22
|
*/
|
|
33
23
|
function isPagesStreamingBot(userAgent) {
|
|
34
|
-
return
|
|
24
|
+
return isBotUserAgent(userAgent);
|
|
35
25
|
}
|
|
36
26
|
function generatePagesETag(payload) {
|
|
37
27
|
return "\"" + fnv1a52(payload).toString(36) + payload.length.toString(36) + "\"";
|
|
@@ -64,7 +54,7 @@ function buildPagesFontHeadHtml(fontLinks, fontPreloads, fontStyles, scriptNonce
|
|
|
64
54
|
let html = "";
|
|
65
55
|
const nonceAttr = createNonceAttribute(scriptNonce);
|
|
66
56
|
for (const link of fontLinks) html += `<link rel="stylesheet"${nonceAttr} href="${escapeHtmlAttr(appendAssetDeploymentIdQuery(link))}" />\n `;
|
|
67
|
-
for (const preload of fontPreloads) html += `<link rel="preload"${nonceAttr} href="${escapeHtmlAttr(
|
|
57
|
+
for (const preload of fontPreloads) html += `<link rel="preload"${nonceAttr} href="${escapeHtmlAttr(preload.href)}" as="font" type="${escapeHtmlAttr(preload.type)}" crossorigin />\n `;
|
|
68
58
|
if (fontStyles.length > 0) html += `<style data-vinext-fonts${nonceAttr}>${fontStyles.join("\n")}</style>\n `;
|
|
69
59
|
return html;
|
|
70
60
|
}
|
|
@@ -72,7 +62,7 @@ function buildPagesNextDataScript(options) {
|
|
|
72
62
|
const nextDataPayload = {
|
|
73
63
|
props: options.props ?? { pageProps: options.pageProps },
|
|
74
64
|
page: options.routePattern,
|
|
75
|
-
query: options.params,
|
|
65
|
+
query: options.isFallback === true ? {} : options.params,
|
|
76
66
|
buildId: options.buildId,
|
|
77
67
|
isFallback: options.isFallback === true
|
|
78
68
|
};
|
|
@@ -142,14 +132,18 @@ async function reportPagesIsrCacheWriteError(error, cacheKey, routePattern) {
|
|
|
142
132
|
});
|
|
143
133
|
} catch {}
|
|
144
134
|
}
|
|
145
|
-
function
|
|
146
|
-
const
|
|
135
|
+
async function writePagesIsrCache(options) {
|
|
136
|
+
const bodyHtml = await readStreamAsText(options.stream);
|
|
137
|
+
await options.setCache(options.cacheKey, {
|
|
147
138
|
kind: "PAGES",
|
|
148
139
|
html: options.shellPrefix + bodyHtml + options.shellSuffix,
|
|
149
140
|
pageData: options.pageData,
|
|
150
141
|
headers: void 0,
|
|
151
142
|
status: options.status
|
|
152
|
-
}, options.revalidateSeconds, void 0, options.expireSeconds)
|
|
143
|
+
}, options.revalidateSeconds, void 0, options.expireSeconds);
|
|
144
|
+
}
|
|
145
|
+
function schedulePagesIsrCacheWrite(options) {
|
|
146
|
+
const cacheWritePromise = writePagesIsrCache(options).catch((error) => reportPagesIsrCacheWriteError(error, options.cacheKey, options.routePattern));
|
|
153
147
|
getRequestExecutionContext()?.waitUntil(cacheWritePromise);
|
|
154
148
|
}
|
|
155
149
|
function applyGsspHeaders(headers, gsspRes, statusCode) {
|
|
@@ -235,15 +229,15 @@ async function renderPagesPageResponse(options) {
|
|
|
235
229
|
const responseHeaders = new Headers({ "Content-Type": "text/html; charset=utf-8" });
|
|
236
230
|
const finalStatus = applyGsspHeaders(responseHeaders, options.gsspRes ?? options.documentReqRes?.res ?? null, options.statusCode);
|
|
237
231
|
let responseBodyStream = bodyStream;
|
|
238
|
-
if (!options.scriptNonce && options.isrRevalidateSeconds !== null && options.isrRevalidateSeconds > 0) {
|
|
232
|
+
if (!options.scriptNonce && options.isrRevalidateSeconds !== null && (options.isrRevalidateSeconds === false || options.isrRevalidateSeconds > 0)) {
|
|
239
233
|
const cacheBodyStreamPair = bodyStream.tee();
|
|
240
234
|
responseBodyStream = cacheBodyStreamPair[0];
|
|
241
235
|
const cacheBodyStream = cacheBodyStreamPair[1];
|
|
242
|
-
const isrPathname = options.routeUrl.split("?")[0];
|
|
243
|
-
|
|
236
|
+
const isrPathname = options.isrCachePathname ?? options.routeUrl.split("?")[0];
|
|
237
|
+
const cacheWriteOptions = {
|
|
244
238
|
cacheKey: options.isrCacheKey("pages", isrPathname),
|
|
245
239
|
expireSeconds: options.expireSeconds,
|
|
246
|
-
pageData: options.pageProps,
|
|
240
|
+
pageData: options.props ?? { pageProps: options.pageProps },
|
|
247
241
|
revalidateSeconds: options.isrRevalidateSeconds,
|
|
248
242
|
routePattern: options.routePattern,
|
|
249
243
|
setCache: options.isrSet,
|
|
@@ -251,19 +245,22 @@ async function renderPagesPageResponse(options) {
|
|
|
251
245
|
shellSuffix,
|
|
252
246
|
status: finalStatus,
|
|
253
247
|
stream: cacheBodyStream
|
|
254
|
-
}
|
|
248
|
+
};
|
|
249
|
+
if (options.isOnDemandRevalidate) await writePagesIsrCache(cacheWriteOptions);
|
|
250
|
+
else schedulePagesIsrCacheWrite(cacheWriteOptions);
|
|
255
251
|
}
|
|
256
252
|
const compositeStream = await buildPagesCompositeStream(responseBodyStream, shellPrefix, shellSuffix);
|
|
257
253
|
const userSetCacheControl = responseHeaders.has("Cache-Control");
|
|
258
254
|
if (options.scriptNonce) responseHeaders.set("Cache-Control", NO_STORE_CACHE_CONTROL);
|
|
259
|
-
else if (options.isrRevalidateSeconds) {
|
|
260
|
-
const isrPathname = options.routeUrl.split("?")[0];
|
|
255
|
+
else if (options.isrRevalidateSeconds !== null) {
|
|
256
|
+
const isrPathname = options.isrCachePathname ?? options.routeUrl.split("?")[0];
|
|
261
257
|
const stem = isrPathname.endsWith("/") ? isrPathname.slice(0, -1) : isrPathname;
|
|
262
258
|
applyCdnResponseHeaders(responseHeaders, {
|
|
263
259
|
cacheControl: buildMissIsrCacheControl(options.isrRevalidateSeconds, options.expireSeconds),
|
|
264
260
|
tags: [encodeCacheTag(`_N_T_${stem || "/"}`)]
|
|
265
261
|
});
|
|
266
|
-
|
|
262
|
+
if (options.isOnDemandRevalidate) responseHeaders.set(NEXTJS_CACHE_HEADER, "REVALIDATED");
|
|
263
|
+
else setCacheStateHeaders(responseHeaders, "MISS");
|
|
267
264
|
} else if (options.isStaticPropsRoute && shouldUseNextDeployCacheControl()) responseHeaders.set("Cache-Control", BROWSER_REVALIDATE_CACHE_CONTROL);
|
|
268
265
|
else if (options.gsspRes && !userSetCacheControl) responseHeaders.set("Cache-Control", NEVER_CACHE_CONTROL);
|
|
269
266
|
if (options.fontLinkHeader) responseHeaders.set("Link", options.fontLinkHeader);
|
|
@@ -7,9 +7,9 @@ import { PagesPageModule } from "./pages-page-data.js";
|
|
|
7
7
|
*
|
|
8
8
|
* The initial `router.isReady` value for the `next/navigation` compat hooks is
|
|
9
9
|
* derived from the page/_app data-fetching exports plus the configured-rewrites
|
|
10
|
-
* flag
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* flag. The client recomputes readiness from those flags and its live URL,
|
|
11
|
+
* matching the Pages Router constructor; server-only readiness remains in the
|
|
12
|
+
* request context. See `getPagesNavigationIsReadyFromSerializedState` in
|
|
13
13
|
* `shims/router.ts`.
|
|
14
14
|
*/
|
|
15
15
|
/**
|
|
@@ -44,6 +44,14 @@ type PagesPipelineDeps = {
|
|
|
44
44
|
hasMiddleware: boolean;
|
|
45
45
|
ctx?: unknown;
|
|
46
46
|
rawSearch?: string;
|
|
47
|
+
configMatchPathname?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Validate an on-demand revalidation credential using the runtime's
|
|
50
|
+
* authoritative build secret. Production adapters must inject the verifier
|
|
51
|
+
* exported by the generated server entry so this early middleware decision
|
|
52
|
+
* uses the same baked secret as the eventual page renderer.
|
|
53
|
+
*/
|
|
54
|
+
authorizeOnDemandRevalidate?: (headerValue: string | null) => boolean;
|
|
47
55
|
matchPageRoute?: ((pathname: string, request: Request) => PageRouteMatch | null) | null;
|
|
48
56
|
runMiddleware?: ((request: Request, ctx: unknown, opts: {
|
|
49
57
|
isDataRequest: boolean;
|