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,35 +1,157 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
2
|
+
import { NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER } from "./headers.js";
|
|
3
|
+
import { isDangerousScheme } from "../shims/url-safety.js";
|
|
3
4
|
import { isUnknownRecord } from "../utils/record.js";
|
|
4
5
|
import { applyCdnResponseHeaders } from "./cache-control.js";
|
|
5
|
-
import { decideIsr } from "./isr-decision.js";
|
|
6
|
+
import { buildMissIsrCacheControl, decideIsr } from "./isr-decision.js";
|
|
6
7
|
import { buildPagesCacheValue } from "./isr-cache.js";
|
|
8
|
+
import { encodeCacheTag } from "../utils/encode-cache-tag.js";
|
|
7
9
|
import { normalizeStaticPathname } from "../routing/route-pattern.js";
|
|
10
|
+
import { buildCacheStateHeaders } from "./cache-headers.js";
|
|
11
|
+
import { isBotUserAgent } from "../utils/html-limited-bots.js";
|
|
8
12
|
import { buildPagesNextDataScript, etagMatches, generatePagesETag, isPagesStreamingBot, requestsNoCache } from "./pages-page-response.js";
|
|
9
|
-
import { hasPagesGetInitialProps, isResponseSent, loadPagesGetInitialProps } from "./pages-get-initial-props.js";
|
|
13
|
+
import { createPagesGetInitialPropsRouter, hasPagesGetInitialProps, isResponseSent, loadPagesGetInitialProps } from "./pages-get-initial-props.js";
|
|
10
14
|
import { buildNextDataPropsJsonResponse } from "./pages-data-route.js";
|
|
11
15
|
import { isSerializableProps } from "./pages-serializable-props.js";
|
|
12
|
-
import { isBotUserAgent } from "../utils/html-limited-bots.js";
|
|
13
16
|
//#region src/server/pages-page-data.ts
|
|
17
|
+
const ALLOWED_PAGES_REDIRECT_STATUS_CODES = /* @__PURE__ */ new Set([
|
|
18
|
+
301,
|
|
19
|
+
302,
|
|
20
|
+
303,
|
|
21
|
+
307,
|
|
22
|
+
308
|
|
23
|
+
]);
|
|
24
|
+
/** Headers that are part of a cached Pages representation, never request state. */
|
|
25
|
+
function isCachedPagesRepresentationHeader(name) {
|
|
26
|
+
const lowerName = name.toLowerCase();
|
|
27
|
+
return lowerName === "location" || lowerName === "content-type";
|
|
28
|
+
}
|
|
29
|
+
function assertPages404DoesNotReturnNotFound(routePattern, result) {
|
|
30
|
+
if (routePattern === "/404" && result?.notFound) throw new Error("The /404 page can not return notFound in \"getStaticProps\", please remove it to continue!");
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Next.js preserves an omitted/false Pages `revalidate` result as an indefinite
|
|
34
|
+
* cache lifetime. The one-year sentinel is only an HTTP Cache-Control detail;
|
|
35
|
+
* storing it as a revalidation deadline would incorrectly regenerate static
|
|
36
|
+
* pages after one year.
|
|
37
|
+
*
|
|
38
|
+
* Next.js source:
|
|
39
|
+
* - packages/next/src/server/render.tsx (`metadata.cacheControl`)
|
|
40
|
+
* - packages/next/src/server/route-modules/pages/pages-handler.ts
|
|
41
|
+
*/
|
|
42
|
+
function resolvePagesRevalidateSeconds(result, routeUrl = "") {
|
|
43
|
+
const revalidate = result.revalidate;
|
|
44
|
+
if (revalidate === true) return 1;
|
|
45
|
+
if (typeof revalidate === "number") {
|
|
46
|
+
if (!Number.isInteger(revalidate)) throw new Error(`A page's revalidate option must be seconds expressed as a natural number for ${routeUrl}. Mixed numbers, such as '${revalidate}', cannot be used.`);
|
|
47
|
+
if (revalidate <= 0) throw new Error(`A page's revalidate option can not be less than or equal to zero for ${routeUrl}.`);
|
|
48
|
+
return revalidate;
|
|
49
|
+
}
|
|
50
|
+
if (revalidate === false || revalidate === void 0) return false;
|
|
51
|
+
throw new Error(`A page's revalidate option must be seconds expressed as a natural number. Mixed numbers and strings cannot be used. Received '${JSON.stringify(revalidate)}' for ${routeUrl}`);
|
|
52
|
+
}
|
|
53
|
+
function resolvePagesExpireSeconds(result, configuredExpireSeconds) {
|
|
54
|
+
return result.revalidate === false || result.revalidate === void 0 ? void 0 : configuredExpireSeconds;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Merge gSP/gSSP data into the custom App's raw pageProps value.
|
|
58
|
+
*
|
|
59
|
+
* Next.js deliberately uses Object.assign rather than object spread, so
|
|
60
|
+
* enumerable keys from arrays and primitive wrapper objects are retained.
|
|
61
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/src/server/render.tsx
|
|
62
|
+
*/
|
|
63
|
+
function mergePagesDataProps(appPageProps, dataProps) {
|
|
64
|
+
return Object.assign({}, appPageProps, dataProps);
|
|
65
|
+
}
|
|
14
66
|
function buildPagesDataNotFoundResponse(deploymentId) {
|
|
15
67
|
const headers = { "Content-Type": "application/json" };
|
|
16
68
|
if (deploymentId) headers[NEXTJS_DEPLOYMENT_ID_HEADER] = deploymentId;
|
|
17
|
-
return new Response("{}", {
|
|
69
|
+
return new Response("{\"notFound\":true}", {
|
|
18
70
|
status: 404,
|
|
19
71
|
headers
|
|
20
72
|
});
|
|
21
73
|
}
|
|
22
|
-
function buildPagesNotFoundResult(options) {
|
|
74
|
+
function buildPagesNotFoundResult(options, revalidateSeconds, cacheState, expireSeconds) {
|
|
23
75
|
if (options.isDataReq) return {
|
|
24
76
|
kind: "response",
|
|
25
77
|
response: buildPagesDataNotFoundResponse(options.deploymentId)
|
|
26
78
|
};
|
|
27
|
-
return {
|
|
79
|
+
return {
|
|
80
|
+
kind: "notFound",
|
|
81
|
+
revalidateSeconds,
|
|
82
|
+
expireSeconds,
|
|
83
|
+
cacheState
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function applyPagesTerminalMissHeaders(response, revalidateSeconds, isrCachePathname, expireSeconds) {
|
|
87
|
+
const stem = isrCachePathname.endsWith("/") ? isrCachePathname.slice(0, -1) : isrCachePathname;
|
|
88
|
+
applyCdnResponseHeaders(response.headers, {
|
|
89
|
+
cacheControl: buildMissIsrCacheControl(revalidateSeconds, expireSeconds),
|
|
90
|
+
tags: [encodeCacheTag(`_N_T_${stem || "/"}`)]
|
|
91
|
+
});
|
|
92
|
+
for (const [name, value] of Object.entries(buildCacheStateHeaders("MISS"))) response.headers.set(name, value);
|
|
93
|
+
return response;
|
|
94
|
+
}
|
|
95
|
+
function applyCachedPagesRepresentationHeaders(response, cacheState, entry, options) {
|
|
96
|
+
const { cacheControl } = decideIsr({
|
|
97
|
+
cacheState,
|
|
98
|
+
kind: "pages",
|
|
99
|
+
revalidateSeconds: entry.cacheControl?.revalidate ?? 60,
|
|
100
|
+
expireSeconds: entry.cacheControl?.expire === void 0 ? void 0 : options.expireSeconds,
|
|
101
|
+
cacheControlMeta: entry.cacheControl
|
|
102
|
+
});
|
|
103
|
+
applyCdnResponseHeaders(response.headers, { cacheControl });
|
|
104
|
+
for (const [name, value] of Object.entries(buildCacheStateHeaders(cacheState))) response.headers.set(name, value);
|
|
105
|
+
return response;
|
|
106
|
+
}
|
|
107
|
+
function buildCachedPagesNotFoundResult(options, entry, cacheState) {
|
|
108
|
+
const result = buildPagesNotFoundResult(options, entry.cacheControl?.revalidate ?? 60, cacheState, entry.cacheControl?.expire);
|
|
109
|
+
if (result.kind === "response") return {
|
|
110
|
+
kind: "response",
|
|
111
|
+
response: applyCachedPagesRepresentationHeaders(result.response, cacheState, entry, options)
|
|
112
|
+
};
|
|
113
|
+
return result;
|
|
28
114
|
}
|
|
29
115
|
function resolvePagesRedirectStatus(redirect) {
|
|
30
116
|
return redirect.statusCode != null ? redirect.statusCode : redirect.permanent ? 308 : 307;
|
|
31
117
|
}
|
|
118
|
+
/** Validate and normalize the redirect metadata returned by gSP/gSSP. */
|
|
119
|
+
function resolvePagesRedirect(redirect, options) {
|
|
120
|
+
const errors = [];
|
|
121
|
+
const hasPermanent = redirect.permanent !== void 0;
|
|
122
|
+
const hasStatusCode = redirect.statusCode !== void 0;
|
|
123
|
+
if (hasPermanent && hasStatusCode) errors.push("`permanent` and `statusCode` can not both be provided");
|
|
124
|
+
else if (hasPermanent && typeof redirect.permanent !== "boolean") errors.push("`permanent` must be `true` or `false`");
|
|
125
|
+
else if (hasStatusCode && !ALLOWED_PAGES_REDIRECT_STATUS_CODES.has(redirect.statusCode)) errors.push(`\`statusCode\` must undefined or one of ${[...ALLOWED_PAGES_REDIRECT_STATUS_CODES].join(", ")}`);
|
|
126
|
+
if (typeof redirect.destination !== "string") errors.push(`\`destination\` should be string but received ${typeof redirect.destination}`);
|
|
127
|
+
if (redirect.basePath !== void 0 && typeof redirect.basePath !== "boolean") errors.push(`\`basePath\` should be undefined or a false, received ${typeof redirect.basePath}`);
|
|
128
|
+
if (errors.length > 0) throw new Error(`Invalid redirect object returned from ${options.method} for ${options.routeUrl}\n${errors.join(" and ")}\nSee more info here: https://nextjs.org/docs/messages/invalid-redirect-gssp`);
|
|
129
|
+
return {
|
|
130
|
+
destination: options.sanitizeDestination(redirect.destination),
|
|
131
|
+
statusCode: resolvePagesRedirectStatus(redirect),
|
|
132
|
+
...redirect.basePath === void 0 ? {} : { basePath: redirect.basePath }
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function resolvePagesRedirectLocation(redirect, configuredBasePath = "") {
|
|
136
|
+
let destination = redirect.destination;
|
|
137
|
+
if (configuredBasePath && redirect.basePath !== false && redirect.destination.startsWith("/")) destination = `${configuredBasePath}${redirect.destination}`;
|
|
138
|
+
if (!destination.startsWith("/")) return destination;
|
|
139
|
+
const urlParts = destination.split("?");
|
|
140
|
+
return urlParts[0].replace(/\\/g, "/").replace(/\/\/+/g, "/") + (urlParts[1] ? `?${urlParts.slice(1).join("?")}` : "");
|
|
141
|
+
}
|
|
142
|
+
function buildPagesRedirectProps(redirect, props) {
|
|
143
|
+
return {
|
|
144
|
+
...props,
|
|
145
|
+
pageProps: {
|
|
146
|
+
...isUnknownRecord(props.pageProps) ? props.pageProps : {},
|
|
147
|
+
__N_REDIRECT: redirect.destination,
|
|
148
|
+
__N_REDIRECT_STATUS: redirect.statusCode,
|
|
149
|
+
...redirect.basePath === void 0 ? {} : { __N_REDIRECT_BASE_PATH: redirect.basePath }
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
32
153
|
function normalizePagesRenderProps(props) {
|
|
154
|
+
if (!("pageProps" in props)) return { pageProps: props };
|
|
33
155
|
return {
|
|
34
156
|
...props,
|
|
35
157
|
pageProps: props.pageProps
|
|
@@ -57,11 +179,7 @@ async function loadPagesAppInitialRenderProps(options, getSharedReqRes) {
|
|
|
57
179
|
const initialProps = await loadPagesGetInitialProps(options.AppComponent, {
|
|
58
180
|
AppTree: options.createAppTree ?? options.createPageElement,
|
|
59
181
|
Component: options.pageModule.default,
|
|
60
|
-
router:
|
|
61
|
-
pathname: options.routePattern,
|
|
62
|
-
query: options.query,
|
|
63
|
-
asPath: options.asPath ?? options.routeUrl
|
|
64
|
-
},
|
|
182
|
+
router: options.router ?? createPagesGetInitialPropsRouter(options.routePattern, options.query, options.asPath ?? options.routeUrl),
|
|
65
183
|
ctx: {
|
|
66
184
|
req,
|
|
67
185
|
res,
|
|
@@ -79,8 +197,8 @@ async function loadPagesAppInitialRenderProps(options, getSharedReqRes) {
|
|
|
79
197
|
response: responsePromise
|
|
80
198
|
};
|
|
81
199
|
if (initialProps) {
|
|
82
|
-
renderProps =
|
|
83
|
-
pageProps = isUnknownRecord(
|
|
200
|
+
renderProps = initialProps;
|
|
201
|
+
pageProps = isUnknownRecord(initialProps.pageProps) ? initialProps.pageProps : {};
|
|
84
202
|
}
|
|
85
203
|
return {
|
|
86
204
|
kind: "props",
|
|
@@ -109,25 +227,67 @@ async function loadPagesAppInitialRenderProps(options, getSharedReqRes) {
|
|
|
109
227
|
* redirects (search `__N_REDIRECT`), consumed in
|
|
110
228
|
* `packages/next/src/shared/lib/router/router.ts` (`pageProps.__N_REDIRECT`).
|
|
111
229
|
*/
|
|
112
|
-
function buildPagesRedirectResponse(redirect, options, props = { pageProps: {} }) {
|
|
113
|
-
const
|
|
230
|
+
function buildPagesRedirectResponse(redirect, options, props = { pageProps: {} }, method = "getStaticProps") {
|
|
231
|
+
const resolved = resolvePagesRedirect(redirect, {
|
|
232
|
+
method,
|
|
233
|
+
routeUrl: options.routeUrl,
|
|
234
|
+
sanitizeDestination: options.sanitizeDestination
|
|
235
|
+
});
|
|
236
|
+
const redirectProps = buildPagesRedirectProps(resolved, props);
|
|
237
|
+
if (isDangerousScheme(resolved.destination)) {
|
|
238
|
+
const headers = new Headers({
|
|
239
|
+
"Cache-Control": "private, no-cache, no-store, max-age=0, must-revalidate",
|
|
240
|
+
"Content-Type": "text/plain; charset=utf-8"
|
|
241
|
+
});
|
|
242
|
+
if (options.deploymentId) headers.set(NEXTJS_DEPLOYMENT_ID_HEADER, options.deploymentId);
|
|
243
|
+
return new Response("Invalid redirect destination", {
|
|
244
|
+
status: 500,
|
|
245
|
+
headers
|
|
246
|
+
});
|
|
247
|
+
}
|
|
114
248
|
if (options.isDataReq) {
|
|
115
249
|
const init = { headers: {} };
|
|
116
250
|
if (options.deploymentId) init.headers[NEXTJS_DEPLOYMENT_ID_HEADER] = options.deploymentId;
|
|
117
|
-
return buildNextDataPropsJsonResponse(
|
|
118
|
-
...props,
|
|
119
|
-
pageProps: {
|
|
120
|
-
...isUnknownRecord(props.pageProps) ? props.pageProps : {},
|
|
121
|
-
__N_REDIRECT: destination,
|
|
122
|
-
__N_REDIRECT_STATUS: resolvePagesRedirectStatus(redirect)
|
|
123
|
-
}
|
|
124
|
-
}, options.safeJsonStringify, init);
|
|
251
|
+
return buildNextDataPropsJsonResponse(redirectProps, options.safeJsonStringify, init);
|
|
125
252
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
253
|
+
const location = resolvePagesRedirectLocation(resolved, options.basePath);
|
|
254
|
+
return new Response(location, {
|
|
255
|
+
status: resolved.statusCode,
|
|
256
|
+
headers: {
|
|
257
|
+
Location: location,
|
|
258
|
+
...resolved.statusCode === 308 ? { Refresh: `0;url=${location}` } : {}
|
|
259
|
+
}
|
|
129
260
|
});
|
|
130
261
|
}
|
|
262
|
+
function buildCachedPagesRedirectResponse(cached, options) {
|
|
263
|
+
const props = normalizePagesRenderProps(cached.props);
|
|
264
|
+
const pageProps = isUnknownRecord(props.pageProps) ? props.pageProps : {};
|
|
265
|
+
const destination = pageProps.__N_REDIRECT;
|
|
266
|
+
const statusCode = pageProps.__N_REDIRECT_STATUS;
|
|
267
|
+
const redirectBasePath = pageProps.__N_REDIRECT_BASE_PATH;
|
|
268
|
+
if (typeof destination !== "string") throw new Error("Invalid cached Pages redirect: missing __N_REDIRECT");
|
|
269
|
+
return buildPagesRedirectResponse({
|
|
270
|
+
destination,
|
|
271
|
+
...typeof statusCode === "number" ? { statusCode } : {},
|
|
272
|
+
...redirectBasePath === void 0 ? {} : { basePath: redirectBasePath }
|
|
273
|
+
}, options, props);
|
|
274
|
+
}
|
|
275
|
+
function getCachedPagesRedirect(cached) {
|
|
276
|
+
if (cached?.kind === "REDIRECT") return cached;
|
|
277
|
+
if (cached?.kind !== "PAGES") return null;
|
|
278
|
+
const locationHeader = cached.headers ? Object.entries(cached.headers).find(([name]) => name.toLowerCase() === "location")?.[1] : void 0;
|
|
279
|
+
const destination = Array.isArray(locationHeader) ? locationHeader[0] : locationHeader;
|
|
280
|
+
if (typeof destination !== "string" || typeof cached.status !== "number" || !ALLOWED_PAGES_REDIRECT_STATUS_CODES.has(cached.status)) return null;
|
|
281
|
+
const props = normalizePagesRenderProps(cached.pageData);
|
|
282
|
+
return {
|
|
283
|
+
kind: "REDIRECT",
|
|
284
|
+
props: buildPagesRedirectProps({
|
|
285
|
+
destination,
|
|
286
|
+
statusCode: cached.status,
|
|
287
|
+
basePath: false
|
|
288
|
+
}, props)
|
|
289
|
+
};
|
|
290
|
+
}
|
|
131
291
|
function getPagesRouteParams(routePattern) {
|
|
132
292
|
return routePattern.split("/").map((segment) => {
|
|
133
293
|
const optionalCatchAll = segment.match(/^\[\[\.\.\.(.+)\]\]$/);
|
|
@@ -152,7 +312,7 @@ function getPagesRouteParams(routePattern) {
|
|
|
152
312
|
}).filter((param) => param !== null);
|
|
153
313
|
}
|
|
154
314
|
function matchesPagesStaticPath(pathEntry, params, routeParams, routeUrl) {
|
|
155
|
-
if (typeof pathEntry === "string") return normalizeStaticPathname(pathEntry) === normalizeStaticPathname(routeUrl);
|
|
315
|
+
if (typeof pathEntry === "string") return normalizePathnameForRouteMatch(normalizeStaticPathname(pathEntry)) === normalizePathnameForRouteMatch(normalizeStaticPathname(routeUrl));
|
|
156
316
|
const entryParams = pathEntry.params;
|
|
157
317
|
if (entryParams === void 0 || entryParams === null) return false;
|
|
158
318
|
return routeParams.every(({ key, repeat, optional }) => {
|
|
@@ -170,12 +330,12 @@ function matchesPagesStaticPath(pathEntry, params, routeParams, routeUrl) {
|
|
|
170
330
|
return String(value) === String(actual);
|
|
171
331
|
});
|
|
172
332
|
}
|
|
173
|
-
function buildPagesCacheResponse(html, cacheState, fontLinkHeader, revalidateSeconds, expireSeconds, cacheControl, status) {
|
|
333
|
+
function buildPagesCacheResponse(html, cacheState, fontLinkHeader, revalidateSeconds, expireSeconds, cacheControl, status, cachedHeaders) {
|
|
174
334
|
const { cacheControl: cacheControlHeader } = decideIsr({
|
|
175
335
|
cacheState,
|
|
176
336
|
kind: "pages",
|
|
177
337
|
revalidateSeconds: revalidateSeconds ?? 60,
|
|
178
|
-
expireSeconds,
|
|
338
|
+
expireSeconds: cacheControl?.expire === void 0 ? void 0 : expireSeconds,
|
|
179
339
|
cacheControlMeta: cacheControl
|
|
180
340
|
});
|
|
181
341
|
const headers = new Headers({
|
|
@@ -184,6 +344,13 @@ function buildPagesCacheResponse(html, cacheState, fontLinkHeader, revalidateSec
|
|
|
184
344
|
});
|
|
185
345
|
applyCdnResponseHeaders(headers, { cacheControl: cacheControlHeader });
|
|
186
346
|
if (fontLinkHeader) headers.set("Link", fontLinkHeader);
|
|
347
|
+
if (cachedHeaders) for (const [name, value] of Object.entries(cachedHeaders)) {
|
|
348
|
+
if (!isCachedPagesRepresentationHeader(name.toLowerCase())) continue;
|
|
349
|
+
if (Array.isArray(value)) {
|
|
350
|
+
headers.delete(name);
|
|
351
|
+
for (const item of value) headers.append(name, item);
|
|
352
|
+
} else headers.set(name, value);
|
|
353
|
+
}
|
|
187
354
|
return new Response(html, {
|
|
188
355
|
status: status ?? 200,
|
|
189
356
|
headers
|
|
@@ -248,6 +415,7 @@ async function resolvePagesPageData(options) {
|
|
|
248
415
|
const userFacingParams = options.route.isDynamic ? options.params : null;
|
|
249
416
|
let isFallback = false;
|
|
250
417
|
let shouldPersistFallbackData = false;
|
|
418
|
+
let onDemandPreviousCacheEntry;
|
|
251
419
|
const previewData = options.isOnDemandRevalidate ? false : options.previewData ?? false;
|
|
252
420
|
if (typeof options.pageModule.getStaticPaths === "function" && options.route.isDynamic) {
|
|
253
421
|
const pathsResult = await options.pageModule.getStaticPaths({
|
|
@@ -258,11 +426,29 @@ async function resolvePagesPageData(options) {
|
|
|
258
426
|
const paths = pathsResult?.paths ?? [];
|
|
259
427
|
const routeParams = getPagesRouteParams(options.routePattern);
|
|
260
428
|
const isValidPath = paths.some((pathEntry) => matchesPagesStaticPath(pathEntry, options.params, routeParams, options.routeUrl));
|
|
261
|
-
if (fallback === false && !isValidPath && previewData === false)
|
|
429
|
+
if (fallback === false && !isValidPath && previewData === false) {
|
|
430
|
+
if (options.isOnDemandRevalidate && !options.revalidateOnlyGenerated) return {
|
|
431
|
+
kind: "response",
|
|
432
|
+
response: new Response("This page could not be found", { status: 404 }),
|
|
433
|
+
onDemandRevalidateSuccess: false
|
|
434
|
+
};
|
|
435
|
+
return buildPagesNotFoundResult(options);
|
|
436
|
+
}
|
|
262
437
|
const isBotRequest = !!options.userAgent && isBotUserAgent(options.userAgent, options.htmlLimitedBots);
|
|
263
438
|
if (fallback === true && !isValidPath && !options.isDataReq && !isBotRequest && previewData === false) isFallback = true;
|
|
264
439
|
shouldPersistFallbackData = fallback === true && !isValidPath && options.isDataReq === true;
|
|
265
440
|
}
|
|
441
|
+
if (typeof options.pageModule.getStaticProps === "function" && options.isOnDemandRevalidate && options.revalidateOnlyGenerated) {
|
|
442
|
+
const pathname = options.isrCachePathname ?? options.routeUrl.split("?")[0];
|
|
443
|
+
onDemandPreviousCacheEntry = await options.isrGet(options.isrCacheKey("pages", pathname));
|
|
444
|
+
if (!onDemandPreviousCacheEntry) return {
|
|
445
|
+
kind: "response",
|
|
446
|
+
response: new Response("This page could not be found", {
|
|
447
|
+
status: 404,
|
|
448
|
+
headers: { [NEXTJS_CACHE_HEADER]: "REVALIDATED" }
|
|
449
|
+
})
|
|
450
|
+
};
|
|
451
|
+
}
|
|
266
452
|
let pageProps = {};
|
|
267
453
|
let gsspRes = null;
|
|
268
454
|
const previewContext = previewData === false ? {} : {
|
|
@@ -288,7 +474,7 @@ async function resolvePagesPageData(options) {
|
|
|
288
474
|
return null;
|
|
289
475
|
}
|
|
290
476
|
if (isFallback) {
|
|
291
|
-
const pathname = options.routeUrl.split("?")[0];
|
|
477
|
+
const pathname = options.isrCachePathname ?? options.routeUrl.split("?")[0];
|
|
292
478
|
if ((await options.isrGet(options.isrCacheKey("pages", pathname)))?.value.value?.kind !== "PAGES") {
|
|
293
479
|
const appShortCircuit = await loadForegroundAppInitialRenderProps();
|
|
294
480
|
if (appShortCircuit) return appShortCircuit;
|
|
@@ -332,10 +518,7 @@ async function resolvePagesPageData(options) {
|
|
|
332
518
|
response: await responsePromise
|
|
333
519
|
};
|
|
334
520
|
if (result?.props) {
|
|
335
|
-
pageProps =
|
|
336
|
-
...pageProps,
|
|
337
|
-
...await Promise.resolve(result.props)
|
|
338
|
-
};
|
|
521
|
+
pageProps = mergePagesDataProps(renderProps.pageProps, await Promise.resolve(result.props));
|
|
339
522
|
renderProps = {
|
|
340
523
|
...renderProps,
|
|
341
524
|
pageProps
|
|
@@ -343,28 +526,22 @@ async function resolvePagesPageData(options) {
|
|
|
343
526
|
}
|
|
344
527
|
if (result?.redirect) return {
|
|
345
528
|
kind: "response",
|
|
346
|
-
response: buildPagesRedirectResponse(result.redirect, options, renderProps)
|
|
529
|
+
response: buildPagesRedirectResponse(result.redirect, options, renderProps, "getServerSideProps")
|
|
347
530
|
};
|
|
348
531
|
if (result?.notFound) return buildPagesNotFoundResult(options);
|
|
349
532
|
if (result?.props !== void 0 && options.validatePropsSerialization !== false) isSerializableProps(options.routePattern, "getServerSideProps", pageProps);
|
|
350
533
|
gsspRes = res;
|
|
351
534
|
}
|
|
352
535
|
let isrRevalidateSeconds = null;
|
|
536
|
+
let isrExpireSeconds;
|
|
353
537
|
if (typeof options.pageModule.getStaticProps === "function") {
|
|
354
|
-
const pathname = options.routeUrl.split("?")[0];
|
|
538
|
+
const pathname = options.isrCachePathname ?? options.routeUrl.split("?")[0];
|
|
355
539
|
const cacheKey = options.isrCacheKey("pages", pathname);
|
|
356
|
-
const cached = await options.isrGet(cacheKey);
|
|
540
|
+
const cached = onDemandPreviousCacheEntry !== void 0 ? onDemandPreviousCacheEntry : await options.isrGet(cacheKey);
|
|
357
541
|
const cachedValue = cached?.value.value;
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
if (hitBotResult) return hitBotResult;
|
|
362
|
-
return {
|
|
363
|
-
kind: "response",
|
|
364
|
-
response: hitResponse
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
|
-
if (!options.isOnDemandRevalidate && cachedValue?.kind === "PAGES" && !cachedValue.generatedFromDataRequest && cached && cached.isStale && !options.scriptNonce && !options.isDataReq && previewData === false) {
|
|
542
|
+
const isLegacyCachedNotFound = cachedValue?.kind === "PAGES" && cachedValue.status === 404 && options.routePattern !== "/404" && options.routePattern !== "/_error";
|
|
543
|
+
const cachedRedirect = getCachedPagesRedirect(cachedValue);
|
|
544
|
+
const scheduleStaleRegeneration = () => {
|
|
368
545
|
options.triggerBackgroundRegeneration(cacheKey, async function() {
|
|
369
546
|
return options.runInFreshUnifiedContext(async () => {
|
|
370
547
|
options.applyRequestContexts();
|
|
@@ -379,18 +556,35 @@ async function resolvePagesPageData(options) {
|
|
|
379
556
|
defaultLocale: options.i18n.defaultLocale,
|
|
380
557
|
revalidateReason: "stale"
|
|
381
558
|
});
|
|
382
|
-
if (freshResult
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
559
|
+
if (!freshResult) return;
|
|
560
|
+
assertPages404DoesNotReturnNotFound(options.routePattern, freshResult);
|
|
561
|
+
const revalidateSeconds = resolvePagesRevalidateSeconds(freshResult, options.routeUrl);
|
|
562
|
+
const expireSeconds = resolvePagesExpireSeconds(freshResult, options.expireSeconds);
|
|
563
|
+
if (freshResult.redirect) {
|
|
564
|
+
const redirect = resolvePagesRedirect(freshResult.redirect, {
|
|
565
|
+
method: "getStaticProps",
|
|
566
|
+
routeUrl: options.routeUrl,
|
|
567
|
+
sanitizeDestination: options.sanitizeDestination
|
|
568
|
+
});
|
|
569
|
+
await options.isrSet(cacheKey, {
|
|
570
|
+
kind: "REDIRECT",
|
|
571
|
+
props: buildPagesRedirectProps(redirect, freshRenderProps)
|
|
572
|
+
}, revalidateSeconds, void 0, expireSeconds);
|
|
573
|
+
return;
|
|
391
574
|
}
|
|
392
|
-
|
|
393
|
-
|
|
575
|
+
if (freshResult.notFound) {
|
|
576
|
+
await options.isrSet(cacheKey, null, revalidateSeconds, void 0, expireSeconds);
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
if (freshResult.props === void 0) return;
|
|
580
|
+
const resolvedFreshProps = await Promise.resolve(freshResult.props);
|
|
581
|
+
freshPageProps = mergePagesDataProps(freshRenderProps.pageProps, resolvedFreshProps);
|
|
582
|
+
freshRenderProps = {
|
|
583
|
+
...freshRenderProps,
|
|
584
|
+
pageProps: freshPageProps
|
|
585
|
+
};
|
|
586
|
+
if (options.validatePropsSerialization !== false) isSerializableProps(options.routePattern, "getStaticProps", freshPageProps);
|
|
587
|
+
if (cachedValue?.kind === "PAGES" && !cachedValue.generatedFromDataRequest) {
|
|
394
588
|
const freshHtml = await renderPagesIsrHtml({
|
|
395
589
|
buildId: options.buildId,
|
|
396
590
|
cachedHtml: cachedValue.html,
|
|
@@ -405,15 +599,61 @@ async function resolvePagesPageData(options) {
|
|
|
405
599
|
nextData: options.nextData,
|
|
406
600
|
vinext: options.vinext
|
|
407
601
|
});
|
|
408
|
-
await options.isrSet(cacheKey, buildPagesCacheValue(freshHtml, freshRenderProps, options.statusCode),
|
|
602
|
+
await options.isrSet(cacheKey, buildPagesCacheValue(freshHtml, freshRenderProps, options.statusCode), revalidateSeconds, void 0, expireSeconds);
|
|
603
|
+
return;
|
|
409
604
|
}
|
|
605
|
+
await options.isrSet(cacheKey, {
|
|
606
|
+
kind: "PAGES",
|
|
607
|
+
html: "",
|
|
608
|
+
pageData: freshRenderProps,
|
|
609
|
+
generatedFromDataRequest: true,
|
|
610
|
+
headers: void 0,
|
|
611
|
+
status: void 0
|
|
612
|
+
}, revalidateSeconds, void 0, expireSeconds);
|
|
410
613
|
});
|
|
411
614
|
}, {
|
|
412
615
|
routerKind: "Pages Router",
|
|
413
616
|
routePath: options.routePattern,
|
|
414
617
|
routeType: "render"
|
|
415
618
|
});
|
|
416
|
-
|
|
619
|
+
};
|
|
620
|
+
if (!options.isOnDemandRevalidate && cached && !cached.isStale && !cached.isExpired && previewData === false) {
|
|
621
|
+
if (cachedValue === null) return buildCachedPagesNotFoundResult(options, cached.value, "HIT");
|
|
622
|
+
if (isLegacyCachedNotFound) return buildCachedPagesNotFoundResult(options, cached.value, "HIT");
|
|
623
|
+
if (cachedRedirect) return {
|
|
624
|
+
kind: "response",
|
|
625
|
+
response: applyCachedPagesRepresentationHeaders(buildCachedPagesRedirectResponse(cachedRedirect, options), "HIT", cached.value, options)
|
|
626
|
+
};
|
|
627
|
+
if (options.isDataReq && cachedValue?.kind === "PAGES") return {
|
|
628
|
+
kind: "response",
|
|
629
|
+
response: applyCachedPagesRepresentationHeaders(buildNextDataPropsJsonResponse(normalizePagesRenderProps(cachedValue.pageData), options.safeJsonStringify, options.deploymentId ? { headers: { [NEXTJS_DEPLOYMENT_ID_HEADER]: options.deploymentId } } : void 0), "HIT", cached.value, options)
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
if (!options.isOnDemandRevalidate && cached?.isStale === false && !cached.isExpired && cachedValue?.kind === "PAGES" && !cachedValue.generatedFromDataRequest && cached && !cached.isStale && !options.scriptNonce && !options.isDataReq && previewData === false) {
|
|
633
|
+
const hitResponse = buildPagesCacheResponse(cachedValue.html, "HIT", options.fontLinkHeader, void 0, options.expireSeconds, cached.value.cacheControl, cachedValue.status, cachedValue.headers);
|
|
634
|
+
const hitBotResult = applyBotETagAndCheck(hitResponse, cachedValue.html, options);
|
|
635
|
+
if (hitBotResult) return hitBotResult;
|
|
636
|
+
return {
|
|
637
|
+
kind: "response",
|
|
638
|
+
response: hitResponse
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
if (!options.isOnDemandRevalidate && cached && cached.isStale && !cached.isExpired && !options.scriptNonce && previewData === false && (cachedValue === null || cachedRedirect !== null || isLegacyCachedNotFound || options.isDataReq)) {
|
|
642
|
+
scheduleStaleRegeneration();
|
|
643
|
+
if (cachedValue === null) return buildCachedPagesNotFoundResult(options, cached.value, "STALE");
|
|
644
|
+
if (isLegacyCachedNotFound) return buildCachedPagesNotFoundResult(options, cached.value, "STALE");
|
|
645
|
+
if (cachedRedirect) return {
|
|
646
|
+
kind: "response",
|
|
647
|
+
response: applyCachedPagesRepresentationHeaders(buildCachedPagesRedirectResponse(cachedRedirect, options), "STALE", cached.value, options)
|
|
648
|
+
};
|
|
649
|
+
if (cachedValue?.kind === "PAGES") return {
|
|
650
|
+
kind: "response",
|
|
651
|
+
response: applyCachedPagesRepresentationHeaders(buildNextDataPropsJsonResponse(normalizePagesRenderProps(cachedValue.pageData), options.safeJsonStringify, options.deploymentId ? { headers: { [NEXTJS_DEPLOYMENT_ID_HEADER]: options.deploymentId } } : void 0), "STALE", cached.value, options)
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
if (!options.isOnDemandRevalidate && cachedValue?.kind === "PAGES" && !cachedValue.generatedFromDataRequest && cached && cached.isStale && !cached.isExpired && !options.scriptNonce && !options.isDataReq && previewData === false) {
|
|
655
|
+
scheduleStaleRegeneration();
|
|
656
|
+
const staleResponse = buildPagesCacheResponse(cachedValue.html, "STALE", options.fontLinkHeader, void 0, options.expireSeconds, cached.value.cacheControl, cachedValue.status, cachedValue.headers);
|
|
417
657
|
const staleBotResult = applyBotETagAndCheck(staleResponse, cachedValue.html, options);
|
|
418
658
|
if (staleBotResult) return staleBotResult;
|
|
419
659
|
return {
|
|
@@ -421,7 +661,7 @@ async function resolvePagesPageData(options) {
|
|
|
421
661
|
response: staleResponse
|
|
422
662
|
};
|
|
423
663
|
}
|
|
424
|
-
const generatedPageData = !options.isOnDemandRevalidate && previewData === false && cached?.isStale === false && cachedValue?.kind === "PAGES" && cachedValue.generatedFromDataRequest && isUnknownRecord(cachedValue.pageData) ? cachedValue.pageData : null;
|
|
664
|
+
const generatedPageData = !options.isOnDemandRevalidate && previewData === false && cached?.isStale === false && !cached.isExpired && cachedValue?.kind === "PAGES" && cachedValue.generatedFromDataRequest && isUnknownRecord(cachedValue.pageData) ? cachedValue.pageData : null;
|
|
425
665
|
if (!generatedPageData) {
|
|
426
666
|
const shortCircuit = await loadForegroundAppInitialRenderProps();
|
|
427
667
|
if (shortCircuit) return shortCircuit;
|
|
@@ -434,30 +674,58 @@ async function resolvePagesPageData(options) {
|
|
|
434
674
|
...previewContext,
|
|
435
675
|
revalidateReason: options.isOnDemandRevalidate ? "on-demand" : options.isBuildTimePrerendering ? "build" : "stale"
|
|
436
676
|
});
|
|
677
|
+
assertPages404DoesNotReturnNotFound(options.routePattern, result);
|
|
437
678
|
if (generatedPageData) {
|
|
438
|
-
renderProps = generatedPageData;
|
|
679
|
+
renderProps = normalizePagesRenderProps(generatedPageData);
|
|
439
680
|
pageProps = isUnknownRecord(renderProps.pageProps) ? renderProps.pageProps : {};
|
|
440
681
|
}
|
|
441
|
-
if (result?.props) {
|
|
442
|
-
pageProps =
|
|
443
|
-
...pageProps,
|
|
444
|
-
...result.props
|
|
445
|
-
};
|
|
682
|
+
if (result?.props !== void 0) {
|
|
683
|
+
pageProps = mergePagesDataProps(renderProps.pageProps, await Promise.resolve(result.props));
|
|
446
684
|
renderProps = {
|
|
447
685
|
...renderProps,
|
|
448
686
|
pageProps
|
|
449
687
|
};
|
|
450
688
|
}
|
|
451
|
-
if (result?.redirect)
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
689
|
+
if (result?.redirect) {
|
|
690
|
+
const response = buildPagesRedirectResponse(result.redirect, options, renderProps);
|
|
691
|
+
if (previewData === false) {
|
|
692
|
+
const revalidateSeconds = resolvePagesRevalidateSeconds(result, options.routeUrl);
|
|
693
|
+
const expireSeconds = resolvePagesExpireSeconds(result, options.expireSeconds);
|
|
694
|
+
const redirect = resolvePagesRedirect(result.redirect, {
|
|
695
|
+
method: "getStaticProps",
|
|
696
|
+
routeUrl: options.routeUrl,
|
|
697
|
+
sanitizeDestination: options.sanitizeDestination
|
|
698
|
+
});
|
|
699
|
+
await options.isrSet(cacheKey, {
|
|
700
|
+
kind: "REDIRECT",
|
|
701
|
+
props: buildPagesRedirectProps(redirect, renderProps)
|
|
702
|
+
}, revalidateSeconds, void 0, expireSeconds);
|
|
703
|
+
applyPagesTerminalMissHeaders(response, revalidateSeconds, pathname, expireSeconds);
|
|
704
|
+
}
|
|
705
|
+
return {
|
|
706
|
+
kind: "response",
|
|
707
|
+
response
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
if (result?.notFound) {
|
|
711
|
+
const revalidateSeconds = resolvePagesRevalidateSeconds(result, options.routeUrl);
|
|
712
|
+
const expireSeconds = resolvePagesExpireSeconds(result, options.expireSeconds);
|
|
713
|
+
if (previewData === false) await options.isrSet(cacheKey, null, revalidateSeconds, void 0, expireSeconds);
|
|
714
|
+
const notFoundResult = buildPagesNotFoundResult(options, revalidateSeconds, previewData === false ? "MISS" : void 0, expireSeconds);
|
|
715
|
+
if (notFoundResult.kind === "response" && previewData === false) applyPagesTerminalMissHeaders(notFoundResult.response, revalidateSeconds, pathname, expireSeconds);
|
|
716
|
+
return notFoundResult;
|
|
717
|
+
}
|
|
456
718
|
if (result?.props !== void 0 && options.validatePropsSerialization !== false) isSerializableProps(options.routePattern, "getStaticProps", pageProps);
|
|
457
|
-
if (previewData === false &&
|
|
458
|
-
|
|
719
|
+
if (previewData === false && result) {
|
|
720
|
+
isrRevalidateSeconds = resolvePagesRevalidateSeconds(result, options.routeUrl);
|
|
721
|
+
isrExpireSeconds = resolvePagesExpireSeconds(result, options.expireSeconds);
|
|
722
|
+
} else if (previewData === false && options.isOnDemandRevalidate) isrRevalidateSeconds = false;
|
|
723
|
+
else if (previewData === false && cachedValue?.kind === "PAGES" && cachedValue.generatedFromDataRequest) {
|
|
724
|
+
isrRevalidateSeconds = cached?.value.cacheControl?.revalidate ?? false;
|
|
725
|
+
isrExpireSeconds = cached?.value.cacheControl?.expire;
|
|
726
|
+
}
|
|
459
727
|
if (shouldPersistFallbackData && previewData === false) {
|
|
460
|
-
const revalidateSeconds = isrRevalidateSeconds ??
|
|
728
|
+
const revalidateSeconds = isrRevalidateSeconds ?? false;
|
|
461
729
|
await options.isrSet(cacheKey, {
|
|
462
730
|
kind: "PAGES",
|
|
463
731
|
html: "",
|
|
@@ -465,7 +733,7 @@ async function resolvePagesPageData(options) {
|
|
|
465
733
|
generatedFromDataRequest: true,
|
|
466
734
|
headers: void 0,
|
|
467
735
|
status: void 0
|
|
468
|
-
}, revalidateSeconds, void 0,
|
|
736
|
+
}, revalidateSeconds, void 0, isrExpireSeconds);
|
|
469
737
|
}
|
|
470
738
|
}
|
|
471
739
|
if (typeof options.pageModule.getServerSideProps !== "function" && typeof options.pageModule.getStaticProps !== "function" && hasPagesGetInitialProps(options.AppComponent)) {
|
|
@@ -505,10 +773,11 @@ async function resolvePagesPageData(options) {
|
|
|
505
773
|
documentReqRes: sharedReqRes,
|
|
506
774
|
gsspRes,
|
|
507
775
|
isrRevalidateSeconds,
|
|
776
|
+
isrExpireSeconds,
|
|
508
777
|
pageProps,
|
|
509
778
|
props: renderProps,
|
|
510
779
|
isFallback: false
|
|
511
780
|
};
|
|
512
781
|
}
|
|
513
782
|
//#endregion
|
|
514
|
-
export { getPagesRouteParams, matchesPagesStaticPath, renderPagesIsrHtml, resolvePagesPageData };
|
|
783
|
+
export { assertPages404DoesNotReturnNotFound, buildPagesRedirectProps, getPagesRouteParams, matchesPagesStaticPath, mergePagesDataProps, renderPagesIsrHtml, resolvePagesPageData, resolvePagesRedirect, resolvePagesRedirectLocation, resolvePagesRevalidateSeconds };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RenderPageEnhancers } from "./pages-document-initial-props.js";
|
|
2
|
+
import { PagesGetInitialPropsRouter } from "./pages-get-initial-props.js";
|
|
2
3
|
import { PagesPageModule } from "./pages-page-data.js";
|
|
3
4
|
import { ComponentType, ReactNode } from "react";
|
|
4
5
|
|
|
@@ -23,7 +24,7 @@ type I18nConfig = {
|
|
|
23
24
|
domain: string;
|
|
24
25
|
defaultLocale: string;
|
|
25
26
|
locales?: string[];
|
|
26
|
-
http?:
|
|
27
|
+
http?: true;
|
|
27
28
|
}>;
|
|
28
29
|
} | null;
|
|
29
30
|
type VinextConfigSubset = {
|
|
@@ -60,7 +61,8 @@ type CreatePagesPageHandlerOptions = {
|
|
|
60
61
|
*/
|
|
61
62
|
getPagesNavigationIsReadyFromSerializedState: ((routePattern: string | undefined, searchString: string, nextData?: Record<string, unknown>) => boolean) | null; /** `setI18nContext` from `vinext/i18n-context`. */
|
|
62
63
|
setI18nContext: ((ctx: Record<string, unknown>) => void) | null; /** `wrapWithRouterContext` from `next/router`. */
|
|
63
|
-
wrapWithRouterContext: ((element: ReactNode) => ReactNode) | null; /**
|
|
64
|
+
wrapWithRouterContext: ((element: ReactNode) => ReactNode) | null; /** Request-scoped `next/router` server instance. */
|
|
65
|
+
router?: PagesGetInitialPropsRouter; /** `resetSSRHead` from `next/head`. */
|
|
64
66
|
resetSSRHead: (() => void) | undefined; /** `getSSRHeadHTML` from `next/head`. */
|
|
65
67
|
getSSRHeadHTML: (() => string) | undefined; /** `setDocumentInitialHead` from `next/head`. */
|
|
66
68
|
setDocumentInitialHead: ((head: ReactNode[]) => void) | undefined; /** `flushPreloads` from `next/dynamic`. */
|
|
@@ -87,7 +89,11 @@ type RenderPageOptions = {
|
|
|
87
89
|
originalUrl?: string;
|
|
88
90
|
renderErrorPageOnMiss?: boolean;
|
|
89
91
|
__isInternalErrorRender?: boolean;
|
|
90
|
-
__forcedRoute?: PageRoute;
|
|
92
|
+
__forcedRoute?: PageRoute; /** Source-page cache lifetime forwarded while rendering a notFound error page. */
|
|
93
|
+
__notFoundRevalidateSeconds?: number | false; /** Source-page expire ceiling forwarded for the outgoing notFound response. */
|
|
94
|
+
__notFoundExpireSeconds?: number; /** Source-page identity used for the outgoing notFound cache tag. */
|
|
95
|
+
__notFoundCachePathname?: string; /** Internal recursion guard while a top-level on-demand request owns the batch. */
|
|
96
|
+
__skipOnDemandCoalesce?: boolean;
|
|
91
97
|
err?: unknown;
|
|
92
98
|
};
|
|
93
99
|
/**
|