vinext 1.0.0-beta.2 → 1.0.0-beta.4
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 +6 -9
- package/dist/build/client-build-config.js +7 -1
- package/dist/build/precompress.js +1 -1
- package/dist/build/prerender.d.ts +2 -1
- package/dist/build/prerender.js +12 -2
- package/dist/check.js +4 -0
- package/dist/cli-args.d.ts +2 -1
- package/dist/cli-args.js +10 -0
- package/dist/cli.js +14 -8
- package/dist/client/navigation-runtime.d.ts +6 -0
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/config-matchers.js +4 -1
- package/dist/config/dotenv.d.ts +3 -4
- package/dist/config/dotenv.js +30 -22
- package/dist/config/next-config.d.ts +16 -5
- package/dist/config/next-config.js +7 -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 +21 -3
- package/dist/entries/app-rsc-manifest.js +19 -0
- package/dist/entries/pages-client-entry.js +0 -1
- package/dist/entries/pages-server-entry.js +13 -3
- package/dist/index.js +122 -49
- package/dist/init-cloudflare.d.ts +3 -1
- package/dist/init-cloudflare.js +59 -5
- package/dist/plugins/client-reference-dedup.js +7 -5
- 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/require-context.js +20 -15
- package/dist/plugins/sass.js +3 -4
- 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 +14 -6
- package/dist/routing/app-route-graph.js +106 -16
- package/dist/server/api-handler.d.ts +2 -0
- package/dist/server/api-handler.js +7 -6
- package/dist/server/app-bfcache-identity.js +28 -2
- package/dist/server/app-browser-entry.js +175 -75
- package/dist/server/app-browser-navigation-controller.d.ts +23 -21
- package/dist/server/app-browser-navigation-controller.js +30 -5
- package/dist/server/app-browser-prefetch-response.d.ts +9 -0
- package/dist/server/app-browser-prefetch-response.js +32 -0
- package/dist/server/app-browser-state.d.ts +8 -3
- package/dist/server/app-browser-state.js +9 -3
- package/dist/server/app-page-cache-finalizer.js +1 -1
- package/dist/server/app-page-cache.d.ts +1 -1
- package/dist/server/app-page-cache.js +16 -2
- package/dist/server/app-page-dispatch.d.ts +9 -1
- package/dist/server/app-page-dispatch.js +37 -8
- package/dist/server/app-page-element-builder.d.ts +4 -1
- package/dist/server/app-page-element-builder.js +34 -7
- package/dist/server/app-page-head.d.ts +3 -3
- package/dist/server/app-page-head.js +58 -13
- package/dist/server/app-page-http-access-fallback-metadata.d.ts +2 -2
- package/dist/server/app-page-http-access-fallback-metadata.js +9 -1
- 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 +1 -1
- package/dist/server/app-page-render.js +13 -3
- package/dist/server/app-page-request.d.ts +3 -1
- package/dist/server/app-page-request.js +4 -13
- package/dist/server/app-page-response.d.ts +2 -0
- package/dist/server/app-page-response.js +7 -2
- package/dist/server/app-page-route-wiring.d.ts +10 -2
- package/dist/server/app-page-route-wiring.js +269 -59
- package/dist/server/app-pages-bridge.d.ts +2 -1
- package/dist/server/app-pages-bridge.js +3 -1
- package/dist/server/app-route-handler-cache.js +4 -0
- package/dist/server/app-route-handler-dispatch.js +9 -3
- package/dist/server/app-route-handler-response.js +1 -1
- package/dist/server/app-route-module-loader.d.ts +6 -0
- package/dist/server/app-route-module-loader.js +3 -0
- package/dist/server/app-router-entry.js +6 -3
- package/dist/server/app-rsc-cache-busting.d.ts +7 -0
- package/dist/server/app-rsc-cache-busting.js +6 -0
- package/dist/server/app-rsc-errors.js +10 -0
- package/dist/server/app-rsc-handler.d.ts +2 -0
- package/dist/server/app-rsc-handler.js +30 -13
- package/dist/server/app-rsc-render-mode.d.ts +3 -2
- package/dist/server/app-rsc-render-mode.js +4 -1
- package/dist/server/app-rsc-request-normalization.js +65 -4
- package/dist/server/app-rsc-route-matching.d.ts +9 -0
- package/dist/server/app-rsc-route-matching.js +6 -0
- package/dist/server/app-server-action-execution.d.ts +1 -1
- package/dist/server/app-ssr-entry.js +4 -4
- package/dist/server/app-visited-response-cache.d.ts +6 -1
- package/dist/server/app-visited-response-cache.js +49 -1
- package/dist/server/cache-control.d.ts +2 -2
- package/dist/server/cache-control.js +2 -1
- package/dist/server/dev-server.d.ts +3 -1
- package/dist/server/dev-server.js +204 -348
- package/dist/server/edge-api-runtime.d.ts +10 -1
- package/dist/server/edge-api-runtime.js +29 -1
- package/dist/server/headers.d.ts +4 -2
- package/dist/server/headers.js +6 -3
- package/dist/server/isr-cache.d.ts +10 -33
- package/dist/server/isr-cache.js +33 -43
- package/dist/server/isr-decision.d.ts +2 -2
- package/dist/server/pages-api-route.d.ts +4 -0
- package/dist/server/pages-api-route.js +6 -3
- package/dist/server/pages-asset-tags.d.ts +1 -0
- package/dist/server/pages-asset-tags.js +6 -4
- package/dist/server/pages-dev-hydration.js +0 -1
- package/dist/server/pages-document-asset-props.d.ts +26 -0
- package/dist/server/pages-document-asset-props.js +69 -0
- package/dist/server/pages-get-initial-props.d.ts +1 -1
- package/dist/server/pages-get-initial-props.js +1 -4
- 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 +10 -6
- package/dist/server/pages-page-data.d.ts +61 -9
- package/dist/server/pages-page-data.js +334 -74
- package/dist/server/pages-page-handler.d.ts +6 -1
- package/dist/server/pages-page-handler.js +119 -20
- package/dist/server/pages-page-response.d.ts +7 -3
- package/dist/server/pages-page-response.js +41 -33
- package/dist/server/pages-request-pipeline.d.ts +7 -0
- package/dist/server/pages-request-pipeline.js +5 -1
- 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 +10 -4
- package/dist/server/prerender-manifest.d.ts +1 -0
- package/dist/server/prod-server.d.ts +2 -1
- package/dist/server/prod-server.js +38 -13
- package/dist/server/revalidation-host.d.ts +11 -0
- package/dist/server/revalidation-host.js +19 -0
- package/dist/server/seed-cache.js +1 -1
- package/dist/server/worker-revalidation-context.d.ts +13 -0
- package/dist/server/worker-revalidation-context.js +30 -0
- package/dist/shims/app-router-scroll-state.d.ts +2 -1
- package/dist/shims/app-router-scroll-state.js +7 -2
- package/dist/shims/cache-handler.d.ts +1 -1
- package/dist/shims/cache-handler.js +10 -7
- package/dist/shims/cache-runtime.d.ts +6 -0
- package/dist/shims/cache-runtime.js +4 -1
- package/dist/shims/cache.js +1 -1
- package/dist/shims/document.js +15 -2
- package/dist/shims/error.js +1 -1
- package/dist/shims/fetch-cache.js +1 -1
- package/dist/shims/font-google-base.js +17 -8
- package/dist/shims/font-local.js +41 -10
- package/dist/shims/hash-scroll.d.ts +1 -1
- package/dist/shims/hash-scroll.js +2 -1
- package/dist/shims/headers.d.ts +10 -13
- package/dist/shims/headers.js +85 -36
- package/dist/shims/internal/cookie-serialize.d.ts +10 -9
- package/dist/shims/internal/cookie-serialize.js +9 -8
- package/dist/shims/internal/interpolate-as.d.ts +15 -1
- package/dist/shims/internal/interpolate-as.js +27 -2
- package/dist/shims/link.d.ts +2 -0
- package/dist/shims/link.js +77 -24
- package/dist/shims/metadata.d.ts +18 -34
- package/dist/shims/metadata.js +98 -56
- package/dist/shims/navigation.d.ts +18 -2
- package/dist/shims/navigation.js +70 -21
- package/dist/shims/request-context.d.ts +6 -2
- package/dist/shims/router.js +18 -7
- package/dist/shims/script.js +1 -1
- package/dist/shims/server.d.ts +7 -6
- package/dist/shims/server.js +156 -57
- package/dist/shims/slot.d.ts +2 -1
- package/dist/shims/slot.js +6 -2
- package/dist/shims/streamed-icons.d.ts +9 -0
- package/dist/shims/streamed-icons.js +33 -0
- package/dist/shims/unified-request-context.d.ts +21 -2
- package/dist/shims/unified-request-context.js +82 -1
- package/dist/utils/cache-control-metadata.d.ts +2 -1
- package/dist/utils/cache-control-metadata.js +5 -1
- 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/package.json +1 -1
|
@@ -1,25 +1,21 @@
|
|
|
1
|
-
import { createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
2
|
-
import
|
|
3
|
-
import { createValidFileMatcher, findFileWithExtensions, findFileWithExts } from "../routing/file-matcher.js";
|
|
1
|
+
import { closeAfterResponse, createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
2
|
+
import { createValidFileMatcher, findFileWithExts } from "../routing/file-matcher.js";
|
|
4
3
|
import { patternToNextFormat } from "../routing/route-validation.js";
|
|
5
4
|
import { matchRoute } from "../routing/pages-router.js";
|
|
6
|
-
import {
|
|
5
|
+
import { PRERENDER_REVALIDATE_HEADER } from "../utils/protocol-headers.js";
|
|
6
|
+
import { NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER } from "./headers.js";
|
|
7
7
|
import { isDangerousScheme } from "../shims/url-safety.js";
|
|
8
|
+
import { sanitizeDestination } from "../config/config-matchers.js";
|
|
8
9
|
import { importModule, reportRequestError } from "./instrumentation.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { PRERENDER_REVALIDATE_HEADER, buildPagesCacheValue, getRevalidateDuration, isOnDemandRevalidateRequest, isrCacheKey, isrGet, isrSet, setRevalidateDuration, triggerBackgroundRegeneration } from "./isr-cache.js";
|
|
14
|
-
import { _runWithCacheState } from "../shims/cache-request-state.js";
|
|
15
|
-
import { ensureFetchPatch, runWithFetchCache } from "../shims/fetch-cache.js";
|
|
16
|
-
import { runWithPrivateCache } from "../shims/cache-runtime.js";
|
|
10
|
+
import { NEVER_CACHE_CONTROL } from "./cache-control.js";
|
|
11
|
+
import { buildMissIsrCacheControl } from "./isr-decision.js";
|
|
12
|
+
import { isOnDemandRevalidateRequest } from "./isr-cache.js";
|
|
13
|
+
import { ensureFetchPatch } from "../shims/fetch-cache.js";
|
|
17
14
|
import { mergeRouteParamsIntoQuery, parseQueryString } from "../utils/query.js";
|
|
18
15
|
import "../shims/router-state.js";
|
|
19
|
-
import { runWithHeadState } from "../shims/head-state.js";
|
|
20
|
-
import { runWithServerInsertedHTMLState } from "../shims/navigation-state.js";
|
|
21
16
|
import { withScriptNonce } from "../shims/script-nonce-context.js";
|
|
22
17
|
import { createInlineScriptTag, createNonceAttribute, escapeHtmlAttr, safeJsonStringify } from "./html.js";
|
|
18
|
+
import { applyDocumentAssetProps, extractDocumentAssetProps, markDocumentAssetPropsProtectedTags, stripDocumentAssetPropsProtectionMarkers } from "./pages-document-asset-props.js";
|
|
23
19
|
import { getClientTraceMetadataHTML } from "./client-trace-metadata.js";
|
|
24
20
|
import { getScriptNonceFromNodeHeaderSources } from "./csp.js";
|
|
25
21
|
import { logRequest, now } from "./request-log.js";
|
|
@@ -29,15 +25,16 @@ import { buildPagesReadinessNextData } from "./pages-readiness.js";
|
|
|
29
25
|
import { resolvePagesPageMethodResponse } from "./pages-page-method.js";
|
|
30
26
|
import { loadUserDocumentInitialProps, runDocumentRenderPage } from "./pages-document-initial-props.js";
|
|
31
27
|
import { callDocumentGetInitialProps } from "./document-initial-head.js";
|
|
28
|
+
import { isBotUserAgent } from "../utils/html-limited-bots.js";
|
|
32
29
|
import { hasPagesGetInitialProps, loadDevAppInitialProps, loadPagesGetInitialProps } from "./pages-get-initial-props.js";
|
|
33
30
|
import { isSerializableProps } from "./pages-serializable-props.js";
|
|
34
|
-
import {
|
|
35
|
-
import { getPagesRouteParams, matchesPagesStaticPath } from "./pages-page-data.js";
|
|
31
|
+
import { assertPages404DoesNotReturnNotFound, buildPagesRedirectProps, getPagesRouteParams, matchesPagesStaticPath, mergePagesDataProps, resolvePagesRedirect, resolvePagesRedirectLocation, resolvePagesRevalidateSeconds } from "./pages-page-data.js";
|
|
36
32
|
import { createPagesDevAssetUrl, createPagesDevModuleUrl } from "./pages-dev-module-url.js";
|
|
37
33
|
import { createPagesDevHydrationScript } from "./pages-dev-hydration.js";
|
|
38
34
|
import { getManifestFilesForModule } from "./pages-asset-tags.js";
|
|
39
35
|
import { PAGES_PREVIEW_CACHE_CONTROL, appendPagesPreviewClearCookies, getPagesPreviewState } from "./pages-preview.js";
|
|
40
36
|
import { attachPagesRequestCookies } from "./pages-node-compat.js";
|
|
37
|
+
import { randomUUID } from "node:crypto";
|
|
41
38
|
import React from "react";
|
|
42
39
|
import { renderToReadableStream } from "react-dom/server.edge";
|
|
43
40
|
//#region src/server/dev-server.ts
|
|
@@ -78,8 +75,15 @@ function applyDevPagesPreviewResponse(res, preview) {
|
|
|
78
75
|
applyDevPagesPreviewHeaders(headers, preview);
|
|
79
76
|
for (const [name, value] of Object.entries(headers)) res.setHeader(name, value);
|
|
80
77
|
}
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
const DEV_PAGES_CACHE_CONTROL = "no-cache, must-revalidate";
|
|
79
|
+
const PAGES_CACHE_ONE_YEAR_SECONDS = 31536e3;
|
|
80
|
+
function applyDevPagesCacheHeaders(res, state, cacheControl = DEV_PAGES_CACHE_CONTROL) {
|
|
81
|
+
res.setHeader(NEXTJS_CACHE_HEADER, state);
|
|
82
|
+
res.setHeader("Cache-Control", cacheControl);
|
|
83
|
+
}
|
|
84
|
+
function buildDevPagesTerminalCacheControl(revalidateSeconds, expireSeconds) {
|
|
85
|
+
if (revalidateSeconds === false) return `s-maxage=${PAGES_CACHE_ONE_YEAR_SECONDS}`;
|
|
86
|
+
return buildMissIsrCacheControl(revalidateSeconds, expireSeconds);
|
|
83
87
|
}
|
|
84
88
|
const DEV_STYLESHEET_ASSET_RE = /\.(?:css|scss|sass)$/i;
|
|
85
89
|
const transformedStylesheetAssetsCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -172,11 +176,17 @@ async function collectDevInitialStylesheetHeadHTML(server, runner, moduleIds, no
|
|
|
172
176
|
* (`buildPagesRedirectResponse`) and Next.js's `render.tsx` `__N_REDIRECT`
|
|
173
177
|
* handling. See AGENTS.md "dev and prod server parity".
|
|
174
178
|
*/
|
|
175
|
-
function writeGsspRedirect(res, redirect, isDataReq, props) {
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
179
|
+
function writeGsspRedirect(res, redirect, isDataReq, props, options) {
|
|
180
|
+
const resolved = resolvePagesRedirect(redirect, {
|
|
181
|
+
method: options.method,
|
|
182
|
+
routeUrl: options.routeUrl,
|
|
183
|
+
sanitizeDestination
|
|
184
|
+
});
|
|
185
|
+
const redirectProps = buildPagesRedirectProps(resolved, {
|
|
186
|
+
...props,
|
|
187
|
+
pageProps: props.pageProps
|
|
188
|
+
});
|
|
189
|
+
if (isDangerousScheme(resolved.destination)) {
|
|
180
190
|
const deploymentId = process.env.__VINEXT_DEPLOYMENT_ID || process.env.NEXT_DEPLOYMENT_ID;
|
|
181
191
|
const headers = {
|
|
182
192
|
"Cache-Control": "private, no-cache, no-store, max-age=0, must-revalidate",
|
|
@@ -192,18 +202,15 @@ function writeGsspRedirect(res, redirect, isDataReq, props) {
|
|
|
192
202
|
const dataHeaders = { "Content-Type": "application/json" };
|
|
193
203
|
if (deploymentId) dataHeaders[NEXTJS_DEPLOYMENT_ID_HEADER] = deploymentId;
|
|
194
204
|
res.writeHead(200, dataHeaders);
|
|
195
|
-
res.end(JSON.stringify({
|
|
196
|
-
...props,
|
|
197
|
-
pageProps: {
|
|
198
|
-
...isUnknownRecord(props.pageProps) ? props.pageProps : {},
|
|
199
|
-
__N_REDIRECT: dest,
|
|
200
|
-
__N_REDIRECT_STATUS: status
|
|
201
|
-
}
|
|
202
|
-
}));
|
|
205
|
+
res.end(JSON.stringify({ ...redirectProps }));
|
|
203
206
|
return;
|
|
204
207
|
}
|
|
205
|
-
|
|
206
|
-
res.
|
|
208
|
+
const location = resolvePagesRedirectLocation(resolved, options.basePath);
|
|
209
|
+
res.writeHead(resolved.statusCode, {
|
|
210
|
+
Location: location,
|
|
211
|
+
...resolved.statusCode === 308 ? { Refresh: `0;url=${location}` } : {}
|
|
212
|
+
});
|
|
213
|
+
res.end(location);
|
|
207
214
|
}
|
|
208
215
|
/** Body placeholder used to split the document shell for streaming. */
|
|
209
216
|
const STREAM_BODY_MARKER = "<!--VINEXT_STREAM_BODY-->";
|
|
@@ -221,7 +228,7 @@ const STREAM_BODY_MARKER = "<!--VINEXT_STREAM_BODY-->";
|
|
|
221
228
|
* shell sooner).
|
|
222
229
|
*/
|
|
223
230
|
async function streamPageToResponse(res, element, options) {
|
|
224
|
-
const { url, server, fontHeadHTML, assetHeadHTML = "", scripts, DocumentComponent, statusCode, extraHeaders, getHeadHTML, enhancePageElement, scriptNonce, documentContext, setDocumentInitialHead, bufferBodyBeforeHeaders = false } = options;
|
|
231
|
+
const { url, server, fontHeadHTML, assetHeadHTML = "", scripts, DocumentComponent, statusCode, extraHeaders, getHeadHTML, enhancePageElement, scriptNonce, documentContext, setDocumentInitialHead, crossOrigin, bufferBodyBeforeHeaders = false } = options;
|
|
225
232
|
const documentRenderPage = await runDocumentRenderPage({
|
|
226
233
|
DocumentComponent,
|
|
227
234
|
enhancePageElement,
|
|
@@ -244,26 +251,46 @@ async function streamPageToResponse(res, element, options) {
|
|
|
244
251
|
let headHTML = getHeadHTML();
|
|
245
252
|
if (documentRenderPage.status === "rendered" && documentRenderPage.stylesHTML) headHTML += `\n ${documentRenderPage.stylesHTML}`;
|
|
246
253
|
let shellTemplate;
|
|
254
|
+
let documentAssetProps = {};
|
|
255
|
+
const protectedAssetMarker = `data-vinext-document-asset-props-protected-${randomUUID()}`;
|
|
256
|
+
const protectAssetTags = (html) => markDocumentAssetPropsProtectedTags(html, protectedAssetMarker);
|
|
257
|
+
const applyGeneratedAssetProps = (html, props, scriptOwner) => protectAssetTags(applyDocumentAssetProps(html, props, {
|
|
258
|
+
configuredCrossOrigin: crossOrigin,
|
|
259
|
+
scriptOwner
|
|
260
|
+
}));
|
|
247
261
|
if (DocumentComponent) {
|
|
248
262
|
const docProps = documentRenderPage.status === "skipped" ? await loadUserDocumentInitialProps(DocumentComponent) : documentRenderPage.docProps;
|
|
249
|
-
|
|
263
|
+
const renderedDocument = extractDocumentAssetProps(await renderToStringAsync(docProps ? React.createElement(DocumentComponent, docProps) : React.createElement(DocumentComponent)));
|
|
264
|
+
documentAssetProps = renderedDocument.props;
|
|
265
|
+
let docHtml = protectAssetTags(renderedDocument.html);
|
|
266
|
+
const generatedScripts = applyGeneratedAssetProps(scripts, renderedDocument.props, "next-script");
|
|
267
|
+
const generatedAssetHeadHTML = applyGeneratedAssetProps(assetHeadHTML, renderedDocument.props, "next-script");
|
|
250
268
|
docHtml = docHtml.replace("__NEXT_MAIN__", STREAM_BODY_MARKER);
|
|
251
|
-
if (headHTML || fontHeadHTML ||
|
|
252
|
-
docHtml = docHtml.replace("<!-- __NEXT_SCRIPTS__ -->",
|
|
253
|
-
if (!docHtml.includes("__NEXT_DATA__")) docHtml = docHtml.replace("</body>", ` ${
|
|
269
|
+
if (headHTML || fontHeadHTML || generatedAssetHeadHTML) docHtml = docHtml.replace("</head>", ` ${protectAssetTags(fontHeadHTML)}${protectAssetTags(headHTML)}\n ${generatedAssetHeadHTML}\n</head>`);
|
|
270
|
+
docHtml = docHtml.replace("<!-- __NEXT_SCRIPTS__ -->", generatedScripts);
|
|
271
|
+
if (!docHtml.includes("__NEXT_DATA__")) docHtml = docHtml.replace("</body>", ` ${generatedScripts}\n</body>`);
|
|
254
272
|
shellTemplate = docHtml;
|
|
255
|
-
} else
|
|
273
|
+
} else {
|
|
274
|
+
const generatedScripts = applyGeneratedAssetProps(scripts, {}, "next-script");
|
|
275
|
+
const generatedAssetHeadHTML = applyGeneratedAssetProps(assetHeadHTML, {}, "next-script");
|
|
276
|
+
shellTemplate = `<!DOCTYPE html>
|
|
256
277
|
<html>
|
|
257
278
|
<head>
|
|
258
|
-
${fontHeadHTML}${headHTML}
|
|
259
|
-
${
|
|
279
|
+
${protectAssetTags(fontHeadHTML)}${protectAssetTags(headHTML)}
|
|
280
|
+
${generatedAssetHeadHTML}
|
|
260
281
|
</head>
|
|
261
282
|
<body>
|
|
262
283
|
<div id="__next">${STREAM_BODY_MARKER}</div>
|
|
263
|
-
${
|
|
284
|
+
${generatedScripts}
|
|
264
285
|
</body>
|
|
265
286
|
</html>`;
|
|
266
|
-
|
|
287
|
+
}
|
|
288
|
+
let transformedShell = await server.transformIndexHtml(url, shellTemplate);
|
|
289
|
+
transformedShell = stripDocumentAssetPropsProtectionMarkers(applyDocumentAssetProps(transformedShell, documentAssetProps, {
|
|
290
|
+
configuredCrossOrigin: crossOrigin,
|
|
291
|
+
protectedAssetMarker,
|
|
292
|
+
scriptOwner: "next-script"
|
|
293
|
+
}), protectedAssetMarker);
|
|
267
294
|
const markerIdx = transformedShell.indexOf(STREAM_BODY_MARKER);
|
|
268
295
|
const prefix = transformedShell.slice(0, markerIdx);
|
|
269
296
|
const suffix = transformedShell.slice(markerIdx + 25);
|
|
@@ -324,7 +351,7 @@ function parseCookieLocale(req, i18nConfig) {
|
|
|
324
351
|
* 4. Render the component to HTML
|
|
325
352
|
* 5. Wrap in _document shell and send response
|
|
326
353
|
*/
|
|
327
|
-
function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatcher, basePath = "", trailingSlash = false, hasMiddleware = false, hasRewrites = false, clientTraceMetadata, htmlLimitedBots, reactStrictMode = false) {
|
|
354
|
+
function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatcher, basePath = "", trailingSlash = false, hasMiddleware = false, hasRewrites = false, clientTraceMetadata, htmlLimitedBots, reactStrictMode = false, expireTime = PAGES_CACHE_ONE_YEAR_SECONDS, crossOrigin) {
|
|
328
355
|
const matcher = fileMatcher ?? createValidFileMatcher();
|
|
329
356
|
const pagePatterns = routes.map((r) => patternToNextFormat(r.pattern));
|
|
330
357
|
const _alsRegistration = Promise.all([runner.import("vinext/head-state"), runner.import("vinext/router-state")]);
|
|
@@ -350,22 +377,25 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
350
377
|
let locale;
|
|
351
378
|
let localeStrippedUrl = url;
|
|
352
379
|
let currentDefaultLocale;
|
|
353
|
-
let currentDomainLocaleDomain;
|
|
354
380
|
const domainLocales = i18nConfig?.domains;
|
|
355
381
|
if (i18nConfig) {
|
|
356
382
|
const resolved = resolvePagesI18nRequest(url, i18nConfig, req.headers, req.headers.host, basePath, trailingSlash);
|
|
357
383
|
locale = resolved.locale;
|
|
358
384
|
localeStrippedUrl = resolved.url;
|
|
359
385
|
currentDefaultLocale = resolved.domainLocale?.defaultLocale ?? i18nConfig.defaultLocale;
|
|
360
|
-
currentDomainLocaleDomain = resolved.domainLocale?.domain;
|
|
361
386
|
if (resolved.redirectUrl) {
|
|
362
387
|
res.writeHead(307, { Location: resolved.redirectUrl });
|
|
363
388
|
res.end();
|
|
364
389
|
return;
|
|
365
390
|
}
|
|
366
391
|
}
|
|
367
|
-
const
|
|
368
|
-
|
|
392
|
+
const errorPageContext = {
|
|
393
|
+
basePath,
|
|
394
|
+
locale: locale ?? currentDefaultLocale,
|
|
395
|
+
locales: i18nConfig?.locales,
|
|
396
|
+
defaultLocale: currentDefaultLocale,
|
|
397
|
+
crossOrigin
|
|
398
|
+
};
|
|
369
399
|
const match = matchRoute(localeStrippedUrl, routes);
|
|
370
400
|
if (!match) {
|
|
371
401
|
if (isDataReq) {
|
|
@@ -377,9 +407,13 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
377
407
|
res.end("{}");
|
|
378
408
|
return;
|
|
379
409
|
}
|
|
380
|
-
|
|
410
|
+
const requestContext = createRequestContext();
|
|
411
|
+
const closeRequest = () => void closeAfterResponse(requestContext);
|
|
412
|
+
res.on("finish", closeRequest);
|
|
413
|
+
res.on("close", closeRequest);
|
|
414
|
+
await runWithRequestContext(requestContext, async () => {
|
|
381
415
|
await _alsRegistration;
|
|
382
|
-
await renderErrorPage(server, runner, req, res, url, pagesDir, 404, void 0, matcher, void 0, reactStrictMode);
|
|
416
|
+
await renderErrorPage(server, runner, req, res, url, pagesDir, 404, void 0, matcher, void 0, reactStrictMode, errorPageContext);
|
|
383
417
|
});
|
|
384
418
|
return;
|
|
385
419
|
}
|
|
@@ -391,7 +425,11 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
391
425
|
let requestAsPath = isDataReq ? gsspResolvedUrl : i18nConfig ? extractLocaleFromUrl$1(originalUrl, i18nConfig, locale).url : originalUrl;
|
|
392
426
|
const userFacingParams = route.isDynamic ? params : null;
|
|
393
427
|
let query = mergeRouteParamsIntoQuery(parseQueryString(url), params);
|
|
394
|
-
|
|
428
|
+
const requestContext = createRequestContext();
|
|
429
|
+
const closeRequest = () => void closeAfterResponse(requestContext);
|
|
430
|
+
res.on("finish", closeRequest);
|
|
431
|
+
res.on("close", closeRequest);
|
|
432
|
+
return runWithRequestContext(requestContext, async () => {
|
|
395
433
|
ensureFetchPatch();
|
|
396
434
|
try {
|
|
397
435
|
await _alsRegistration;
|
|
@@ -419,10 +457,8 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
419
457
|
};
|
|
420
458
|
const requestPreviewData = requestPreview.data;
|
|
421
459
|
let AppComponent = null;
|
|
422
|
-
const
|
|
423
|
-
if (
|
|
424
|
-
AppComponent = (await importModule(runner, appPath)).default ?? null;
|
|
425
|
-
} catch {}
|
|
460
|
+
const appFilePath = findFileWithExts(pagesDir, "_app", matcher);
|
|
461
|
+
if (appFilePath) AppComponent = (await importModule(runner, appFilePath)).default ?? null;
|
|
426
462
|
const pagesNextData = {
|
|
427
463
|
...buildPagesReadinessNextData({
|
|
428
464
|
pageModule,
|
|
@@ -472,10 +508,9 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
472
508
|
let pageProps = {};
|
|
473
509
|
let renderProps = { pageProps };
|
|
474
510
|
if (requestPreviewData !== false) renderProps.__N_PREVIEW = true;
|
|
475
|
-
let
|
|
511
|
+
let isOnDemandRevalidate = false;
|
|
512
|
+
let staticPropsRevalidateSeconds = false;
|
|
476
513
|
let isFallbackRender = false;
|
|
477
|
-
let shouldPersistFallbackData = false;
|
|
478
|
-
let staticPropsPreviewData = requestPreviewData;
|
|
479
514
|
if (typeof pageModule.getStaticPaths === "function" && route.isDynamic) {
|
|
480
515
|
const pathsResult = await pageModule.getStaticPaths({
|
|
481
516
|
locales: i18nConfig?.locales ?? [],
|
|
@@ -491,17 +526,17 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
491
526
|
const notFoundHeaders = { "Content-Type": "application/json" };
|
|
492
527
|
if (deploymentId) notFoundHeaders[NEXTJS_DEPLOYMENT_ID_HEADER] = deploymentId;
|
|
493
528
|
res.writeHead(404, notFoundHeaders);
|
|
494
|
-
res.end("{}");
|
|
529
|
+
res.end("{\"notFound\":true}");
|
|
495
530
|
return;
|
|
496
531
|
}
|
|
497
|
-
await renderErrorPage(server, runner, req, res, url, pagesDir, 404, routerShim.wrapWithRouterContext, matcher, void 0, reactStrictMode);
|
|
532
|
+
await renderErrorPage(server, runner, req, res, url, pagesDir, 404, routerShim.wrapWithRouterContext, matcher, void 0, reactStrictMode, errorPageContext);
|
|
498
533
|
return;
|
|
499
534
|
}
|
|
500
535
|
const userAgentHeader = req.headers["user-agent"];
|
|
501
536
|
const userAgent = Array.isArray(userAgentHeader) ? userAgentHeader[0] : userAgentHeader;
|
|
502
537
|
const isBotRequest = !!userAgent && isBotUserAgent(userAgent, htmlLimitedBots);
|
|
503
538
|
if (fallback === true && !isValidPath && !isDataReq && !isBotRequest && requestPreviewData === false) {
|
|
504
|
-
isFallbackRender =
|
|
539
|
+
isFallbackRender = true;
|
|
505
540
|
if (isFallbackRender && typeof routerShim.setSSRContext === "function") routerShim.setSSRContext({
|
|
506
541
|
pathname: patternToNextFormat(route.pattern),
|
|
507
542
|
query: {},
|
|
@@ -514,7 +549,6 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
514
549
|
isFallback: true
|
|
515
550
|
});
|
|
516
551
|
}
|
|
517
|
-
shouldPersistFallbackData = fallback === true && !isValidPath && isDataReq;
|
|
518
552
|
}
|
|
519
553
|
const gsspExtraHeaders = {};
|
|
520
554
|
const hasAppGetInitialProps = hasPagesGetInitialProps(AppComponent);
|
|
@@ -526,7 +560,6 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
526
560
|
const appTree = React.createElement(AppComponent, {
|
|
527
561
|
...appTreeProps,
|
|
528
562
|
Component: PageComponent,
|
|
529
|
-
pageProps: appTreeProps.pageProps,
|
|
530
563
|
router: routerShim.default
|
|
531
564
|
});
|
|
532
565
|
return typeof routerShim.wrapWithRouterContext === "function" ? routerShim.wrapWithRouterContext(appTree) : appTree;
|
|
@@ -577,17 +610,18 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
577
610
|
const result = await pageModule.getServerSideProps(context);
|
|
578
611
|
if (res.writableEnded) return;
|
|
579
612
|
if (result && "props" in result) {
|
|
580
|
-
pageProps =
|
|
581
|
-
...pageProps,
|
|
582
|
-
...await Promise.resolve(result.props)
|
|
583
|
-
};
|
|
613
|
+
pageProps = mergePagesDataProps(renderProps.pageProps, await Promise.resolve(result.props));
|
|
584
614
|
renderProps = {
|
|
585
615
|
...renderProps,
|
|
586
616
|
pageProps
|
|
587
617
|
};
|
|
588
618
|
}
|
|
589
619
|
if (result && "redirect" in result) {
|
|
590
|
-
writeGsspRedirect(res, result.redirect, isDataReq, renderProps
|
|
620
|
+
writeGsspRedirect(res, result.redirect, isDataReq, renderProps, {
|
|
621
|
+
basePath,
|
|
622
|
+
method: "getServerSideProps",
|
|
623
|
+
routeUrl: url
|
|
624
|
+
});
|
|
591
625
|
return;
|
|
592
626
|
}
|
|
593
627
|
if (result && "notFound" in result && result.notFound) {
|
|
@@ -597,10 +631,10 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
597
631
|
const notFoundHeaders = { "Content-Type": "application/json" };
|
|
598
632
|
if (deploymentId) notFoundHeaders[NEXTJS_DEPLOYMENT_ID_HEADER] = deploymentId;
|
|
599
633
|
res.writeHead(404, notFoundHeaders);
|
|
600
|
-
res.end("{}");
|
|
634
|
+
res.end("{\"notFound\":true}");
|
|
601
635
|
return;
|
|
602
636
|
}
|
|
603
|
-
await renderErrorPage(server, runner, req, res, url, pagesDir, 404, routerShim.wrapWithRouterContext, void 0, void 0, reactStrictMode);
|
|
637
|
+
await renderErrorPage(server, runner, req, res, url, pagesDir, 404, routerShim.wrapWithRouterContext, void 0, void 0, reactStrictMode, errorPageContext);
|
|
604
638
|
return;
|
|
605
639
|
}
|
|
606
640
|
if (result && "props" in result) isSerializableProps(patternToNextFormat(route.pattern), "getServerSideProps", pageProps);
|
|
@@ -616,216 +650,19 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
616
650
|
}
|
|
617
651
|
const responseHeaders = typeof res.getHeaders === "function" ? res.getHeaders() : void 0;
|
|
618
652
|
const scriptNonce = getScriptNonceFromNodeHeaderSources(req.headers, responseHeaders);
|
|
619
|
-
let earlyFontLinkHeader = "";
|
|
620
|
-
try {
|
|
621
|
-
const earlyPreloads = [];
|
|
622
|
-
const fontGoogleEarly = await importModule(runner, "next/font/google");
|
|
623
|
-
if (typeof fontGoogleEarly.getSSRFontPreloads === "function") earlyPreloads.push(...fontGoogleEarly.getSSRFontPreloads());
|
|
624
|
-
const fontLocalEarly = await importModule(runner, "next/font/local");
|
|
625
|
-
if (typeof fontLocalEarly.getSSRFontPreloads === "function") earlyPreloads.push(...fontLocalEarly.getSSRFontPreloads());
|
|
626
|
-
if (earlyPreloads.length > 0) earlyFontLinkHeader = earlyPreloads.map((p) => `<${p.href}>; rel=preload; as=font; type=${p.type}; crossorigin`).join(", ");
|
|
627
|
-
} catch {}
|
|
628
653
|
if (typeof pageModule.getStaticProps === "function" && !isFallbackRender) {
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
654
|
+
isOnDemandRevalidate = isOnDemandRevalidateRequest(req.headers[PRERENDER_REVALIDATE_HEADER]);
|
|
655
|
+
if (isOnDemandRevalidate && req.headers["x-prerender-revalidate-if-generated"] !== void 0) {
|
|
656
|
+
res.writeHead(404, { [NEXTJS_CACHE_HEADER]: "REVALIDATED" });
|
|
657
|
+
res.end("This page could not be found");
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
632
660
|
const previewData = requestPreviewData;
|
|
633
|
-
staticPropsPreviewData = previewData;
|
|
634
661
|
const previewContext = previewData === false ? {} : {
|
|
635
662
|
draftMode: true,
|
|
636
663
|
preview: true,
|
|
637
664
|
previewData
|
|
638
665
|
};
|
|
639
|
-
if (!isOnDemandRevalidate && cached && !cached.isStale && cached.value.value?.kind === "PAGES" && !cached.value.value.generatedFromDataRequest && !scriptNonce && !isDataReq && previewData === false) {
|
|
640
|
-
const cachedHtml = cached.value.value.html;
|
|
641
|
-
const transformedHtml = await server.transformIndexHtml(url, cachedHtml);
|
|
642
|
-
const { cacheControl: hitCacheControl } = decideIsr({
|
|
643
|
-
cacheState: "HIT",
|
|
644
|
-
kind: "dev",
|
|
645
|
-
revalidateSeconds: getRevalidateDuration(cacheKey) ?? 60
|
|
646
|
-
});
|
|
647
|
-
const hitHeaders = {
|
|
648
|
-
"Content-Type": "text/html; charset=utf-8",
|
|
649
|
-
...buildCacheStateHeaders("HIT"),
|
|
650
|
-
"Cache-Control": hitCacheControl
|
|
651
|
-
};
|
|
652
|
-
if (earlyFontLinkHeader) hitHeaders["Link"] = earlyFontLinkHeader;
|
|
653
|
-
res.writeHead(200, hitHeaders);
|
|
654
|
-
res.end(transformedHtml);
|
|
655
|
-
return;
|
|
656
|
-
}
|
|
657
|
-
if (!isOnDemandRevalidate && cached && cached.isStale && cached.value.value?.kind === "PAGES" && !cached.value.value.generatedFromDataRequest && !scriptNonce && !isDataReq && previewData === false) {
|
|
658
|
-
const cachedHtml = cached.value.value.html;
|
|
659
|
-
const transformedHtml = await server.transformIndexHtml(url, cachedHtml);
|
|
660
|
-
triggerBackgroundRegeneration(cacheKey, async () => {
|
|
661
|
-
return runWithRequestContext(createRequestContext({
|
|
662
|
-
executionContext: null,
|
|
663
|
-
ssrContext: {
|
|
664
|
-
pathname: patternToNextFormat(route.pattern),
|
|
665
|
-
query,
|
|
666
|
-
asPath: requestAsPath,
|
|
667
|
-
navigationIsReady,
|
|
668
|
-
locale: locale ?? currentDefaultLocale,
|
|
669
|
-
locales: i18nConfig?.locales,
|
|
670
|
-
defaultLocale: currentDefaultLocale
|
|
671
|
-
},
|
|
672
|
-
i18nContext: i18nConfig ? {
|
|
673
|
-
locale: locale ?? currentDefaultLocale,
|
|
674
|
-
locales: i18nConfig.locales,
|
|
675
|
-
defaultLocale: currentDefaultLocale,
|
|
676
|
-
domainLocales,
|
|
677
|
-
hostname: req.headers.host?.split(":", 1)[0]
|
|
678
|
-
} : null
|
|
679
|
-
}), async () => {
|
|
680
|
-
ensureFetchPatch();
|
|
681
|
-
let freshPageProps = {};
|
|
682
|
-
let freshRenderProps = { pageProps: freshPageProps };
|
|
683
|
-
let RegenApp = null;
|
|
684
|
-
const appPath = path.join(pagesDir, "_app");
|
|
685
|
-
if (findFileWithExtensions(appPath, matcher)) try {
|
|
686
|
-
RegenApp = (await runner.import(appPath)).default ?? null;
|
|
687
|
-
} catch {}
|
|
688
|
-
if (RegenApp && hasPagesGetInitialProps(RegenApp)) {
|
|
689
|
-
const regenReq = {
|
|
690
|
-
url: req.url,
|
|
691
|
-
headers: req.headers,
|
|
692
|
-
method: req.method
|
|
693
|
-
};
|
|
694
|
-
const regenRes = {
|
|
695
|
-
headersSent: false,
|
|
696
|
-
writableEnded: false,
|
|
697
|
-
statusCode: 200,
|
|
698
|
-
getHeaders() {
|
|
699
|
-
return {};
|
|
700
|
-
}
|
|
701
|
-
};
|
|
702
|
-
const initialProps = await loadPagesGetInitialProps(RegenApp, {
|
|
703
|
-
AppTree: (appTreeProps) => {
|
|
704
|
-
const appTree = React.createElement(RegenApp, {
|
|
705
|
-
...appTreeProps,
|
|
706
|
-
Component: pageModule.default,
|
|
707
|
-
pageProps: appTreeProps.pageProps,
|
|
708
|
-
router: routerShim.default
|
|
709
|
-
});
|
|
710
|
-
return typeof routerShim.wrapWithRouterContext === "function" ? routerShim.wrapWithRouterContext(appTree) : appTree;
|
|
711
|
-
},
|
|
712
|
-
Component: pageModule.default,
|
|
713
|
-
router: routerShim.default,
|
|
714
|
-
ctx: {
|
|
715
|
-
req: regenReq,
|
|
716
|
-
res: regenRes,
|
|
717
|
-
pathname: patternToNextFormat(route.pattern),
|
|
718
|
-
query,
|
|
719
|
-
asPath: requestAsPath,
|
|
720
|
-
locale: locale ?? currentDefaultLocale,
|
|
721
|
-
locales: i18nConfig?.locales,
|
|
722
|
-
defaultLocale: currentDefaultLocale
|
|
723
|
-
}
|
|
724
|
-
});
|
|
725
|
-
if (regenRes.headersSent || regenRes.writableEnded) return;
|
|
726
|
-
if (initialProps) {
|
|
727
|
-
freshRenderProps = initialProps;
|
|
728
|
-
freshPageProps = isUnknownRecord(initialProps.pageProps) ? initialProps.pageProps : {};
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
const freshResult = await pageModule.getStaticProps({
|
|
732
|
-
params: userFacingParams,
|
|
733
|
-
locale: locale ?? currentDefaultLocale,
|
|
734
|
-
locales: i18nConfig?.locales,
|
|
735
|
-
defaultLocale: currentDefaultLocale,
|
|
736
|
-
revalidateReason: "stale"
|
|
737
|
-
});
|
|
738
|
-
if (freshResult && "props" in freshResult) {
|
|
739
|
-
const revalidate = typeof freshResult.revalidate === "number" ? freshResult.revalidate : cached.value.cacheControl?.revalidate ?? 0;
|
|
740
|
-
if (revalidate > 0) {
|
|
741
|
-
freshPageProps = {
|
|
742
|
-
...freshPageProps,
|
|
743
|
-
...freshResult.props
|
|
744
|
-
};
|
|
745
|
-
freshRenderProps = {
|
|
746
|
-
...freshRenderProps,
|
|
747
|
-
pageProps: freshPageProps
|
|
748
|
-
};
|
|
749
|
-
if (typeof routerShim.setSSRContext === "function") routerShim.setSSRContext({
|
|
750
|
-
pathname: patternToNextFormat(route.pattern),
|
|
751
|
-
query,
|
|
752
|
-
asPath: requestAsPath,
|
|
753
|
-
navigationIsReady,
|
|
754
|
-
locale: locale ?? currentDefaultLocale,
|
|
755
|
-
locales: i18nConfig?.locales,
|
|
756
|
-
defaultLocale: currentDefaultLocale,
|
|
757
|
-
domainLocales
|
|
758
|
-
});
|
|
759
|
-
if (i18nConfig) {
|
|
760
|
-
await runner.import("vinext/i18n-state");
|
|
761
|
-
const i18nCtx = await importModule(runner, "vinext/i18n-context");
|
|
762
|
-
if (typeof i18nCtx.setI18nContext === "function") i18nCtx.setI18nContext({
|
|
763
|
-
locale: locale ?? currentDefaultLocale,
|
|
764
|
-
locales: i18nConfig.locales,
|
|
765
|
-
defaultLocale: currentDefaultLocale,
|
|
766
|
-
domainLocales,
|
|
767
|
-
hostname: req.headers.host?.split(":", 1)[0]
|
|
768
|
-
});
|
|
769
|
-
}
|
|
770
|
-
let el = RegenApp ? React.createElement(RegenApp, {
|
|
771
|
-
...freshRenderProps,
|
|
772
|
-
Component: pageModule.default,
|
|
773
|
-
pageProps: freshRenderProps.pageProps,
|
|
774
|
-
router: routerShim.default
|
|
775
|
-
}) : React.createElement(pageModule.default, freshPageProps);
|
|
776
|
-
if (routerShim.wrapWithRouterContext) el = routerShim.wrapWithRouterContext(el);
|
|
777
|
-
const freshBody = await renderIsrPassToStringAsync(withScriptNonce(el, scriptNonce));
|
|
778
|
-
const viteRoot = server.config.root;
|
|
779
|
-
const viteBase = server.config.base;
|
|
780
|
-
const regenPageUrl = createPagesDevModuleUrl(viteRoot, route.filePath, viteBase);
|
|
781
|
-
const regenAppUrl = RegenApp ? createPagesDevModuleUrl(viteRoot, path.join(pagesDir, "_app"), viteBase) : null;
|
|
782
|
-
const freshPagesNextData = {
|
|
783
|
-
...pagesNextData,
|
|
784
|
-
__vinext: {
|
|
785
|
-
...pagesNextData.__vinext,
|
|
786
|
-
pageModuleUrl: regenPageUrl,
|
|
787
|
-
appModuleUrl: regenAppUrl,
|
|
788
|
-
hasMiddleware,
|
|
789
|
-
routeUrl: requestAsPath
|
|
790
|
-
}
|
|
791
|
-
};
|
|
792
|
-
const freshHtml = `<!DOCTYPE html><html><head></head><body><div id="__next">${freshBody}</div>${`<script id="__NEXT_DATA__" type="application/json">${safeJsonStringify({
|
|
793
|
-
props: freshRenderProps,
|
|
794
|
-
page: patternToNextFormat(route.pattern),
|
|
795
|
-
query: params,
|
|
796
|
-
buildId: process.env.__VINEXT_BUILD_ID,
|
|
797
|
-
isFallback: false,
|
|
798
|
-
locale: locale ?? currentDefaultLocale,
|
|
799
|
-
locales: i18nConfig?.locales,
|
|
800
|
-
defaultLocale: currentDefaultLocale,
|
|
801
|
-
domainLocales,
|
|
802
|
-
...freshPagesNextData
|
|
803
|
-
})}<\/script>`}\n ${cachedHtml.match(/<script type="module">[\s\S]*?<\/script>/)?.[0] ?? ""}</body></html>`;
|
|
804
|
-
await isrSet(cacheKey, buildPagesCacheValue(freshHtml, freshRenderProps), revalidate);
|
|
805
|
-
setRevalidateDuration(cacheKey, revalidate);
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
});
|
|
809
|
-
}, {
|
|
810
|
-
routerKind: "Pages Router",
|
|
811
|
-
routePath: route.pattern,
|
|
812
|
-
routeType: "render"
|
|
813
|
-
});
|
|
814
|
-
const { cacheControl: staleCacheControl } = decideIsr({
|
|
815
|
-
cacheState: "STALE",
|
|
816
|
-
kind: "dev",
|
|
817
|
-
revalidateSeconds: getRevalidateDuration(cacheKey) ?? 60
|
|
818
|
-
});
|
|
819
|
-
const staleHeaders = {
|
|
820
|
-
"Content-Type": "text/html; charset=utf-8",
|
|
821
|
-
...buildCacheStateHeaders("STALE"),
|
|
822
|
-
"Cache-Control": staleCacheControl
|
|
823
|
-
};
|
|
824
|
-
if (earlyFontLinkHeader) staleHeaders["Link"] = earlyFontLinkHeader;
|
|
825
|
-
res.writeHead(200, staleHeaders);
|
|
826
|
-
res.end(transformedHtml);
|
|
827
|
-
return;
|
|
828
|
-
}
|
|
829
666
|
const context = {
|
|
830
667
|
params: userFacingParams,
|
|
831
668
|
locale: locale ?? currentDefaultLocale,
|
|
@@ -834,43 +671,47 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
834
671
|
revalidateReason: isOnDemandRevalidate ? "on-demand" : "stale",
|
|
835
672
|
...previewContext
|
|
836
673
|
};
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
const
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
pageProps = isUnknownRecord(renderProps.pageProps) ? renderProps.pageProps : {};
|
|
843
|
-
}
|
|
674
|
+
if (await loadAppInitialProps()) return;
|
|
675
|
+
const result = await pageModule.getStaticProps(context);
|
|
676
|
+
const routePattern = patternToNextFormat(route.pattern);
|
|
677
|
+
assertPages404DoesNotReturnNotFound(routePattern, result);
|
|
678
|
+
if (result) staticPropsRevalidateSeconds = resolvePagesRevalidateSeconds(result, routePattern);
|
|
844
679
|
if (result && "props" in result) {
|
|
845
|
-
pageProps =
|
|
846
|
-
...pageProps,
|
|
847
|
-
...await Promise.resolve(result.props)
|
|
848
|
-
};
|
|
680
|
+
pageProps = mergePagesDataProps(renderProps.pageProps, await Promise.resolve(result.props));
|
|
849
681
|
renderProps = {
|
|
850
682
|
...renderProps,
|
|
851
683
|
pageProps
|
|
852
684
|
};
|
|
853
685
|
}
|
|
854
686
|
if (result && "redirect" in result) {
|
|
855
|
-
|
|
687
|
+
if (previewData === false) resolvePagesRedirect(result.redirect, {
|
|
688
|
+
method: "getStaticProps",
|
|
689
|
+
routeUrl: url,
|
|
690
|
+
sanitizeDestination
|
|
691
|
+
});
|
|
692
|
+
applyDevPagesCacheHeaders(res, isOnDemandRevalidate ? "REVALIDATED" : "HIT", buildDevPagesTerminalCacheControl(staticPropsRevalidateSeconds, expireTime));
|
|
693
|
+
writeGsspRedirect(res, result.redirect, isDataReq, renderProps, {
|
|
694
|
+
basePath,
|
|
695
|
+
method: "getStaticProps",
|
|
696
|
+
routeUrl: url
|
|
697
|
+
});
|
|
856
698
|
return;
|
|
857
699
|
}
|
|
858
700
|
if (result && "notFound" in result && result.notFound) {
|
|
701
|
+
applyDevPagesCacheHeaders(res, isOnDemandRevalidate ? "REVALIDATED" : "HIT", isDataReq ? buildDevPagesTerminalCacheControl(staticPropsRevalidateSeconds, expireTime) : DEV_PAGES_CACHE_CONTROL);
|
|
859
702
|
applyDevPagesPreviewResponse(res, requestPreview);
|
|
860
703
|
if (isDataReq) {
|
|
861
704
|
const deploymentId = process.env.__VINEXT_DEPLOYMENT_ID || process.env.NEXT_DEPLOYMENT_ID;
|
|
862
705
|
const notFoundHeaders = { "Content-Type": "application/json" };
|
|
863
706
|
if (deploymentId) notFoundHeaders[NEXTJS_DEPLOYMENT_ID_HEADER] = deploymentId;
|
|
864
707
|
res.writeHead(404, notFoundHeaders);
|
|
865
|
-
res.end("{}");
|
|
708
|
+
res.end("{\"notFound\":true}");
|
|
866
709
|
return;
|
|
867
710
|
}
|
|
868
|
-
await renderErrorPage(server, runner, req, res, url, pagesDir, 404, routerShim.wrapWithRouterContext, void 0, void 0, reactStrictMode);
|
|
711
|
+
await renderErrorPage(server, runner, req, res, url, pagesDir, 404, routerShim.wrapWithRouterContext, void 0, void 0, reactStrictMode, errorPageContext);
|
|
869
712
|
return;
|
|
870
713
|
}
|
|
871
|
-
if (result && "props" in result) isSerializableProps(
|
|
872
|
-
if (previewData === false && typeof result?.revalidate === "number" && result.revalidate > 0) isrRevalidateSeconds = result.revalidate;
|
|
873
|
-
else if (previewData === false && cached?.value.value?.kind === "PAGES" && cached.value.value.generatedFromDataRequest) isrRevalidateSeconds = cached.value.cacheControl?.revalidate ?? 31536e3;
|
|
714
|
+
if (result && "props" in result) isSerializableProps(routePattern, "getStaticProps", pageProps);
|
|
874
715
|
}
|
|
875
716
|
if (typeof pageModule.getServerSideProps !== "function" && typeof pageModule.getStaticProps !== "function" && hasAppGetInitialProps) {
|
|
876
717
|
if (await loadAppInitialProps()) return;
|
|
@@ -899,20 +740,11 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
899
740
|
}
|
|
900
741
|
}
|
|
901
742
|
if (isDataReq) {
|
|
902
|
-
if (shouldPersistFallbackData && staticPropsPreviewData === false) {
|
|
903
|
-
const cacheKey = pagesIsrCacheKey(url.split("?")[0]);
|
|
904
|
-
const revalidateSeconds = isrRevalidateSeconds ?? 31536e3;
|
|
905
|
-
await isrSet(cacheKey, {
|
|
906
|
-
kind: "PAGES",
|
|
907
|
-
html: "",
|
|
908
|
-
pageData: renderProps,
|
|
909
|
-
generatedFromDataRequest: true,
|
|
910
|
-
headers: void 0,
|
|
911
|
-
status: void 0
|
|
912
|
-
}, revalidateSeconds);
|
|
913
|
-
setRevalidateDuration(cacheKey, revalidateSeconds);
|
|
914
|
-
}
|
|
915
743
|
const dataHeaders = { "Content-Type": "application/json" };
|
|
744
|
+
if (typeof pageModule.getStaticProps === "function") {
|
|
745
|
+
dataHeaders["Cache-Control"] = DEV_PAGES_CACHE_CONTROL;
|
|
746
|
+
dataHeaders[NEXTJS_CACHE_HEADER] = isOnDemandRevalidate ? "REVALIDATED" : "HIT";
|
|
747
|
+
}
|
|
916
748
|
if ((statusCode ?? 200) === 200) dataHeaders["x-nextjs-matched-path"] = `${locale ? `/${locale}` : ""}${patternToNextFormat(route.pattern)}`;
|
|
917
749
|
if (gsspExtraHeaders) for (const [k, v] of Object.entries(gsspExtraHeaders)) dataHeaders[k] = v;
|
|
918
750
|
applyDevPagesPreviewHeaders(dataHeaders, requestPreview);
|
|
@@ -932,7 +764,6 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
932
764
|
if (AppComponent) element = createElement(AppComponent, {
|
|
933
765
|
...renderProps,
|
|
934
766
|
Component: PageComponent,
|
|
935
|
-
pageProps: renderProps.pageProps,
|
|
936
767
|
router: routerShim.default
|
|
937
768
|
});
|
|
938
769
|
else element = createElement(PageComponent, pageProps);
|
|
@@ -943,7 +774,8 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
943
774
|
if (typeof dynamicShim.flushPreloads === "function") await dynamicShim.flushPreloads();
|
|
944
775
|
const nonceAttr = createNonceAttribute(scriptNonce);
|
|
945
776
|
let fontHeadHTML = "";
|
|
946
|
-
const
|
|
777
|
+
const appAssetPath = AppComponent ? appFilePath : null;
|
|
778
|
+
const assetHeadHTML = await collectDevInitialStylesheetHeadHTML(server, runner, [appAssetPath, route.filePath], nonceAttr);
|
|
947
779
|
const allFontStyles = [];
|
|
948
780
|
const allFontPreloads = [];
|
|
949
781
|
try {
|
|
@@ -966,15 +798,15 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
966
798
|
for (const { href, type } of allFontPreloads) {
|
|
967
799
|
const safeHref = href.replace(/&/g, "&").replace(/"/g, """);
|
|
968
800
|
const safeType = type.replace(/&/g, "&").replace(/"/g, """);
|
|
969
|
-
fontHeadHTML += `<link rel="preload"${nonceAttr} href="${safeHref}" as="font" type="${safeType}" crossorigin />\n `;
|
|
801
|
+
fontHeadHTML += `<link rel="preload"${nonceAttr} href="${safeHref}" as="font" type="${safeType}" crossorigin="anonymous" />\n `;
|
|
970
802
|
}
|
|
971
803
|
if (allFontStyles.length > 0) fontHeadHTML += `<style data-vinext-fonts${nonceAttr}>${allFontStyles.join("\n")}</style>\n `;
|
|
972
804
|
const viteRoot = server.config.root;
|
|
973
805
|
const viteBase = server.config.base;
|
|
974
806
|
const pageModuleUrl = createPagesDevModuleUrl(viteRoot, route.filePath, viteBase);
|
|
975
807
|
const pageModuleSource = createPagesDevModuleUrl(viteRoot, route.filePath, "/");
|
|
976
|
-
const appModuleUrl =
|
|
977
|
-
const appModuleSource =
|
|
808
|
+
const appModuleUrl = appAssetPath ? createPagesDevModuleUrl(viteRoot, appAssetPath, viteBase) : null;
|
|
809
|
+
const appModuleSource = appAssetPath ? createPagesDevModuleUrl(viteRoot, appAssetPath, "/") : null;
|
|
978
810
|
const serializedPagesNextData = {
|
|
979
811
|
...pagesNextData,
|
|
980
812
|
__vinext: {
|
|
@@ -1004,17 +836,14 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
1004
836
|
domainLocales,
|
|
1005
837
|
...serializedPagesNextData
|
|
1006
838
|
})}<\/script>`;
|
|
1007
|
-
const
|
|
839
|
+
const docFilePath = findFileWithExts(pagesDir, "_document", matcher);
|
|
1008
840
|
let DocumentComponent = null;
|
|
1009
|
-
if (
|
|
1010
|
-
DocumentComponent = (await runner.import(docPath)).default ?? null;
|
|
1011
|
-
} catch {}
|
|
841
|
+
if (docFilePath) DocumentComponent = (await runner.import(docFilePath)).default ?? null;
|
|
1012
842
|
const allScripts = `${nextDataScript}\n ${createInlineScriptTag(`window.__VINEXT_PAGE_PATTERNS__=${safeJsonStringify(pagePatterns)}`, scriptNonce)}\n ${hydrationScript}`;
|
|
1013
843
|
const extraHeaders = { ...gsspExtraHeaders };
|
|
1014
|
-
if (
|
|
1015
|
-
|
|
1016
|
-
extraHeaders[
|
|
1017
|
-
Object.assign(extraHeaders, buildCacheStateHeaders("MISS"));
|
|
844
|
+
if (typeof pageModule.getStaticProps === "function") {
|
|
845
|
+
extraHeaders["Cache-Control"] = DEV_PAGES_CACHE_CONTROL;
|
|
846
|
+
extraHeaders[NEXTJS_CACHE_HEADER] = isFallbackRender ? "MISS" : isOnDemandRevalidate ? "REVALIDATED" : "HIT";
|
|
1018
847
|
}
|
|
1019
848
|
applyDevPagesPreviewHeaders(extraHeaders, requestPreview);
|
|
1020
849
|
if (allFontPreloads.length > 0) extraHeaders["Link"] = allFontPreloads.map((p) => `<${p.href}>; rel=preload; as=font; type=${p.type}; crossorigin`).join(", ");
|
|
@@ -1046,7 +875,7 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
1046
875
|
if (FinalApp) enhancedElement = createElement(FinalApp, {
|
|
1047
876
|
...renderProps,
|
|
1048
877
|
Component: FinalComp,
|
|
1049
|
-
|
|
878
|
+
router: routerShim.default
|
|
1050
879
|
});
|
|
1051
880
|
else enhancedElement = createElement(FinalComp, pageProps);
|
|
1052
881
|
if (wrapWithRouterContext) enhancedElement = wrapWithRouterContext(enhancedElement);
|
|
@@ -1058,22 +887,11 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
1058
887
|
return traceHTML ? `${headHTML}\n ${traceHTML}` : headHTML;
|
|
1059
888
|
},
|
|
1060
889
|
setDocumentInitialHead: typeof headShim.setDocumentInitialHead === "function" ? headShim.setDocumentInitialHead : void 0,
|
|
890
|
+
crossOrigin,
|
|
1061
891
|
bufferBodyBeforeHeaders: true
|
|
1062
892
|
});
|
|
1063
893
|
_renderEnd = now();
|
|
1064
894
|
if (typeof routerShim.setSSRContext === "function") routerShim.setSSRContext(null);
|
|
1065
|
-
if (!scriptNonce && isrRevalidateSeconds !== null && isrRevalidateSeconds > 0) {
|
|
1066
|
-
let isrElement = AppComponent ? createElement(AppComponent, {
|
|
1067
|
-
...renderProps,
|
|
1068
|
-
Component: pageModule.default,
|
|
1069
|
-
pageProps
|
|
1070
|
-
}) : createElement(pageModule.default, pageProps);
|
|
1071
|
-
if (wrapWithRouterContext) isrElement = wrapWithRouterContext(isrElement);
|
|
1072
|
-
const isrHtml = `<!DOCTYPE html><html><head>${assetHeadHTML}</head><body><div id="__next">${await renderIsrPassToStringAsync(withScriptNonce(isrElement, scriptNonce))}</div>${allScripts}</body></html>`;
|
|
1073
|
-
const cacheKey = pagesIsrCacheKey(url.split("?")[0]);
|
|
1074
|
-
await isrSet(cacheKey, buildPagesCacheValue(isrHtml, pageProps), isrRevalidateSeconds);
|
|
1075
|
-
setRevalidateDuration(cacheKey, isrRevalidateSeconds);
|
|
1076
|
-
}
|
|
1077
895
|
} catch (e) {
|
|
1078
896
|
console.error(e);
|
|
1079
897
|
reportRequestError(e instanceof Error ? e : new Error(String(e)), {
|
|
@@ -1086,7 +904,7 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
1086
904
|
routeType: "render"
|
|
1087
905
|
}).catch(() => {});
|
|
1088
906
|
try {
|
|
1089
|
-
await renderErrorPage(server, runner, req, res, url, pagesDir, 500, void 0, matcher, e instanceof Error ? e : new Error(String(e)), reactStrictMode);
|
|
907
|
+
await renderErrorPage(server, runner, req, res, url, pagesDir, 500, void 0, matcher, e instanceof Error ? e : new Error(String(e)), reactStrictMode, errorPageContext);
|
|
1090
908
|
} catch (fallbackErr) {
|
|
1091
909
|
res.statusCode = 500;
|
|
1092
910
|
res.end(`Internal Server Error: ${fallbackErr.message}`);
|
|
@@ -1103,23 +921,24 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
1103
921
|
* - 500: pages/500.tsx -> pages/_error.tsx -> default
|
|
1104
922
|
* - other: pages/_error.tsx -> default
|
|
1105
923
|
*/
|
|
1106
|
-
async function renderErrorPage(server, runner, req, res, url, pagesDir, statusCode, wrapWithRouterContext, fileMatcher, err, reactStrictMode = false) {
|
|
924
|
+
async function renderErrorPage(server, runner, req, res, url, pagesDir, statusCode, wrapWithRouterContext, fileMatcher, err, reactStrictMode = false, context = { basePath: "" }) {
|
|
1107
925
|
attachPagesRequestCookies(req);
|
|
1108
926
|
const matcher = fileMatcher ?? createValidFileMatcher();
|
|
1109
927
|
const candidates = statusCode === 404 ? ["404", "_error"] : statusCode === 500 ? ["500", "_error"] : ["_error"];
|
|
1110
928
|
for (const candidate of candidates) {
|
|
1111
929
|
let errorRouterShim = null;
|
|
930
|
+
let candidateLoaded = false;
|
|
931
|
+
let errorAssetPath = null;
|
|
1112
932
|
try {
|
|
1113
|
-
|
|
933
|
+
errorAssetPath = findFileWithExts(pagesDir, candidate, matcher);
|
|
1114
934
|
if (!errorAssetPath && candidate !== "_error") continue;
|
|
1115
|
-
const
|
|
935
|
+
const errorModule = await importModule(runner, errorAssetPath ?? "next/error");
|
|
936
|
+
candidateLoaded = true;
|
|
937
|
+
const ErrorComponent = errorModule.default;
|
|
1116
938
|
if (!ErrorComponent) continue;
|
|
1117
939
|
let AppComponent = null;
|
|
1118
|
-
const appPathErr = path.join(pagesDir, "_app");
|
|
1119
940
|
const appAssetPath = findFileWithExts(pagesDir, "_app", matcher);
|
|
1120
|
-
if (
|
|
1121
|
-
AppComponent = (await importModule(runner, appAssetPath ?? appPathErr)).default ?? null;
|
|
1122
|
-
} catch {}
|
|
941
|
+
if (appAssetPath) AppComponent = (await importModule(runner, appAssetPath)).default ?? null;
|
|
1123
942
|
const createElement = React.createElement;
|
|
1124
943
|
res.statusCode = statusCode;
|
|
1125
944
|
const errorPage = candidate === "_error" ? "/_error" : `/${candidate}`;
|
|
@@ -1146,10 +965,36 @@ async function renderErrorPage(server, runner, req, res, url, pagesDir, statusCo
|
|
|
1146
965
|
asPath: url
|
|
1147
966
|
});
|
|
1148
967
|
if (res.headersSent || res.writableEnded) return;
|
|
1149
|
-
|
|
968
|
+
let errorProps = {
|
|
1150
969
|
...initialErrorProps,
|
|
1151
970
|
statusCode
|
|
1152
971
|
};
|
|
972
|
+
if (typeof errorModule.getStaticProps === "function") {
|
|
973
|
+
const isOnDemandRevalidate = isOnDemandRevalidateRequest(req.headers[PRERENDER_REVALIDATE_HEADER]);
|
|
974
|
+
const staticResult = await errorModule.getStaticProps({
|
|
975
|
+
locale: context.locale,
|
|
976
|
+
locales: context.locales,
|
|
977
|
+
defaultLocale: context.defaultLocale,
|
|
978
|
+
revalidateReason: isOnDemandRevalidate ? "on-demand" : "stale"
|
|
979
|
+
});
|
|
980
|
+
assertPages404DoesNotReturnNotFound(errorPage, staticResult);
|
|
981
|
+
if (staticResult?.redirect) {
|
|
982
|
+
applyDevPagesCacheHeaders(res, isOnDemandRevalidate ? "REVALIDATED" : "HIT", NEVER_CACHE_CONTROL);
|
|
983
|
+
writeGsspRedirect(res, staticResult.redirect, false, { pageProps: errorProps }, {
|
|
984
|
+
basePath: context.basePath,
|
|
985
|
+
method: "getStaticProps",
|
|
986
|
+
routeUrl: url
|
|
987
|
+
});
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
990
|
+
if (staticResult?.props !== void 0) {
|
|
991
|
+
const staticProps = await Promise.resolve(staticResult.props);
|
|
992
|
+
isSerializableProps(errorPage, "getStaticProps", staticProps);
|
|
993
|
+
errorProps = mergePagesDataProps(errorProps, staticProps);
|
|
994
|
+
}
|
|
995
|
+
if (staticResult) resolvePagesRevalidateSeconds(staticResult, errorPage);
|
|
996
|
+
applyDevPagesCacheHeaders(res, isOnDemandRevalidate ? "REVALIDATED" : "HIT");
|
|
997
|
+
}
|
|
1153
998
|
let renderProps;
|
|
1154
999
|
if (AppComponent && hasPagesGetInitialProps(AppComponent)) {
|
|
1155
1000
|
const appInitialProps = await loadPagesGetInitialProps(AppComponent, {
|
|
@@ -1173,13 +1018,15 @@ async function renderErrorPage(server, runner, req, res, url, pagesDir, statusCo
|
|
|
1173
1018
|
}
|
|
1174
1019
|
});
|
|
1175
1020
|
if (res.headersSent || res.writableEnded) return;
|
|
1176
|
-
|
|
1021
|
+
const appRenderProps = appInitialProps ?? {};
|
|
1022
|
+
renderProps = Object.hasOwn(appRenderProps, "pageProps") ? {
|
|
1023
|
+
...appRenderProps,
|
|
1024
|
+
pageProps: mergePagesDataProps(appRenderProps.pageProps, errorProps)
|
|
1025
|
+
} : appRenderProps;
|
|
1177
1026
|
} else renderProps = { pageProps: errorProps };
|
|
1178
1027
|
let DocumentComponent = null;
|
|
1179
|
-
const
|
|
1180
|
-
if (
|
|
1181
|
-
DocumentComponent = (await importModule(runner, docPathErr)).default ?? null;
|
|
1182
|
-
} catch {}
|
|
1028
|
+
const docFilePathErr = findFileWithExts(pagesDir, "_document", matcher);
|
|
1029
|
+
if (docFilePathErr) DocumentComponent = (await importModule(runner, docFilePathErr)).default ?? null;
|
|
1183
1030
|
const createErrorElement = (FinalApp, FinalComponent) => {
|
|
1184
1031
|
let errorElement = FinalApp ? createElement(FinalApp, {
|
|
1185
1032
|
...renderProps,
|
|
@@ -1237,9 +1084,14 @@ async function renderErrorPage(server, runner, req, res, url, pagesDir, statusCo
|
|
|
1237
1084
|
return createErrorElement(FinalApp, FinalComponent);
|
|
1238
1085
|
},
|
|
1239
1086
|
getHeadHTML: () => typeof headShim.getSSRHeadHTML === "function" ? headShim.getSSRHeadHTML() : "",
|
|
1240
|
-
setDocumentInitialHead: typeof headShim.setDocumentInitialHead === "function" ? headShim.setDocumentInitialHead : void 0
|
|
1087
|
+
setDocumentInitialHead: typeof headShim.setDocumentInitialHead === "function" ? headShim.setDocumentInitialHead : void 0,
|
|
1088
|
+
crossOrigin: context.crossOrigin
|
|
1241
1089
|
});
|
|
1242
1090
|
else {
|
|
1091
|
+
const bodyHtml = await renderToStringAsync(element);
|
|
1092
|
+
const protectedAssetMarker = `data-vinext-document-asset-props-protected-${randomUUID()}`;
|
|
1093
|
+
const protectAssetTags = (assetHtml) => markDocumentAssetPropsProtectedTags(assetHtml, protectedAssetMarker);
|
|
1094
|
+
const protectedErrorScripts = protectAssetTags(applyDocumentAssetProps(errorScripts, {}, { configuredCrossOrigin: context.crossOrigin }));
|
|
1243
1095
|
const html = `<!DOCTYPE html>
|
|
1244
1096
|
<html>
|
|
1245
1097
|
<head>
|
|
@@ -1248,17 +1100,21 @@ async function renderErrorPage(server, runner, req, res, url, pagesDir, statusCo
|
|
|
1248
1100
|
${assetHeadHTML}
|
|
1249
1101
|
</head>
|
|
1250
1102
|
<body>
|
|
1251
|
-
<div id="__next">${
|
|
1252
|
-
${
|
|
1103
|
+
<div id="__next">${protectAssetTags(bodyHtml)}</div>
|
|
1104
|
+
${protectedErrorScripts}
|
|
1253
1105
|
</body>
|
|
1254
1106
|
</html>`;
|
|
1255
|
-
const transformedHtml = await server.transformIndexHtml(url, html)
|
|
1107
|
+
const transformedHtml = stripDocumentAssetPropsProtectionMarkers(applyDocumentAssetProps(await server.transformIndexHtml(url, html), {}, {
|
|
1108
|
+
configuredCrossOrigin: context.crossOrigin,
|
|
1109
|
+
protectedAssetMarker
|
|
1110
|
+
}), protectedAssetMarker);
|
|
1256
1111
|
res.writeHead(statusCode, { "Content-Type": "text/html; charset=utf-8" });
|
|
1257
1112
|
res.end(transformedHtml);
|
|
1258
1113
|
}
|
|
1259
1114
|
return;
|
|
1260
|
-
} catch {
|
|
1115
|
+
} catch (error) {
|
|
1261
1116
|
if (res.headersSent || res.writableEnded) return;
|
|
1117
|
+
if (errorAssetPath || candidateLoaded) throw error;
|
|
1262
1118
|
continue;
|
|
1263
1119
|
} finally {
|
|
1264
1120
|
if (typeof errorRouterShim?.setSSRContext === "function") errorRouterShim.setSSRContext(null);
|