vinext 0.1.2 → 0.1.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/dist/build/client-build-config.d.ts +11 -2
- package/dist/build/client-build-config.js +17 -6
- package/dist/build/prerender.d.ts +9 -1
- package/dist/build/prerender.js +42 -12
- package/dist/build/run-prerender.d.ts +10 -2
- package/dist/build/run-prerender.js +15 -1
- package/dist/client/app-nav-failure-handler.d.ts +8 -0
- package/dist/client/app-nav-failure-handler.js +44 -0
- package/dist/client/pages-router-link-navigation.d.ts +33 -7
- package/dist/client/pages-router-link-navigation.js +32 -2
- package/dist/client/vinext-next-data.d.ts +18 -1
- package/dist/client/vinext-next-data.js +2 -0
- package/dist/client/window-next.d.ts +2 -1
- package/dist/client/window-next.js +12 -1
- package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
- package/dist/config/config-matchers.d.ts +11 -1
- package/dist/config/config-matchers.js +87 -16
- package/dist/config/next-config.d.ts +46 -4
- package/dist/config/next-config.js +147 -48
- package/dist/config/tsconfig-paths.js +14 -1
- package/dist/deploy.d.ts +30 -11
- package/dist/deploy.js +200 -112
- package/dist/entries/app-browser-entry.d.ts +9 -3
- package/dist/entries/app-browser-entry.js +21 -3
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +65 -5
- package/dist/entries/app-rsc-manifest.js +2 -0
- package/dist/entries/app-ssr-entry.js +1 -1
- package/dist/entries/pages-client-entry.js +66 -20
- package/dist/entries/pages-server-entry.js +47 -31
- package/dist/index.js +417 -102
- package/dist/plugins/dynamic-preload-metadata.js +2 -4
- package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
- package/dist/plugins/extensionless-dynamic-import.js +152 -0
- package/dist/plugins/fonts.js +5 -4
- package/dist/plugins/optimize-imports.d.ts +2 -1
- package/dist/plugins/optimize-imports.js +11 -9
- package/dist/plugins/postcss.js +7 -7
- package/dist/plugins/strip-server-exports.d.ts +9 -7
- package/dist/plugins/strip-server-exports.js +493 -46
- package/dist/plugins/typeof-window.d.ts +14 -0
- package/dist/plugins/typeof-window.js +150 -0
- package/dist/routing/app-route-graph.d.ts +2 -1
- package/dist/routing/app-route-graph.js +46 -16
- package/dist/routing/file-matcher.d.ts +10 -1
- package/dist/routing/file-matcher.js +22 -1
- package/dist/routing/pages-router.js +3 -3
- package/dist/routing/utils.d.ts +35 -6
- package/dist/routing/utils.js +59 -7
- package/dist/server/api-handler.d.ts +6 -1
- package/dist/server/api-handler.js +21 -15
- package/dist/server/app-browser-action-result.d.ts +19 -6
- package/dist/server/app-browser-action-result.js +20 -11
- package/dist/server/app-browser-entry.js +175 -91
- package/dist/server/app-browser-error.d.ts +10 -6
- package/dist/server/app-browser-error.js +43 -8
- package/dist/server/app-browser-hydration.d.ts +2 -0
- package/dist/server/app-browser-hydration.js +1 -0
- package/dist/server/app-browser-navigation-controller.d.ts +5 -3
- package/dist/server/app-browser-navigation-controller.js +23 -2
- package/dist/server/app-browser-server-action-navigation.d.ts +6 -0
- package/dist/server/app-browser-server-action-navigation.js +9 -0
- package/dist/server/app-browser-state.d.ts +1 -1
- package/dist/server/app-browser-state.js +19 -11
- package/dist/server/app-browser-stream.js +86 -43
- package/dist/server/app-browser-visible-commit.d.ts +1 -1
- package/dist/server/app-elements-wire.d.ts +6 -1
- package/dist/server/app-elements-wire.js +14 -4
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-fallback-renderer.d.ts +1 -0
- package/dist/server/app-fallback-renderer.js +3 -1
- package/dist/server/app-optimistic-routing.js +2 -2
- package/dist/server/app-page-boundary-render.d.ts +1 -0
- package/dist/server/app-page-boundary-render.js +27 -14
- package/dist/server/app-page-cache-render.d.ts +53 -0
- package/dist/server/app-page-cache-render.js +91 -0
- package/dist/server/app-page-cache.d.ts +16 -2
- package/dist/server/app-page-cache.js +62 -1
- package/dist/server/app-page-dispatch.d.ts +26 -0
- package/dist/server/app-page-dispatch.js +149 -92
- package/dist/server/app-page-element-builder.d.ts +1 -0
- package/dist/server/app-page-element-builder.js +5 -2
- package/dist/server/app-page-execution.d.ts +6 -1
- package/dist/server/app-page-execution.js +21 -1
- package/dist/server/app-page-probe.d.ts +1 -0
- package/dist/server/app-page-probe.js +4 -0
- package/dist/server/app-page-render-observation.d.ts +3 -1
- package/dist/server/app-page-render-observation.js +17 -1
- package/dist/server/app-page-render.d.ts +12 -1
- package/dist/server/app-page-render.js +42 -4
- package/dist/server/app-page-request.d.ts +2 -0
- package/dist/server/app-page-request.js +2 -1
- package/dist/server/app-page-route-wiring.d.ts +3 -1
- package/dist/server/app-page-route-wiring.js +14 -5
- package/dist/server/app-page-stream.d.ts +15 -3
- package/dist/server/app-page-stream.js +11 -5
- package/dist/server/app-pages-bridge.d.ts +23 -1
- package/dist/server/app-pages-bridge.js +26 -17
- package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
- package/dist/server/app-ppr-fallback-shell-render.js +26 -0
- package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
- package/dist/server/app-ppr-fallback-shell.js +8 -1
- package/dist/server/app-route-handler-dispatch.js +9 -2
- package/dist/server/app-route-handler-policy.d.ts +1 -0
- package/dist/server/app-router-entry.js +5 -0
- package/dist/server/app-rsc-cache-busting.js +2 -0
- package/dist/server/app-rsc-handler.d.ts +28 -0
- package/dist/server/app-rsc-handler.js +195 -59
- package/dist/server/app-rsc-route-matching.d.ts +3 -0
- package/dist/server/app-rsc-route-matching.js +8 -2
- package/dist/server/app-segment-config.d.ts +9 -1
- package/dist/server/app-segment-config.js +12 -3
- package/dist/server/app-server-action-execution.d.ts +1 -0
- package/dist/server/app-server-action-execution.js +47 -15
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +84 -39
- package/dist/server/before-interactive-head.d.ts +17 -0
- package/dist/server/before-interactive-head.js +35 -0
- package/dist/server/cache-control.js +4 -0
- package/dist/server/csp.js +1 -4
- package/dist/server/dev-server.d.ts +2 -2
- package/dist/server/dev-server.js +321 -83
- package/dist/server/hybrid-route-priority.d.ts +22 -0
- package/dist/server/hybrid-route-priority.js +33 -0
- package/dist/server/image-optimization.d.ts +18 -9
- package/dist/server/image-optimization.js +37 -23
- package/dist/server/implicit-tags.d.ts +2 -1
- package/dist/server/implicit-tags.js +4 -1
- package/dist/server/middleware-matcher.js +12 -3
- package/dist/server/middleware-runtime.d.ts +3 -4
- package/dist/server/middleware-runtime.js +2 -0
- package/dist/server/navigation-planner.d.ts +135 -41
- package/dist/server/navigation-planner.js +138 -0
- package/dist/server/navigation-trace.d.ts +9 -1
- package/dist/server/navigation-trace.js +9 -1
- package/dist/server/operation-token.d.ts +40 -0
- package/dist/server/operation-token.js +85 -0
- package/dist/server/pages-api-route.d.ts +6 -0
- package/dist/server/pages-api-route.js +13 -2
- package/dist/server/pages-asset-tags.d.ts +2 -1
- package/dist/server/pages-asset-tags.js +6 -2
- package/dist/server/pages-data-route.d.ts +9 -2
- package/dist/server/pages-data-route.js +18 -6
- package/dist/server/pages-dev-module-url.d.ts +4 -0
- package/dist/server/pages-dev-module-url.js +15 -0
- package/dist/server/pages-document-initial-props.d.ts +4 -15
- package/dist/server/pages-document-initial-props.js +27 -56
- package/dist/server/pages-get-initial-props.d.ts +54 -4
- package/dist/server/pages-get-initial-props.js +43 -1
- package/dist/server/pages-i18n.js +2 -2
- package/dist/server/pages-node-compat.js +2 -2
- package/dist/server/pages-page-data.d.ts +11 -2
- package/dist/server/pages-page-data.js +207 -34
- package/dist/server/pages-page-handler.d.ts +4 -2
- package/dist/server/pages-page-handler.js +62 -23
- package/dist/server/pages-page-response.d.ts +4 -1
- package/dist/server/pages-page-response.js +11 -8
- package/dist/server/pages-readiness.js +1 -1
- package/dist/server/pages-request-pipeline.d.ts +8 -7
- package/dist/server/pages-request-pipeline.js +126 -47
- package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
- package/dist/server/pregenerated-concrete-paths.js +2 -19
- package/dist/server/prerender-manifest.d.ts +33 -0
- package/dist/server/prerender-manifest.js +54 -0
- package/dist/server/prerender-route-params.d.ts +1 -2
- package/dist/server/prod-server.d.ts +3 -1
- package/dist/server/prod-server.js +50 -13
- package/dist/server/request-pipeline.d.ts +3 -15
- package/dist/server/request-pipeline.js +58 -47
- package/dist/server/rsc-stream-hints.d.ts +5 -1
- package/dist/server/rsc-stream-hints.js +6 -1
- package/dist/server/seed-cache.js +10 -18
- package/dist/server/static-file-cache.js +16 -4
- package/dist/shims/app-router-scroll-state.d.ts +3 -1
- package/dist/shims/app-router-scroll-state.js +14 -2
- package/dist/shims/app-router-scroll.d.ts +3 -0
- package/dist/shims/app-router-scroll.js +28 -18
- package/dist/shims/before-interactive-context.d.ts +14 -3
- package/dist/shims/cache-runtime.js +3 -2
- package/dist/shims/cache.d.ts +1 -0
- package/dist/shims/cache.js +1 -1
- package/dist/shims/cdn-cache.d.ts +5 -5
- package/dist/shims/document.d.ts +15 -20
- package/dist/shims/document.js +5 -8
- package/dist/shims/dynamic-preload-chunks.js +6 -4
- package/dist/shims/error-boundary.d.ts +2 -0
- package/dist/shims/error-boundary.js +7 -0
- package/dist/shims/error.js +3 -2
- package/dist/shims/error.react-server.d.ts +9 -0
- package/dist/shims/error.react-server.js +6 -0
- package/dist/shims/fetch-cache.d.ts +3 -1
- package/dist/shims/fetch-cache.js +45 -20
- package/dist/shims/hash-scroll.js +6 -1
- package/dist/shims/headers.js +29 -4
- package/dist/shims/image.js +9 -2
- package/dist/shims/internal/als-registry.js +28 -1
- package/dist/shims/internal/app-route-detection.js +8 -17
- package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
- package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
- package/dist/shims/internal/navigation-untracked.d.ts +35 -0
- package/dist/shims/internal/navigation-untracked.js +55 -0
- package/dist/shims/internal/pages-data-fetch-dedup.d.ts +6 -7
- package/dist/shims/internal/pages-data-fetch-dedup.js +67 -14
- package/dist/shims/internal/pages-data-target.d.ts +7 -2
- package/dist/shims/internal/pages-data-target.js +17 -8
- package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
- package/dist/shims/internal/pages-router-accessor.js +13 -0
- package/dist/shims/internal/router-context.d.ts +2 -1
- package/dist/shims/internal/router-context.js +3 -1
- package/dist/shims/link.js +47 -19
- package/dist/shims/metadata.js +4 -4
- package/dist/shims/navigation.d.ts +8 -2
- package/dist/shims/navigation.js +63 -31
- package/dist/shims/ppr-fallback-shell.d.ts +5 -1
- package/dist/shims/ppr-fallback-shell.js +28 -7
- package/dist/shims/router.d.ts +18 -3
- package/dist/shims/router.js +512 -142
- package/dist/shims/script.js +8 -4
- package/dist/shims/server.d.ts +16 -1
- package/dist/shims/server.js +44 -12
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/utils/built-asset-url.d.ts +4 -0
- package/dist/utils/built-asset-url.js +11 -0
- package/dist/utils/commonjs-loader.d.ts +16 -0
- package/dist/utils/commonjs-loader.js +100 -0
- package/dist/utils/deployment-id.d.ts +8 -0
- package/dist/utils/deployment-id.js +22 -0
- package/dist/utils/has-trailing-comma.d.ts +24 -0
- package/dist/utils/has-trailing-comma.js +62 -0
- package/dist/utils/html-limited-bots.d.ts +18 -1
- package/dist/utils/html-limited-bots.js +23 -1
- package/dist/utils/parse-cookie.d.ts +13 -0
- package/dist/utils/parse-cookie.js +52 -0
- package/dist/utils/path.d.ts +7 -1
- package/dist/utils/path.js +9 -1
- package/dist/utils/text-stream.d.ts +1 -1
- package/dist/utils/text-stream.js +2 -2
- package/dist/utils/vite-version.d.ts +12 -1
- package/dist/utils/vite-version.js +9 -1
- package/package.json +2 -2
- package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
- package/dist/shims/internal/parse-cookie-header.js +0 -30
|
@@ -5,8 +5,9 @@ import { fnv1a52 } from "../utils/hash.js";
|
|
|
5
5
|
import { encodeCacheTag } from "../utils/encode-cache-tag.js";
|
|
6
6
|
import { NEVER_CACHE_CONTROL, NO_STORE_CACHE_CONTROL, applyCdnResponseHeaders } from "./cache-control.js";
|
|
7
7
|
import { buildMissIsrCacheControl } from "./isr-decision.js";
|
|
8
|
+
import { appendAssetDeploymentIdQuery } from "../utils/deployment-id.js";
|
|
8
9
|
import { withScriptNonce } from "../shims/script-nonce-context.js";
|
|
9
|
-
import {
|
|
10
|
+
import { createNonceAttribute, escapeHtmlAttr } from "./html.js";
|
|
10
11
|
import { getClientTraceMetadataHTML } from "./client-trace-metadata.js";
|
|
11
12
|
import { readStreamAsText } from "../utils/text-stream.js";
|
|
12
13
|
import { loadUserDocumentInitialProps, runDocumentRenderPage } from "./pages-document-initial-props.js";
|
|
@@ -62,14 +63,14 @@ function requestsNoCache(cacheControl) {
|
|
|
62
63
|
function buildPagesFontHeadHtml(fontLinks, fontPreloads, fontStyles, scriptNonce) {
|
|
63
64
|
let html = "";
|
|
64
65
|
const nonceAttr = createNonceAttribute(scriptNonce);
|
|
65
|
-
for (const link of fontLinks) html += `<link rel="stylesheet"${nonceAttr} href="${escapeHtmlAttr(link)}" />\n `;
|
|
66
|
-
for (const preload of fontPreloads) html += `<link rel="preload"${nonceAttr} href="${escapeHtmlAttr(preload.href)}" as="font" type="${escapeHtmlAttr(preload.type)}" crossorigin />\n `;
|
|
66
|
+
for (const link of fontLinks) html += `<link rel="stylesheet"${nonceAttr} href="${escapeHtmlAttr(appendAssetDeploymentIdQuery(link))}" />\n `;
|
|
67
|
+
for (const preload of fontPreloads) html += `<link rel="preload"${nonceAttr} href="${escapeHtmlAttr(appendAssetDeploymentIdQuery(preload.href))}" as="font" type="${escapeHtmlAttr(preload.type)}" crossorigin />\n `;
|
|
67
68
|
if (fontStyles.length > 0) html += `<style data-vinext-fonts${nonceAttr}>${fontStyles.join("\n")}</style>\n `;
|
|
68
69
|
return html;
|
|
69
70
|
}
|
|
70
71
|
function buildPagesNextDataScript(options) {
|
|
71
72
|
const nextDataPayload = {
|
|
72
|
-
props: { pageProps: options.pageProps },
|
|
73
|
+
props: options.props ?? { pageProps: options.pageProps },
|
|
73
74
|
page: options.routePattern,
|
|
74
75
|
query: options.params,
|
|
75
76
|
buildId: options.buildId,
|
|
@@ -88,8 +89,7 @@ function buildPagesNextDataScript(options) {
|
|
|
88
89
|
...options.nextData?.__vinext,
|
|
89
90
|
...options.vinext
|
|
90
91
|
};
|
|
91
|
-
|
|
92
|
-
return createInlineScriptTag(`window.__NEXT_DATA__ = ${options.safeJsonStringify(nextDataPayload)}${localeGlobals}`, options.scriptNonce);
|
|
92
|
+
return `<script id="__NEXT_DATA__" type="application/json"${createNonceAttribute(options.scriptNonce)}>${options.safeJsonStringify(nextDataPayload)}<\/script>`;
|
|
93
93
|
}
|
|
94
94
|
async function buildPagesShellHtml(bodyMarker, fontHeadHTML, nextDataScript, options) {
|
|
95
95
|
if (options.DocumentComponent) {
|
|
@@ -171,6 +171,7 @@ function applyGsspHeaders(headers, gsspRes, statusCode) {
|
|
|
171
171
|
return statusCode ?? gsspRes.statusCode;
|
|
172
172
|
}
|
|
173
173
|
async function renderPagesPageResponse(options) {
|
|
174
|
+
const renderProps = options.props ?? { pageProps: options.pageProps };
|
|
174
175
|
options.resetSSRHead?.();
|
|
175
176
|
await options.flushPreloads?.();
|
|
176
177
|
const fontHeadHTML = buildPagesFontHeadHtml(options.getFontLinks(), options.fontPreloads, options.getFontStyles(), options.scriptNonce);
|
|
@@ -179,6 +180,7 @@ async function renderPagesPageResponse(options) {
|
|
|
179
180
|
i18n: options.i18n,
|
|
180
181
|
isFallback: options.isFallback,
|
|
181
182
|
pageProps: options.pageProps,
|
|
183
|
+
props: renderProps,
|
|
182
184
|
params: options.params,
|
|
183
185
|
routePattern: options.routePattern,
|
|
184
186
|
safeJsonStringify: options.safeJsonStringify,
|
|
@@ -194,8 +196,9 @@ async function renderPagesPageResponse(options) {
|
|
|
194
196
|
renderStylesToString: async (element) => readStreamAsText(await options.renderToReadableStream(element)),
|
|
195
197
|
scriptNonce: options.scriptNonce,
|
|
196
198
|
context: {
|
|
199
|
+
err: options.err,
|
|
197
200
|
pathname: options.routePattern,
|
|
198
|
-
query: options.params,
|
|
201
|
+
query: options.query ?? options.params,
|
|
199
202
|
asPath: options.routeUrl
|
|
200
203
|
}
|
|
201
204
|
});
|
|
@@ -205,7 +208,7 @@ async function renderPagesPageResponse(options) {
|
|
|
205
208
|
controller.close();
|
|
206
209
|
} });
|
|
207
210
|
else {
|
|
208
|
-
const pageElement = withScriptNonce(React.createElement(React.Fragment, null, options.createPageElement(
|
|
211
|
+
const pageElement = withScriptNonce(React.createElement(React.Fragment, null, options.createPageElement(renderProps)), options.scriptNonce);
|
|
209
212
|
bodyStream = await options.renderToReadableStream(pageElement);
|
|
210
213
|
}
|
|
211
214
|
if (documentRenderPage.status === "skipped") await callDocumentGetInitialProps(options.DocumentComponent, options.setDocumentInitialHead);
|
|
@@ -10,7 +10,7 @@ function buildPagesReadinessNextData(options) {
|
|
|
10
10
|
const hasAppGip = typeof options.appComponent?.getInitialProps === "function";
|
|
11
11
|
return {
|
|
12
12
|
gssp: hasPageGssp,
|
|
13
|
-
gsp: hasPageGsp,
|
|
13
|
+
gsp: hasPageGsp ? true : void 0,
|
|
14
14
|
gip: hasPageGip,
|
|
15
15
|
appGip: hasAppGip,
|
|
16
16
|
autoExport: !hasPageGssp && !hasPageGsp && !hasPageGip && !hasAppGip,
|
|
@@ -5,7 +5,10 @@ import { HeaderRecord } from "./request-pipeline.js";
|
|
|
5
5
|
type PagesRenderOptions = {
|
|
6
6
|
isDataReq?: boolean;
|
|
7
7
|
renderErrorPageOnMiss?: boolean;
|
|
8
|
+
originalUrl?: string;
|
|
8
9
|
};
|
|
10
|
+
type FilesystemRoutePhase = "direct" | "beforeFiles" | "afterFiles" | "fallback";
|
|
11
|
+
declare function fetchWorkerFilesystemRoute(request: Request, requestPathname: string, phase: FilesystemRoutePhase, fetchAsset: (request: Request) => Promise<Response>): Promise<Response | false>;
|
|
9
12
|
type MiddlewareResult = {
|
|
10
13
|
continue: boolean;
|
|
11
14
|
redirectUrl?: string;
|
|
@@ -52,15 +55,13 @@ type PagesPipelineDeps = {
|
|
|
52
55
|
*/
|
|
53
56
|
proxyExternal?: ((currentRequest: Request, externalUrl: string) => Promise<Response>) | null;
|
|
54
57
|
/**
|
|
55
|
-
* Optional
|
|
58
|
+
* Optional filesystem/static-asset probe supplied by each runtime adapter.
|
|
56
59
|
* Called post-middleware (so middleware can intercept/redirect public files) with the
|
|
57
60
|
* original basePath-stripped pathname and the staged middleware response headers.
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* to fall through to rewrites/render. Worker/dev adapters omit this — their public files
|
|
61
|
-
* are served by the asset binding / Vite respectively.
|
|
61
|
+
* Node may write directly to `res` and return true; dev/Workers return a Response.
|
|
62
|
+
* Resolves false to continue through rewrites, API routes, and page rendering.
|
|
62
63
|
*/
|
|
63
|
-
|
|
64
|
+
serveFilesystemRoute?: ((requestPathname: string, stagedHeaders: HeaderRecord, phase: FilesystemRoutePhase) => Promise<boolean | Response>) | null;
|
|
64
65
|
};
|
|
65
66
|
/**
|
|
66
67
|
* Wrap an adapter's `runMiddleware` callback so middleware receives the original
|
|
@@ -110,4 +111,4 @@ type PagesPipelineResult = {
|
|
|
110
111
|
*/
|
|
111
112
|
declare function runPagesRequest(request: Request, deps: PagesPipelineDeps): Promise<PagesPipelineResult>;
|
|
112
113
|
//#endregion
|
|
113
|
-
export { MiddlewareResult, PagesPipelineDeps, PagesPipelineResult, PagesRenderOptions, runPagesRequest, wrapMiddlewareWithBasePath };
|
|
114
|
+
export { FilesystemRoutePhase, MiddlewareResult, PagesPipelineDeps, PagesPipelineResult, PagesRenderOptions, fetchWorkerFilesystemRoute, runPagesRequest, wrapMiddlewareWithBasePath };
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import { addBasePathToPathname, hasBasePath } from "../utils/base-path.js";
|
|
2
2
|
import { applyMiddlewareRequestHeaders, isExternalUrl, matchRedirect, matchRewrite, preserveRedirectDestinationQuery, proxyExternalRequest, requestContextFromRequest, sanitizeDestination } from "../config/config-matchers.js";
|
|
3
|
-
import { applyConfigHeadersToHeaderRecord, normalizeTrailingSlash } from "./request-pipeline.js";
|
|
3
|
+
import { applyConfigHeadersToHeaderRecord, cloneRequestWithUrl, normalizeTrailingSlash } from "./request-pipeline.js";
|
|
4
4
|
import { mergeRewriteQuery } from "../utils/query.js";
|
|
5
5
|
import { normalizeDefaultLocalePathname, stripI18nLocaleForApiRoute } from "./pages-i18n.js";
|
|
6
6
|
import { mergeHeaders } from "./worker-utils.js";
|
|
7
7
|
//#region src/server/pages-request-pipeline.ts
|
|
8
|
+
async function fetchWorkerFilesystemRoute(request, requestPathname, phase, fetchAsset) {
|
|
9
|
+
if (phase === "direct" || request.method !== "GET" && request.method !== "HEAD" || requestPathname === "/api" || requestPathname.startsWith("/api/")) return false;
|
|
10
|
+
const assetUrl = new URL(request.url);
|
|
11
|
+
assetUrl.pathname = requestPathname;
|
|
12
|
+
assetUrl.search = "";
|
|
13
|
+
const response = await fetchAsset(new Request(assetUrl, request));
|
|
14
|
+
return response.status === 404 ? false : response;
|
|
15
|
+
}
|
|
8
16
|
/**
|
|
9
17
|
* Wrap an adapter's `runMiddleware` callback so middleware receives the original
|
|
10
18
|
* (pre-basePath-stripping) URL. Adapters strip the basePath before handing the
|
|
@@ -68,9 +76,19 @@ async function runPagesRequest(request, deps) {
|
|
|
68
76
|
};
|
|
69
77
|
}
|
|
70
78
|
}
|
|
71
|
-
|
|
79
|
+
const originalResolvedUrl = pathname + search;
|
|
80
|
+
let resolvedUrl = originalResolvedUrl;
|
|
72
81
|
const middlewareHeaders = {};
|
|
73
82
|
let middlewareStatus;
|
|
83
|
+
const serveFilesystemRoute = async (requestPathname, phase) => {
|
|
84
|
+
if (!deps.serveFilesystemRoute) return null;
|
|
85
|
+
const served = await deps.serveFilesystemRoute(requestPathname, middlewareHeaders, phase);
|
|
86
|
+
if (served instanceof Response) return {
|
|
87
|
+
type: "response",
|
|
88
|
+
response: mergeHeaders(served, middlewareHeaders, middlewareStatus)
|
|
89
|
+
};
|
|
90
|
+
return served ? { type: "handled" } : null;
|
|
91
|
+
};
|
|
74
92
|
if (typeof deps.runMiddleware === "function") {
|
|
75
93
|
const result = await deps.runMiddleware(request, deps.ctx ?? null, { isDataRequest });
|
|
76
94
|
if (result.waitUntilPromises && result.waitUntilPromises.length > 0) {
|
|
@@ -114,7 +132,12 @@ async function runPagesRequest(request, deps) {
|
|
|
114
132
|
}
|
|
115
133
|
const { postMwReqCtx, request: postMwReq } = applyMiddlewareRequestHeaders(middlewareHeaders, request, { preserveCredentialHeaders: isExternalUrl(resolvedUrl) });
|
|
116
134
|
request = postMwReq;
|
|
117
|
-
|
|
135
|
+
const pathnameForResolvedUrl = (value) => value.split("#", 1)[0].split("?", 1)[0];
|
|
136
|
+
const rewriteRequestContext = () => ({
|
|
137
|
+
...postMwReqCtx,
|
|
138
|
+
query: new URL(resolvedUrl, url).searchParams
|
|
139
|
+
});
|
|
140
|
+
let resolvedPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
118
141
|
const matchResolvedPathname = (p) => i18nConfig ? normalizeDefaultLocalePathname(p, i18nConfig, { hostname: requestHostname }) : p;
|
|
119
142
|
if (configHeaders.length) applyConfigHeadersToHeaderRecord(middlewareHeaders, {
|
|
120
143
|
configHeaders,
|
|
@@ -126,22 +149,25 @@ async function runPagesRequest(request, deps) {
|
|
|
126
149
|
type: "response",
|
|
127
150
|
response: mergeHeaders(await proxyExternal(request, resolvedUrl), middlewareHeaders, void 0)
|
|
128
151
|
};
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
152
|
+
const directFilesystemResult = await serveFilesystemRoute(pathname, "direct");
|
|
153
|
+
if (directFilesystemResult) return directFilesystemResult;
|
|
132
154
|
let configRewriteFired = false;
|
|
133
|
-
|
|
134
|
-
const rewritten = matchRewrite(matchResolvedPathname(resolvedPathname),
|
|
155
|
+
for (const rewrite of configRewrites.beforeFiles ?? []) {
|
|
156
|
+
const rewritten = matchRewrite(matchResolvedPathname(resolvedPathname), [rewrite], rewriteRequestContext(), basePathState);
|
|
135
157
|
if (rewritten) {
|
|
136
158
|
if (isExternalUrl(rewritten)) return {
|
|
137
159
|
type: "response",
|
|
138
160
|
response: await proxyExternal(request, rewritten)
|
|
139
161
|
};
|
|
140
162
|
resolvedUrl = mergeRewriteQuery(resolvedUrl, rewritten);
|
|
141
|
-
resolvedPathname = resolvedUrl
|
|
163
|
+
resolvedPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
142
164
|
configRewriteFired = true;
|
|
143
165
|
}
|
|
144
166
|
}
|
|
167
|
+
if (configRewriteFired) {
|
|
168
|
+
const beforeFilesResult = await serveFilesystemRoute(resolvedPathname, "beforeFiles");
|
|
169
|
+
if (beforeFilesResult) return beforeFilesResult;
|
|
170
|
+
}
|
|
145
171
|
if (basePath && !hadBasePath && !configRewriteFired) return {
|
|
146
172
|
type: "response",
|
|
147
173
|
response: new Response("This page could not be found", {
|
|
@@ -149,36 +175,77 @@ async function runPagesRequest(request, deps) {
|
|
|
149
175
|
headers: { "Content-Type": "text/html; charset=utf-8" }
|
|
150
176
|
})
|
|
151
177
|
};
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
178
|
+
const handleResolvedApiRoute = async () => {
|
|
179
|
+
const apiLookupUrl = stripI18nLocaleForApiRoute(resolvedUrl, i18nConfig);
|
|
180
|
+
const apiLookupPathname = apiLookupUrl.split("?")[0];
|
|
181
|
+
if (!apiLookupPathname.startsWith("/api/") && apiLookupPathname !== "/api") return null;
|
|
182
|
+
if (typeof deps.handleApi === "function") {
|
|
183
|
+
let apiRequest = request;
|
|
184
|
+
if (basePath && hadBasePath) {
|
|
185
|
+
const apiRequestUrl = new URL(request.url);
|
|
186
|
+
apiRequestUrl.pathname = addBasePathToPathname(apiRequestUrl.pathname, basePath);
|
|
187
|
+
apiRequest = cloneRequestWithUrl(request, apiRequestUrl.toString());
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
type: "response",
|
|
191
|
+
defaultContentType: "application/octet-stream",
|
|
192
|
+
response: mergeHeaders(await deps.handleApi(apiRequest, apiLookupUrl, deps.ctx ?? null), middlewareHeaders, middlewareStatus)
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
type: "api",
|
|
197
|
+
apiUrl: apiLookupUrl,
|
|
198
|
+
stagedHeaders: middlewareHeaders,
|
|
199
|
+
requestHeaders: request.headers,
|
|
200
|
+
middlewareStatus
|
|
201
|
+
};
|
|
165
202
|
};
|
|
166
|
-
const
|
|
203
|
+
const apiResult = await handleResolvedApiRoute();
|
|
204
|
+
if (apiResult) return apiResult;
|
|
205
|
+
let pageMatch = deps.matchPageRoute ? deps.matchPageRoute(resolvedPathname, request) : null;
|
|
167
206
|
let resolvedPathnameChanged = false;
|
|
168
|
-
if (
|
|
169
|
-
const rewritten = matchRewrite(matchResolvedPathname(resolvedPathname),
|
|
207
|
+
if (!pageMatch || pageMatch.route.isDynamic) for (const rewrite of configRewrites.afterFiles ?? []) {
|
|
208
|
+
const rewritten = matchRewrite(matchResolvedPathname(resolvedPathname), [rewrite], rewriteRequestContext(), basePathState);
|
|
170
209
|
if (rewritten) {
|
|
171
210
|
if (isExternalUrl(rewritten)) return {
|
|
172
211
|
type: "response",
|
|
173
212
|
response: await proxyExternal(request, rewritten)
|
|
174
213
|
};
|
|
175
214
|
resolvedUrl = mergeRewriteQuery(resolvedUrl, rewritten);
|
|
176
|
-
resolvedPathname = resolvedUrl
|
|
215
|
+
resolvedPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
177
216
|
resolvedPathnameChanged = true;
|
|
217
|
+
const afterFilesFilesystemResult = await serveFilesystemRoute(resolvedPathname, "afterFiles");
|
|
218
|
+
if (afterFilesFilesystemResult) return afterFilesFilesystemResult;
|
|
219
|
+
const afterFilesApiResult = await handleResolvedApiRoute();
|
|
220
|
+
if (afterFilesApiResult) return afterFilesApiResult;
|
|
221
|
+
pageMatch = deps.matchPageRoute ? deps.matchPageRoute(resolvedPathname, request) : null;
|
|
222
|
+
if (pageMatch) break;
|
|
178
223
|
}
|
|
179
224
|
}
|
|
225
|
+
const refreshDataRewriteHeader = () => {
|
|
226
|
+
if ((isDataReq || isDataRequest) && resolvedUrl !== originalResolvedUrl && !isExternalUrl(resolvedUrl)) middlewareHeaders["x-nextjs-rewrite"] = resolvedUrl;
|
|
227
|
+
else delete middlewareHeaders["x-nextjs-rewrite"];
|
|
228
|
+
};
|
|
229
|
+
refreshDataRewriteHeader();
|
|
180
230
|
if (typeof deps.renderPage === "function") {
|
|
181
|
-
|
|
231
|
+
let renderPageMatch = pageMatch;
|
|
232
|
+
if ((isDataReq || isDataRequest) && !renderPageMatch && configRewrites.fallback?.length) for (const rewrite of configRewrites.fallback) {
|
|
233
|
+
const fallbackRewrite = matchRewrite(matchResolvedPathname(resolvedPathname), [rewrite], rewriteRequestContext(), basePathState);
|
|
234
|
+
if (!fallbackRewrite) continue;
|
|
235
|
+
if (isExternalUrl(fallbackRewrite)) return {
|
|
236
|
+
type: "response",
|
|
237
|
+
response: await proxyExternal(request, fallbackRewrite)
|
|
238
|
+
};
|
|
239
|
+
resolvedUrl = mergeRewriteQuery(resolvedUrl, fallbackRewrite);
|
|
240
|
+
resolvedPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
241
|
+
const fallbackFilesystemResult = await serveFilesystemRoute(resolvedPathname, "fallback");
|
|
242
|
+
if (fallbackFilesystemResult) return fallbackFilesystemResult;
|
|
243
|
+
const fallbackApiResult = await handleResolvedApiRoute();
|
|
244
|
+
if (fallbackApiResult) return fallbackApiResult;
|
|
245
|
+
renderPageMatch = deps.matchPageRoute ? deps.matchPageRoute(resolvedPathname, request) : null;
|
|
246
|
+
refreshDataRewriteHeader();
|
|
247
|
+
if (renderPageMatch) break;
|
|
248
|
+
}
|
|
182
249
|
const shouldDeferErrorPageOnMiss = !isDataReq && !isDataRequest && !!deps.matchPageRoute && !renderPageMatch;
|
|
183
250
|
const initialRenderOptions = shouldDeferErrorPageOnMiss ? { renderErrorPageOnMiss: false } : isDataReq ? { isDataReq: true } : void 0;
|
|
184
251
|
const stagedHeaders = new Headers();
|
|
@@ -186,16 +253,22 @@ async function runPagesRequest(request, deps) {
|
|
|
186
253
|
else stagedHeaders.set(k, v);
|
|
187
254
|
let response = await deps.renderPage(request, resolvedUrl, initialRenderOptions, stagedHeaders);
|
|
188
255
|
let matchedFallbackRewrite = false;
|
|
189
|
-
if (response.status === 404 && shouldDeferErrorPageOnMiss && configRewrites.fallback?.length) {
|
|
190
|
-
const fallbackRewrite = matchRewrite(matchResolvedPathname(resolvedPathname),
|
|
191
|
-
if (fallbackRewrite)
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
256
|
+
if (response.status === 404 && shouldDeferErrorPageOnMiss && configRewrites.fallback?.length) for (const rewrite of configRewrites.fallback) {
|
|
257
|
+
const fallbackRewrite = matchRewrite(matchResolvedPathname(resolvedPathname), [rewrite], rewriteRequestContext(), basePathState);
|
|
258
|
+
if (!fallbackRewrite) continue;
|
|
259
|
+
if (isExternalUrl(fallbackRewrite)) return {
|
|
260
|
+
type: "response",
|
|
261
|
+
response: await proxyExternal(request, fallbackRewrite)
|
|
262
|
+
};
|
|
263
|
+
resolvedUrl = mergeRewriteQuery(resolvedUrl, fallbackRewrite);
|
|
264
|
+
resolvedPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
265
|
+
const fallbackFilesystemResult = await serveFilesystemRoute(resolvedPathname, "fallback");
|
|
266
|
+
if (fallbackFilesystemResult) return fallbackFilesystemResult;
|
|
267
|
+
const fallbackApiResult = await handleResolvedApiRoute();
|
|
268
|
+
if (fallbackApiResult) return fallbackApiResult;
|
|
269
|
+
response = await deps.renderPage(request, resolvedUrl, void 0, stagedHeaders);
|
|
270
|
+
matchedFallbackRewrite = true;
|
|
271
|
+
if (response.status !== 404) break;
|
|
199
272
|
}
|
|
200
273
|
if (response.status === 404 && shouldDeferErrorPageOnMiss && !matchedFallbackRewrite) response = await deps.renderPage(request, resolvedUrl, void 0, stagedHeaders);
|
|
201
274
|
const merged = mergeHeaders(response, middlewareHeaders, middlewareStatus);
|
|
@@ -206,16 +279,22 @@ async function runPagesRequest(request, deps) {
|
|
|
206
279
|
defaultContentType: "text/html"
|
|
207
280
|
};
|
|
208
281
|
}
|
|
209
|
-
if (!(resolvedPathnameChanged ? deps.matchPageRoute ? deps.matchPageRoute(resolvedPathname, request) : null : pageMatch) && configRewrites.fallback?.length) {
|
|
210
|
-
const fallbackRewrite = matchRewrite(matchResolvedPathname(resolvedPathname),
|
|
211
|
-
if (fallbackRewrite)
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
282
|
+
if (!(resolvedPathnameChanged ? deps.matchPageRoute ? deps.matchPageRoute(resolvedPathname, request) : null : pageMatch) && configRewrites.fallback?.length) for (const rewrite of configRewrites.fallback) {
|
|
283
|
+
const fallbackRewrite = matchRewrite(matchResolvedPathname(resolvedPathname), [rewrite], rewriteRequestContext(), basePathState);
|
|
284
|
+
if (!fallbackRewrite) continue;
|
|
285
|
+
if (isExternalUrl(fallbackRewrite)) return {
|
|
286
|
+
type: "response",
|
|
287
|
+
response: await proxyExternal(request, fallbackRewrite)
|
|
288
|
+
};
|
|
289
|
+
resolvedUrl = mergeRewriteQuery(resolvedUrl, fallbackRewrite);
|
|
290
|
+
resolvedPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
291
|
+
const fallbackFilesystemResult = await serveFilesystemRoute(resolvedPathname, "fallback");
|
|
292
|
+
if (fallbackFilesystemResult) return fallbackFilesystemResult;
|
|
293
|
+
const fallbackApiResult = await handleResolvedApiRoute();
|
|
294
|
+
if (fallbackApiResult) return fallbackApiResult;
|
|
295
|
+
if (deps.matchPageRoute?.(resolvedPathname, request)) break;
|
|
218
296
|
}
|
|
297
|
+
refreshDataRewriteHeader();
|
|
219
298
|
return {
|
|
220
299
|
type: "render",
|
|
221
300
|
resolvedUrl,
|
|
@@ -227,4 +306,4 @@ async function runPagesRequest(request, deps) {
|
|
|
227
306
|
};
|
|
228
307
|
}
|
|
229
308
|
//#endregion
|
|
230
|
-
export { runPagesRequest, wrapMiddlewareWithBasePath };
|
|
309
|
+
export { fetchWorkerFilesystemRoute, runPagesRequest, wrapMiddlewareWithBasePath };
|
|
@@ -4,28 +4,12 @@ declare global {
|
|
|
4
4
|
}
|
|
5
5
|
declare function normalizePregeneratedPathname(pathname: string): string;
|
|
6
6
|
declare function clearPregeneratedConcretePaths(): void;
|
|
7
|
-
/**
|
|
8
|
-
* Records a concrete URL path for a route pattern. The pathname is normalized
|
|
9
|
-
* here so this is the single source of truth: every caller — the Worker global
|
|
10
|
-
* table and the Node `seed-cache.ts` path — stores the canonical form that
|
|
11
|
-
* matches the runtime `cleanPathname` lookup without having to pre-normalize.
|
|
12
|
-
*/
|
|
13
7
|
declare function addPregeneratedConcretePath(routePattern: string, pathname: string): void;
|
|
14
|
-
/**
|
|
15
|
-
* Returns the live backing `Set` for a route pattern (not a copy) to keep
|
|
16
|
-
* lookups allocation-free on the serving hot path. The `ReadonlySet` type
|
|
17
|
-
* forbids mutation at compile time. Callers must treat the result as
|
|
18
|
-
* point-in-time and must NOT retain it across a re-seed: each
|
|
19
|
-
* `initPregeneratedPathsFromGlobals` call runs `clearPregeneratedConcretePaths`,
|
|
20
|
-
* which empties the map, leaving any previously-returned reference stale. Read
|
|
21
|
-
* it, use it, drop it — never cache the reference.
|
|
22
|
-
*/
|
|
23
8
|
declare function getRenderedConcreteUrlPathsForRoute(routePattern: string): ReadonlySet<string> | undefined;
|
|
24
9
|
/**
|
|
25
10
|
* Populate the registry from `globalThis.__VINEXT_PREGENERATED_CONCRETE_PATHS`.
|
|
26
11
|
* No-op when the global is not set (Node path — seed-cache handles it later).
|
|
27
|
-
*
|
|
28
|
-
* runtime `cleanPathname`.
|
|
12
|
+
* Pathnames are normalised so they match the runtime `cleanPathname`.
|
|
29
13
|
*/
|
|
30
14
|
declare function initPregeneratedPathsFromGlobals(): void;
|
|
31
15
|
//#endregion
|
|
@@ -16,38 +16,21 @@ const concreteUrlPathsByRoute = /* @__PURE__ */ new Map();
|
|
|
16
16
|
function clearPregeneratedConcretePaths() {
|
|
17
17
|
concreteUrlPathsByRoute.clear();
|
|
18
18
|
}
|
|
19
|
-
/**
|
|
20
|
-
* Records a concrete URL path for a route pattern. The pathname is normalized
|
|
21
|
-
* here so this is the single source of truth: every caller — the Worker global
|
|
22
|
-
* table and the Node `seed-cache.ts` path — stores the canonical form that
|
|
23
|
-
* matches the runtime `cleanPathname` lookup without having to pre-normalize.
|
|
24
|
-
*/
|
|
25
19
|
function addPregeneratedConcretePath(routePattern, pathname) {
|
|
26
|
-
const normalized = normalizePregeneratedPathname(pathname);
|
|
27
20
|
let paths = concreteUrlPathsByRoute.get(routePattern);
|
|
28
21
|
if (!paths) {
|
|
29
22
|
paths = /* @__PURE__ */ new Set();
|
|
30
23
|
concreteUrlPathsByRoute.set(routePattern, paths);
|
|
31
24
|
}
|
|
32
|
-
paths.add(
|
|
25
|
+
paths.add(normalizePregeneratedPathname(pathname));
|
|
33
26
|
}
|
|
34
|
-
/**
|
|
35
|
-
* Returns the live backing `Set` for a route pattern (not a copy) to keep
|
|
36
|
-
* lookups allocation-free on the serving hot path. The `ReadonlySet` type
|
|
37
|
-
* forbids mutation at compile time. Callers must treat the result as
|
|
38
|
-
* point-in-time and must NOT retain it across a re-seed: each
|
|
39
|
-
* `initPregeneratedPathsFromGlobals` call runs `clearPregeneratedConcretePaths`,
|
|
40
|
-
* which empties the map, leaving any previously-returned reference stale. Read
|
|
41
|
-
* it, use it, drop it — never cache the reference.
|
|
42
|
-
*/
|
|
43
27
|
function getRenderedConcreteUrlPathsForRoute(routePattern) {
|
|
44
28
|
return concreteUrlPathsByRoute.get(routePattern);
|
|
45
29
|
}
|
|
46
30
|
/**
|
|
47
31
|
* Populate the registry from `globalThis.__VINEXT_PREGENERATED_CONCRETE_PATHS`.
|
|
48
32
|
* No-op when the global is not set (Node path — seed-cache handles it later).
|
|
49
|
-
*
|
|
50
|
-
* runtime `cleanPathname`.
|
|
33
|
+
* Pathnames are normalised so they match the runtime `cleanPathname`.
|
|
51
34
|
*/
|
|
52
35
|
function initPregeneratedPathsFromGlobals() {
|
|
53
36
|
const raw = globalThis.__VINEXT_PREGENERATED_CONCRETE_PATHS;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//#region src/server/prerender-manifest.d.ts
|
|
2
|
+
type PrerenderManifestRoute = {
|
|
3
|
+
route: string;
|
|
4
|
+
status?: string;
|
|
5
|
+
revalidate?: number | false;
|
|
6
|
+
expire?: number;
|
|
7
|
+
path?: string;
|
|
8
|
+
router?: string;
|
|
9
|
+
fallback?: boolean;
|
|
10
|
+
};
|
|
11
|
+
type PrerenderManifest = {
|
|
12
|
+
buildId?: string;
|
|
13
|
+
trailingSlash?: boolean;
|
|
14
|
+
routes?: PrerenderManifestRoute[];
|
|
15
|
+
};
|
|
16
|
+
declare function readPrerenderManifest(manifestPath: string): PrerenderManifest | null;
|
|
17
|
+
declare function getRenderedAppRoutes(routes: PrerenderManifestRoute[]): PrerenderManifestRoute[];
|
|
18
|
+
/**
|
|
19
|
+
* Returns true when `pathname` contains bracket-delimited route params,
|
|
20
|
+
* indicating it is a fallback-shell placeholder (e.g. `/en/blog/[slug]`)
|
|
21
|
+
* rather than a concrete rendered URL.
|
|
22
|
+
*/
|
|
23
|
+
declare function isFallbackShellArtifactPath(pathname: string, route?: PrerenderManifestRoute): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Build the pregenerated concrete-path payload table from a prerender manifest.
|
|
26
|
+
*
|
|
27
|
+
* Filters out fallback-shell placeholder paths and groups remaining concrete
|
|
28
|
+
* paths by route pattern. Returns an empty array when the manifest has no
|
|
29
|
+
* rendered App routes or all routes are fallback-shell artifacts.
|
|
30
|
+
*/
|
|
31
|
+
declare function buildPregeneratedConcretePathTable(manifest: PrerenderManifest): Array<[string, string[]]>;
|
|
32
|
+
//#endregion
|
|
33
|
+
export { buildPregeneratedConcretePathTable, getRenderedAppRoutes, isFallbackShellArtifactPath, readPrerenderManifest };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
//#region src/server/prerender-manifest.ts
|
|
3
|
+
function readPrerenderManifest(manifestPath) {
|
|
4
|
+
if (!fs.existsSync(manifestPath)) return null;
|
|
5
|
+
try {
|
|
6
|
+
return JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
7
|
+
} catch (error) {
|
|
8
|
+
console.warn(`[vinext] Failed to read prerender manifest at ${manifestPath}:`, error);
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function getRenderedAppRoutes(routes) {
|
|
13
|
+
return routes.filter((r) => r.status === "rendered" && r.router === "app");
|
|
14
|
+
}
|
|
15
|
+
function groupRoutesByPattern(routes) {
|
|
16
|
+
const byPattern = /* @__PURE__ */ new Map();
|
|
17
|
+
for (const r of routes) {
|
|
18
|
+
const pathname = r.path ?? r.route;
|
|
19
|
+
const existing = byPattern.get(r.route);
|
|
20
|
+
if (existing) existing.push(pathname);
|
|
21
|
+
else byPattern.set(r.route, [pathname]);
|
|
22
|
+
}
|
|
23
|
+
return byPattern;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Returns true when `pathname` contains bracket-delimited route params,
|
|
27
|
+
* indicating it is a fallback-shell placeholder (e.g. `/en/blog/[slug]`)
|
|
28
|
+
* rather than a concrete rendered URL.
|
|
29
|
+
*/
|
|
30
|
+
function isFallbackShellArtifactPath(pathname, route) {
|
|
31
|
+
if (route?.fallback === true) return true;
|
|
32
|
+
if (route?.fallback === void 0) {
|
|
33
|
+
if (process.env.NODE_ENV !== "production") console.warn("[vinext] Legacy manifest detected: missing `fallback` flag for route. Using bracket heuristic for fallback-shell detection. A concrete URL containing literal brackets may be misclassified as a fallback shell.");
|
|
34
|
+
return pathname.includes("[") || pathname.includes("]");
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Build the pregenerated concrete-path payload table from a prerender manifest.
|
|
40
|
+
*
|
|
41
|
+
* Filters out fallback-shell placeholder paths and groups remaining concrete
|
|
42
|
+
* paths by route pattern. Returns an empty array when the manifest has no
|
|
43
|
+
* rendered App routes or all routes are fallback-shell artifacts.
|
|
44
|
+
*/
|
|
45
|
+
function buildPregeneratedConcretePathTable(manifest) {
|
|
46
|
+
const routes = manifest?.routes;
|
|
47
|
+
if (!routes?.length) return [];
|
|
48
|
+
const concreteRoutes = getRenderedAppRoutes(routes).filter((r) => {
|
|
49
|
+
return !isFallbackShellArtifactPath(r.path ?? r.route, r);
|
|
50
|
+
});
|
|
51
|
+
return Array.from(groupRoutesByPattern(concreteRoutes).entries());
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
export { buildPregeneratedConcretePathTable, getRenderedAppRoutes, isFallbackShellArtifactPath, readPrerenderManifest };
|
|
@@ -5,7 +5,6 @@ type PrerenderRouteParamsPayload = {
|
|
|
5
5
|
params: PrerenderRouteParams;
|
|
6
6
|
routePattern: string;
|
|
7
7
|
};
|
|
8
|
-
/** @public exported for #1716 serving consumers; not yet referenced in-repo */
|
|
9
8
|
type PrerenderRouteParamsRouteMatch = {
|
|
10
9
|
kind: "exact";
|
|
11
10
|
params: PrerenderRouteParams;
|
|
@@ -21,4 +20,4 @@ declare function prerenderRouteParamsPayloadMatchesRoute(payload: PrerenderRoute
|
|
|
21
20
|
declare function matchPrerenderRouteParamsPayload(payload: PrerenderRouteParamsPayload | null, routePattern: string, params: PrerenderRouteParams): PrerenderRouteParamsRouteMatch | null;
|
|
22
21
|
declare function encodePrerenderRouteParams(pattern: string, params: PrerenderRouteParams, fallbackParamNames?: readonly string[]): PrerenderRouteParamsPayload | null;
|
|
23
22
|
//#endregion
|
|
24
|
-
export { PrerenderRouteParams, PrerenderRouteParamsPayload,
|
|
23
|
+
export { PrerenderRouteParams, PrerenderRouteParamsPayload, encodePrerenderRouteParams, matchPrerenderRouteParamsPayload, prerenderRouteParamsPayloadMatchesRoute, readTrustedPrerenderRouteParams, readTrustedPrerenderRouteParamsFromHeaders, serializePrerenderRouteParamsHeader };
|
|
@@ -41,6 +41,8 @@ import { IncomingMessage, ServerResponse } from "node:http";
|
|
|
41
41
|
*/
|
|
42
42
|
declare function resolveServerEntryImportUrl(entryPath: string): string;
|
|
43
43
|
declare function importServerEntryModule(entryPath: string): Promise<any>;
|
|
44
|
+
/** Convert a Node.js IncomingMessage into a ReadableStream for Web Request body. */
|
|
45
|
+
declare function readNodeStream(req: IncomingMessage): ReadableStream<Uint8Array>;
|
|
44
46
|
type ProdServerOptions = {
|
|
45
47
|
/** Port to listen on */port?: number; /** Host to bind to */
|
|
46
48
|
host?: string; /** Path to the build output directory */
|
|
@@ -143,4 +145,4 @@ declare function resolveAppRouterPrerenderSeeder(entryModule: unknown): AppRoute
|
|
|
143
145
|
*/
|
|
144
146
|
declare function resolveAppRouterAssetPath(pathname: string, assetPathPrefix: string, assetPrefix: string): string | null;
|
|
145
147
|
//#endregion
|
|
146
|
-
export { COMPRESSIBLE_TYPES, COMPRESS_THRESHOLD, ProdServerOptions, importServerEntryModule, mergeResponseHeaders, mergeWebResponse, negotiateEncoding, nodeToWebRequest, resolveAppRouterAssetPath, resolveAppRouterPrerenderSeeder, resolveRequestHost as resolveHost, resolveServerEntryImportUrl, sendCompressed, sendWebResponse, startProdServer, trustProxy, trustedHosts, tryServeStatic };
|
|
148
|
+
export { COMPRESSIBLE_TYPES, COMPRESS_THRESHOLD, ProdServerOptions, importServerEntryModule, mergeResponseHeaders, mergeWebResponse, negotiateEncoding, nodeToWebRequest, readNodeStream, resolveAppRouterAssetPath, resolveAppRouterPrerenderSeeder, resolveRequestHost as resolveHost, resolveServerEntryImportUrl, sendCompressed, sendWebResponse, startProdServer, trustProxy, trustedHosts, tryServeStatic };
|