vinext 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build/prerender.d.ts +9 -1
- package/dist/build/prerender.js +41 -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/vinext-next-data.d.ts +18 -1
- 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.js +73 -14
- package/dist/config/next-config.d.ts +46 -4
- package/dist/config/next-config.js +147 -48
- package/dist/deploy.d.ts +30 -11
- package/dist/deploy.js +180 -99
- 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 +64 -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 +53 -8
- package/dist/entries/pages-server-entry.js +41 -5
- package/dist/index.js +200 -62
- package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
- package/dist/plugins/extensionless-dynamic-import.js +152 -0
- 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/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 +44 -14
- 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 +19 -10
- package/dist/server/app-browser-entry.js +167 -90
- 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 +4 -2
- 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-stream.js +86 -43
- 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 +18 -0
- package/dist/server/app-pages-bridge.js +22 -5
- 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 +25 -0
- package/dist/server/app-rsc-handler.js +154 -54
- package/dist/server/app-rsc-route-matching.d.ts +3 -0
- package/dist/server/app-rsc-route-matching.js +2 -0
- 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 +42 -13
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +83 -10
- package/dist/server/cache-control.js +4 -0
- package/dist/server/dev-server.d.ts +2 -2
- package/dist/server/dev-server.js +244 -51
- 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/navigation-planner.d.ts +133 -30
- package/dist/server/navigation-planner.js +114 -0
- package/dist/server/navigation-trace.d.ts +8 -1
- package/dist/server/navigation-trace.js +8 -1
- 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 +8 -1
- package/dist/server/pages-data-route.js +11 -2
- 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-node-compat.js +2 -2
- package/dist/server/pages-page-data.d.ts +11 -2
- package/dist/server/pages-page-data.js +204 -33
- package/dist/server/pages-page-handler.d.ts +4 -2
- package/dist/server/pages-page-handler.js +59 -22
- package/dist/server/pages-page-response.d.ts +2 -1
- package/dist/server/pages-page-response.js +7 -4
- package/dist/server/pages-request-pipeline.d.ts +1 -0
- package/dist/server/pages-request-pipeline.js +73 -36
- 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.js +9 -3
- 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/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/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/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/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-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 +12 -5
- package/dist/shims/navigation.d.ts +8 -2
- package/dist/shims/navigation.js +61 -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 +13 -2
- package/dist/shims/router.js +419 -128
- 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/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/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
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { isPprFallbackShellAbortError, preparePprFallbackShellFinalRender, waitForPprFallbackShellCacheReady } from "../shims/ppr-fallback-shell.js";
|
|
2
|
+
import { readAppPageBinaryStream } from "./app-page-execution.js";
|
|
3
|
+
//#region src/server/app-ppr-fallback-shell-render.ts
|
|
4
|
+
async function warmPprFallbackShellCaches(options) {
|
|
5
|
+
let warmupError = null;
|
|
6
|
+
const warmupDrain = readAppPageBinaryStream(options.renderToReadableStream(options.element, {
|
|
7
|
+
signal: options.state.abortController.signal,
|
|
8
|
+
onError(error, requestInfo, errorContext) {
|
|
9
|
+
if (options.state.abortController.signal.aborted || isPprFallbackShellAbortError(error)) return;
|
|
10
|
+
return options.onError(error, requestInfo, errorContext);
|
|
11
|
+
}
|
|
12
|
+
})).catch((error) => {
|
|
13
|
+
if (options.state.abortController.signal.aborted || isPprFallbackShellAbortError(error)) return;
|
|
14
|
+
warmupError = error;
|
|
15
|
+
});
|
|
16
|
+
try {
|
|
17
|
+
await waitForPprFallbackShellCacheReady(options.state);
|
|
18
|
+
} finally {
|
|
19
|
+
options.state.abortController.abort();
|
|
20
|
+
await warmupDrain;
|
|
21
|
+
preparePprFallbackShellFinalRender(options.state);
|
|
22
|
+
}
|
|
23
|
+
if (warmupError) throw warmupError;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { warmPprFallbackShellCaches };
|
|
@@ -9,6 +9,18 @@ type AppPprFallbackShell = {
|
|
|
9
9
|
pathname: string;
|
|
10
10
|
params: Record<string, string | string[]>;
|
|
11
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* A fallback-shell cache entry as consumed by the dispatch layer.
|
|
14
|
+
* Produced at build time by the PPR prerender and served at request time
|
|
15
|
+
* when the exact cache entry for a dynamic child param is missing.
|
|
16
|
+
*/
|
|
17
|
+
type AppPagePprFallbackCacheShell = {
|
|
18
|
+
fallbackParamNames: readonly string[];
|
|
19
|
+
params: Record<string, string | string[]>;
|
|
20
|
+
pathname: string;
|
|
21
|
+
};
|
|
22
|
+
declare function markAppPprDynamicFallbackShellHtml(html: string): string;
|
|
23
|
+
declare function isAppPprDynamicFallbackShellHtml(html: string): boolean;
|
|
12
24
|
declare function createAppPprFallbackShell(route: AppPprFallbackShellRoute, matchedParams: Record<string, string | string[]>): AppPprFallbackShell | null;
|
|
13
25
|
declare function createAppPprFallbackShells(route: AppPprFallbackShellRoute, matchedParams: Record<string, string | string[]>): AppPprFallbackShell[];
|
|
14
26
|
declare function rewriteAppPprFallbackShellHtmlNavigation(options: {
|
|
@@ -18,4 +30,4 @@ declare function rewriteAppPprFallbackShellHtmlNavigation(options: {
|
|
|
18
30
|
searchParams: URLSearchParams;
|
|
19
31
|
}): string;
|
|
20
32
|
//#endregion
|
|
21
|
-
export { createAppPprFallbackShell, createAppPprFallbackShells, rewriteAppPprFallbackShellHtmlNavigation };
|
|
33
|
+
export { AppPagePprFallbackCacheShell, createAppPprFallbackShell, createAppPprFallbackShells, isAppPprDynamicFallbackShellHtml, markAppPprDynamicFallbackShellHtml, rewriteAppPprFallbackShellHtmlNavigation };
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { createInlineScriptTag } from "./html.js";
|
|
2
2
|
import { createNavigationRuntimeRscMetadataScript } from "./app-ssr-stream.js";
|
|
3
3
|
//#region src/server/app-ppr-fallback-shell.ts
|
|
4
|
+
const PPR_DYNAMIC_FALLBACK_SHELL_MARKER = "<!--vinext-ppr-dynamic-fallback-shell-->";
|
|
5
|
+
function markAppPprDynamicFallbackShellHtml(html) {
|
|
6
|
+
return html + PPR_DYNAMIC_FALLBACK_SHELL_MARKER;
|
|
7
|
+
}
|
|
8
|
+
function isAppPprDynamicFallbackShellHtml(html) {
|
|
9
|
+
return html.includes(PPR_DYNAMIC_FALLBACK_SHELL_MARKER);
|
|
10
|
+
}
|
|
4
11
|
function routeRootParamNames(route) {
|
|
5
12
|
return new Set(route.rootParamNames ?? []);
|
|
6
13
|
}
|
|
@@ -79,4 +86,4 @@ function rewriteAppPprFallbackShellHtmlNavigation(options) {
|
|
|
79
86
|
return metadataScript + options.html;
|
|
80
87
|
}
|
|
81
88
|
//#endregion
|
|
82
|
-
export { createAppPprFallbackShell, createAppPprFallbackShells, rewriteAppPprFallbackShellHtmlNavigation };
|
|
89
|
+
export { createAppPprFallbackShell, createAppPprFallbackShells, isAppPprDynamicFallbackShellHtml, markAppPprDynamicFallbackShellHtml, rewriteAppPprFallbackShellHtmlNavigation };
|
|
@@ -2,16 +2,17 @@ import { createRequestContext, runWithRequestContext } from "../shims/unified-re
|
|
|
2
2
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
3
3
|
import { reportRequestError } from "./instrumentation.js";
|
|
4
4
|
import { consumeDynamicUsage, getAndClearPendingCookies, getDraftModeCookieHeader, markDynamicUsage, setHeadersAccessPhase } from "../shims/headers.js";
|
|
5
|
-
import { ensureFetchPatch, getCollectedFetchTags, setCurrentFetchSoftTags } from "../shims/fetch-cache.js";
|
|
5
|
+
import { ensureFetchPatch, getCollectedFetchTags, setCurrentFetchCacheMode, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault } from "../shims/fetch-cache.js";
|
|
6
6
|
import { setNavigationContext } from "../shims/navigation.js";
|
|
7
7
|
import { makeThenableParams } from "../shims/thenable-params.js";
|
|
8
|
+
import { buildPageCacheTags } from "./implicit-tags.js";
|
|
8
9
|
import { isKnownDynamicAppRoute, isValidHTTPMethod } from "./app-route-handler-runtime.js";
|
|
9
10
|
import { getAppRouteHandlerRevalidateSeconds, hasAppRouteHandlerDefaultExport, resolveAppRouteHandlerMethod, shouldReadAppRouteHandlerCache } from "./app-route-handler-policy.js";
|
|
10
11
|
import { createStaticGenerationHeadersContext } from "./app-static-generation.js";
|
|
11
|
-
import { buildPageCacheTags } from "./implicit-tags.js";
|
|
12
12
|
import { applyRouteHandlerMiddlewareContext } from "./app-route-handler-response.js";
|
|
13
13
|
import { executeAppRouteHandler } from "./app-route-handler-execution.js";
|
|
14
14
|
import { readAppRouteHandlerCacheResponse } from "./app-route-handler-cache.js";
|
|
15
|
+
import { resolveAppRouteHandlerFetchCacheMode } from "./app-segment-config.js";
|
|
15
16
|
//#region src/server/app-route-handler-dispatch.ts
|
|
16
17
|
function isAppRouteHandlerFunction(value) {
|
|
17
18
|
return typeof value === "function";
|
|
@@ -32,6 +33,8 @@ async function runInRouteHandlerRevalidationContext(options, renderFn) {
|
|
|
32
33
|
}), async () => {
|
|
33
34
|
ensureFetchPatch();
|
|
34
35
|
setCurrentFetchSoftTags(buildRouteHandlerPageCacheTags(options.cleanPathname, [], options.routeSegments));
|
|
36
|
+
setCurrentFetchCacheMode(options.fetchCacheMode);
|
|
37
|
+
setCurrentForceDynamicFetchDefault(options.dynamicConfig === "force-dynamic");
|
|
35
38
|
await renderFn();
|
|
36
39
|
});
|
|
37
40
|
}
|
|
@@ -56,6 +59,9 @@ async function dispatchAppRouteHandler(options) {
|
|
|
56
59
|
}), options.middlewareContext);
|
|
57
60
|
}
|
|
58
61
|
const resolvedHandlerFn = isAppRouteHandlerFunction(handlerFn) ? handlerFn : void 0;
|
|
62
|
+
const fetchCacheMode = resolveAppRouteHandlerFetchCacheMode(handler);
|
|
63
|
+
setCurrentFetchCacheMode(fetchCacheMode);
|
|
64
|
+
setCurrentForceDynamicFetchDefault(handler.dynamic === "force-dynamic");
|
|
59
65
|
if (revalidateSeconds !== null && shouldReadAppRouteHandlerCache({
|
|
60
66
|
dynamicConfig: handler.dynamic,
|
|
61
67
|
handlerFn: resolvedHandlerFn,
|
|
@@ -96,6 +102,7 @@ async function dispatchAppRouteHandler(options) {
|
|
|
96
102
|
cleanPathname: options.cleanPathname,
|
|
97
103
|
draftModeSecret: options.draftModeSecret,
|
|
98
104
|
dynamicConfig: handler.dynamic,
|
|
105
|
+
fetchCacheMode,
|
|
99
106
|
routePattern: route.pattern,
|
|
100
107
|
routeSegments: route.routeSegments
|
|
101
108
|
}, renderFn);
|
|
@@ -3,6 +3,7 @@ import { RouteHandlerHttpMethod, RouteHandlerModule } from "./app-route-handler-
|
|
|
3
3
|
//#region src/server/app-route-handler-policy.d.ts
|
|
4
4
|
type AppRouteHandlerModule = {
|
|
5
5
|
dynamic?: string;
|
|
6
|
+
fetchCache?: unknown;
|
|
6
7
|
revalidate?: unknown;
|
|
7
8
|
} & RouteHandlerModule;
|
|
8
9
|
type AppRouteHandlerFunction = (...args: unknown[]) => unknown;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import "./server-globals.js";
|
|
2
2
|
import { runWithExecutionContext } from "../shims/request-context.js";
|
|
3
|
+
import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER } from "./headers.js";
|
|
3
4
|
import { badRequestResponse, notFoundResponse, notFoundStaticAssetResponse } from "./http-error-responses.js";
|
|
4
5
|
import { cloneRequestWithHeaders, filterInternalHeaders, isOpenRedirectShaped } from "./request-pipeline.js";
|
|
5
6
|
import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js";
|
|
6
7
|
import { resolveStaticAssetSignal } from "./worker-utils.js";
|
|
8
|
+
import { readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
|
|
7
9
|
import rscHandler, { __assetPrefix, __basePath } from "virtual:vinext-rsc-entry";
|
|
8
10
|
import { registerConfiguredCacheAdapters } from "virtual:vinext-cache-adapters";
|
|
9
11
|
//#region src/server/app-router-entry.ts
|
|
@@ -23,7 +25,10 @@ async function handleRequest(request, env, ctx) {
|
|
|
23
25
|
}
|
|
24
26
|
if (isNextStaticPath(url.pathname, __workerBasePath, __workerAssetPathPrefix)) return notFoundStaticAssetResponse();
|
|
25
27
|
{
|
|
28
|
+
const prerenderRouteParamsPayload = readTrustedPrerenderRouteParams(request);
|
|
26
29
|
const filteredHeaders = filterInternalHeaders(request.headers);
|
|
30
|
+
const prerenderRouteParamsHeader = serializePrerenderRouteParamsHeader(prerenderRouteParamsPayload);
|
|
31
|
+
if (prerenderRouteParamsHeader !== null) filteredHeaders.set(VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, prerenderRouteParamsHeader);
|
|
27
32
|
request = cloneRequestWithHeaders(request, filteredHeaders);
|
|
28
33
|
}
|
|
29
34
|
const handleFn = () => rscHandler(request, ctx);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_RSC_RENDER_MODE_HEADER } from "./headers.js";
|
|
2
2
|
import { fnv1a64 } from "../utils/hash.js";
|
|
3
3
|
import { parseAppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
4
|
+
import { applyDeploymentIdHeader } from "../utils/deployment-id.js";
|
|
4
5
|
//#region src/server/app-rsc-cache-busting.ts
|
|
5
6
|
/**
|
|
6
7
|
* RSC cache-busting hashes cover the headers that make an RSC payload vary.
|
|
@@ -148,6 +149,7 @@ function createRscRequestHeaders(options = {}) {
|
|
|
148
149
|
Accept: VINEXT_RSC_CONTENT_TYPE,
|
|
149
150
|
["RSC"]: "1"
|
|
150
151
|
});
|
|
152
|
+
applyDeploymentIdHeader(headers);
|
|
151
153
|
if (options.interceptionContext !== void 0 && options.interceptionContext !== null) headers.set(VINEXT_INTERCEPTION_CONTEXT_HEADER, options.interceptionContext);
|
|
152
154
|
if (options.mountedSlotsHeader !== void 0 && options.mountedSlotsHeader !== null) headers.set(VINEXT_MOUNTED_SLOTS_HEADER, options.mountedSlotsHeader);
|
|
153
155
|
if (options.clientReuseManifestHeader !== void 0 && options.clientReuseManifestHeader !== null) headers.set(VINEXT_CLIENT_REUSE_MANIFEST_HEADER, options.clientReuseManifestHeader);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NextHeader, NextI18nConfig, NextRedirect, NextRewrite } from "../config/next-config.js";
|
|
2
|
+
import { ImageConfig } from "./image-optimization.js";
|
|
2
3
|
import { ClientReuseManifestParseResult } from "./client-reuse-manifest.js";
|
|
3
4
|
import { RootParams } from "../shims/root-params.js";
|
|
4
5
|
import { MiddlewareModule } from "./middleware-runtime.js";
|
|
@@ -17,6 +18,7 @@ type RootParamNamesMap = Parameters<typeof handleAppPrerenderEndpoint>[1]["rootP
|
|
|
17
18
|
type AppRscMiddlewareContext = AppMiddlewareContext;
|
|
18
19
|
type AppRscHandlerRoute = {
|
|
19
20
|
isDynamic: boolean;
|
|
21
|
+
params?: readonly string[];
|
|
20
22
|
page?: unknown;
|
|
21
23
|
pattern: string;
|
|
22
24
|
rootParamNames?: readonly string[];
|
|
@@ -41,6 +43,17 @@ type DispatchMatchedPageOptions<TRoute> = {
|
|
|
41
43
|
middlewareContext: AppRscMiddlewareContext;
|
|
42
44
|
mountedSlotsHeader: string | null;
|
|
43
45
|
params: AppPageParams;
|
|
46
|
+
pprFallbackCacheShells?: readonly {
|
|
47
|
+
fallbackParamNames: readonly string[];
|
|
48
|
+
params: AppPageParams;
|
|
49
|
+
pathname: string;
|
|
50
|
+
}[] | null;
|
|
51
|
+
pprFallbackShell?: {
|
|
52
|
+
fallbackParamNames: readonly string[];
|
|
53
|
+
routePattern: string;
|
|
54
|
+
};
|
|
55
|
+
renderedConcreteUrlPaths?: ReadonlySet<string>;
|
|
56
|
+
skipStaticParamsValidation?: boolean;
|
|
44
57
|
staticParamsValidationParams?: AppPageParams;
|
|
45
58
|
rootParams?: RootParams;
|
|
46
59
|
request: Request;
|
|
@@ -110,8 +123,17 @@ type RenderNotFoundOptions<TRoute> = {
|
|
|
110
123
|
scriptNonce?: string;
|
|
111
124
|
};
|
|
112
125
|
type RenderPagesFallbackOptions = {
|
|
126
|
+
allowRscDocumentFallback?: boolean;
|
|
127
|
+
appRouteMatch?: {
|
|
128
|
+
route: {
|
|
129
|
+
isDynamic: boolean;
|
|
130
|
+
pattern: string;
|
|
131
|
+
};
|
|
132
|
+
} | null;
|
|
113
133
|
isRscRequest: boolean;
|
|
134
|
+
matchKind?: "dynamic" | "static";
|
|
114
135
|
middlewareContext: AppRscMiddlewareContext;
|
|
136
|
+
pathname?: string;
|
|
115
137
|
request: Request;
|
|
116
138
|
url: URL;
|
|
117
139
|
};
|
|
@@ -122,6 +144,7 @@ type NavigationContextValue = {
|
|
|
122
144
|
};
|
|
123
145
|
type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
|
|
124
146
|
basePath: string;
|
|
147
|
+
cacheComponents?: boolean;
|
|
125
148
|
clearRequestContext: () => void;
|
|
126
149
|
configHeaders: NextHeader[];
|
|
127
150
|
configRedirects: NextRedirect[];
|
|
@@ -150,6 +173,8 @@ type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
|
|
|
150
173
|
handleProgressiveActionRequest: (options: HandleProgressiveActionRequestOptions) => Promise<Response | ProgressiveActionFormStateResult | null>;
|
|
151
174
|
handleServerActionRequest: (options: HandleServerActionRequestOptions) => Promise<Response | null>;
|
|
152
175
|
i18nConfig: NextI18nConfig | null;
|
|
176
|
+
imageConfig?: ImageConfig;
|
|
177
|
+
isDev: boolean;
|
|
153
178
|
isMiddlewareProxy: boolean;
|
|
154
179
|
loadPrerenderPagesRoutes?: () => Promise<unknown>;
|
|
155
180
|
makeThenableParams: MakeThenableParams;
|
|
@@ -4,27 +4,31 @@ import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
|
4
4
|
import { ACTION_REVALIDATED_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER } from "./headers.js";
|
|
5
5
|
import { isExternalUrl, matchRedirect, matchRewrite, preserveRedirectDestinationQuery, proxyExternalRequest, requestContextFromRequest, sanitizeDestination } from "../config/config-matchers.js";
|
|
6
6
|
import { notFoundResponse } from "./http-error-responses.js";
|
|
7
|
-
import { applyConfigHeadersToResponse, cloneRequestWithHeaders, cloneRequestWithUrl, filterInternalHeaders, normalizeTrailingSlash, resolvePublicFileRoute
|
|
7
|
+
import { applyConfigHeadersToResponse, cloneRequestWithHeaders, cloneRequestWithUrl, filterInternalHeaders, normalizeTrailingSlash, resolvePublicFileRoute } from "./request-pipeline.js";
|
|
8
8
|
import { headersContextFromRequest } from "../shims/headers.js";
|
|
9
9
|
import { ensureFetchPatch, setCurrentFetchSoftTags } from "../shims/fetch-cache.js";
|
|
10
|
-
import {
|
|
10
|
+
import { mergeRewriteQuery } from "../utils/query.js";
|
|
11
|
+
import { VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM, createRscRedirectLocation, hasRscCacheBustingSearchParam, resolveInvalidRscCacheBustingRequest, stripRscCacheBustingSearchParam, stripRscSuffix } from "./app-rsc-cache-busting.js";
|
|
11
12
|
import { getScriptNonceFromHeaderSources } from "./csp.js";
|
|
12
13
|
import { normalizeDefaultLocalePathname } from "./pages-i18n.js";
|
|
13
|
-
import { isImageOptimizationPath } from "./image-optimization.js";
|
|
14
|
+
import { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, isImageOptimizationPath, resolveDevImageRedirect } from "./image-optimization.js";
|
|
14
15
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
15
16
|
import "./app-page-response.js";
|
|
16
|
-
import {
|
|
17
|
+
import { createAppPprFallbackShells } from "./app-ppr-fallback-shell.js";
|
|
18
|
+
import { matchPrerenderRouteParamsPayload, readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
|
|
19
|
+
import { getRenderedConcreteUrlPathsForRoute } from "./pregenerated-concrete-paths.js";
|
|
20
|
+
import { pickRootParams, setRootParams } from "../shims/root-params.js";
|
|
21
|
+
import { flattenErrorCauses } from "../utils/error-cause.js";
|
|
17
22
|
import { applyAppMiddleware } from "./app-middleware.js";
|
|
18
23
|
import { buildPageCacheTags } from "./implicit-tags.js";
|
|
19
24
|
import { buildPostMwRequestContext } from "./app-post-middleware-context.js";
|
|
20
|
-
import { pickRootParams, setRootParams } from "../shims/root-params.js";
|
|
21
25
|
import { handleAppPrerenderEndpoint } from "./app-prerender-endpoints.js";
|
|
22
|
-
import { flattenErrorCauses } from "../utils/error-cause.js";
|
|
23
26
|
import { finalizeAppRscResponse } from "./app-rsc-response-finalizer.js";
|
|
24
27
|
import { normalizeRscRequest } from "./app-rsc-request-normalization.js";
|
|
25
28
|
import { handleMetadataRouteRequest } from "./metadata-route-response.js";
|
|
26
29
|
import { runWithPrerenderWorkUnit } from "./prerender-work-unit-setup.js";
|
|
27
30
|
//#region src/server/app-rsc-handler.ts
|
|
31
|
+
const STATIC_METADATA_CONFIG_HEADER_OVERRIDES = new Set(["cache-control"]);
|
|
28
32
|
function applyMiddlewareContextToResponse(response, middlewareContext) {
|
|
29
33
|
if (!middlewareContext.headers && middlewareContext.status == null) return response;
|
|
30
34
|
const headers = new Headers(response.headers);
|
|
@@ -38,6 +42,10 @@ function applyMiddlewareContextToResponse(response, middlewareContext) {
|
|
|
38
42
|
function hasProperty(value, key) {
|
|
39
43
|
return key in value;
|
|
40
44
|
}
|
|
45
|
+
function isEdgeRouteHandler(handler) {
|
|
46
|
+
if (!handler || typeof handler !== "object" || !hasProperty(handler, "runtime")) return false;
|
|
47
|
+
return handler.runtime === "edge" || handler.runtime === "experimental-edge";
|
|
48
|
+
}
|
|
41
49
|
function isExecutionContextLike(value) {
|
|
42
50
|
if (!value || typeof value !== "object") return false;
|
|
43
51
|
return hasProperty(value, "waitUntil") && typeof value.waitUntil === "function";
|
|
@@ -56,6 +64,17 @@ async function applyRewrite(options, cleanPathname) {
|
|
|
56
64
|
}
|
|
57
65
|
return rewritten;
|
|
58
66
|
}
|
|
67
|
+
function requestContextForResolvedUrl(requestContext, resolvedUrl, baseUrl) {
|
|
68
|
+
return {
|
|
69
|
+
cookies: requestContext.cookies,
|
|
70
|
+
headers: requestContext.headers,
|
|
71
|
+
host: requestContext.host,
|
|
72
|
+
query: new URL(resolvedUrl, baseUrl).searchParams
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function pathnameForResolvedUrl(resolvedUrl) {
|
|
76
|
+
return resolvedUrl.split("#", 1)[0].split("?", 1)[0];
|
|
77
|
+
}
|
|
59
78
|
function applyConfigHeadersToMiddlewareRedirect(response, options) {
|
|
60
79
|
if (response.status < 300 || response.status >= 400) return response;
|
|
61
80
|
if (!options.configHeaders.length) return response;
|
|
@@ -82,6 +101,13 @@ function requestWithoutRscCacheBustingSearchParam(request) {
|
|
|
82
101
|
stripRscCacheBustingSearchParam(url);
|
|
83
102
|
return cloneRequestWithUrl(request.body ? request.clone() : request, url.toString());
|
|
84
103
|
}
|
|
104
|
+
function requestWithoutRscSuffix(request) {
|
|
105
|
+
const url = new URL(request.url);
|
|
106
|
+
const pathname = stripRscSuffix(url.pathname);
|
|
107
|
+
if (pathname === url.pathname) return request;
|
|
108
|
+
url.pathname = pathname;
|
|
109
|
+
return cloneRequestWithUrl(request.body ? request.clone() : request, url.toString());
|
|
110
|
+
}
|
|
85
111
|
async function handleAppRscRequest(options, request, preMiddlewareRequestContext, isDataRequest) {
|
|
86
112
|
const handlerStart = process.env.NODE_ENV !== "production" ? performance.now() : 0;
|
|
87
113
|
if (process.env.NODE_ENV !== "production") {
|
|
@@ -92,6 +118,8 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
92
118
|
if (normalized instanceof Response) return normalized;
|
|
93
119
|
const { url, isRscRequest, interceptionContextHeader, mountedSlotsHeader, renderMode, clientReuseManifest } = normalized;
|
|
94
120
|
let { pathname, cleanPathname } = normalized;
|
|
121
|
+
let resolvedUrl = cleanPathname + url.search;
|
|
122
|
+
const getResolvedSearchParams = () => new URL(resolvedUrl, url).searchParams;
|
|
95
123
|
const canonicalPathname = cleanPathname;
|
|
96
124
|
const basePathState = {
|
|
97
125
|
basePath: options.basePath,
|
|
@@ -124,12 +152,14 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
124
152
|
request
|
|
125
153
|
});
|
|
126
154
|
if (rscCacheBustingRedirect) return rscCacheBustingRedirect;
|
|
127
|
-
const
|
|
155
|
+
const normalizedUserlandRequest = requestWithoutRscSuffix(request);
|
|
156
|
+
const userlandRequest = requestWithoutRscCacheBustingSearchParam(normalizedUserlandRequest);
|
|
128
157
|
const middlewareContext = {
|
|
129
158
|
headers: null,
|
|
130
159
|
requestHeaders: null,
|
|
131
160
|
status: null
|
|
132
161
|
};
|
|
162
|
+
let didMiddlewareRewrite = false;
|
|
133
163
|
if (options.middlewareModule) {
|
|
134
164
|
const middlewareResult = await applyAppMiddleware({
|
|
135
165
|
basePath: options.basePath,
|
|
@@ -149,30 +179,46 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
149
179
|
requestContext: preMiddlewareRequestContext
|
|
150
180
|
});
|
|
151
181
|
cleanPathname = middlewareResult.cleanPathname;
|
|
182
|
+
didMiddlewareRewrite = cleanPathname !== normalized.cleanPathname;
|
|
152
183
|
if (middlewareResult.search !== null) url.search = middlewareResult.search;
|
|
184
|
+
resolvedUrl = cleanPathname + url.search;
|
|
153
185
|
}
|
|
154
186
|
const scriptNonce = getScriptNonceFromHeaderSources(request.headers, middlewareContext.headers);
|
|
155
187
|
const postMiddlewareRequestContext = buildPostMwRequestContext(userlandRequest);
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
188
|
+
for (const rewrite of options.configRewrites.beforeFiles) {
|
|
189
|
+
const beforeFilesRewrite = await applyRewrite({
|
|
190
|
+
basePathState,
|
|
191
|
+
clearRequestContext: options.clearRequestContext,
|
|
192
|
+
request: normalizedUserlandRequest,
|
|
193
|
+
requestContext: requestContextForResolvedUrl(postMiddlewareRequestContext, resolvedUrl, url),
|
|
194
|
+
rewrites: [rewrite]
|
|
195
|
+
}, matchPathname(cleanPathname));
|
|
196
|
+
if (beforeFilesRewrite instanceof Response) return beforeFilesRewrite;
|
|
197
|
+
if (beforeFilesRewrite) {
|
|
198
|
+
resolvedUrl = mergeRewriteQuery(resolvedUrl, beforeFilesRewrite);
|
|
199
|
+
cleanPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
165
202
|
if (isImageOptimizationPath(cleanPathname)) {
|
|
166
|
-
const
|
|
167
|
-
if (
|
|
168
|
-
return Response.redirect(new URL(
|
|
203
|
+
const imageRedirect = resolveDevImageRedirect(url, [...options.imageConfig?.deviceSizes ?? DEFAULT_DEVICE_SIZES, ...options.imageConfig?.imageSizes ?? DEFAULT_IMAGE_SIZES], options.imageConfig?.qualities, { isDev: options.isDev });
|
|
204
|
+
if (!imageRedirect) return new Response("Invalid image optimization parameters", { status: 400 });
|
|
205
|
+
return Response.redirect(new URL(imageRedirect, url.origin).href, 302);
|
|
169
206
|
}
|
|
170
207
|
const metadataRouteResponse = await handleMetadataRouteRequest({
|
|
171
208
|
metadataRoutes: options.metadataRoutes,
|
|
172
209
|
cleanPathname,
|
|
173
210
|
makeThenableParams: options.makeThenableParams
|
|
174
211
|
});
|
|
175
|
-
if (metadataRouteResponse)
|
|
212
|
+
if (metadataRouteResponse) {
|
|
213
|
+
applyConfigHeadersToResponse(metadataRouteResponse.headers, {
|
|
214
|
+
basePathState,
|
|
215
|
+
configHeaders: options.configHeaders,
|
|
216
|
+
overwriteExisting: STATIC_METADATA_CONFIG_HEADER_OVERRIDES,
|
|
217
|
+
pathname: matchPathname(cleanPathname),
|
|
218
|
+
requestContext: preMiddlewareRequestContext
|
|
219
|
+
});
|
|
220
|
+
return applyMiddlewareContextToResponse(metadataRouteResponse, middlewareContext);
|
|
221
|
+
}
|
|
176
222
|
const publicFileResponse = resolvePublicFileRoute({
|
|
177
223
|
cleanPathname,
|
|
178
224
|
middlewareContext,
|
|
@@ -184,10 +230,13 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
184
230
|
options.clearRequestContext();
|
|
185
231
|
return publicFileResponse;
|
|
186
232
|
}
|
|
187
|
-
|
|
233
|
+
stripRscCacheBustingSearchParam(url);
|
|
234
|
+
const resolved = new URL(resolvedUrl, url);
|
|
235
|
+
stripRscCacheBustingSearchParam(resolved);
|
|
236
|
+
resolvedUrl = resolved.pathname + resolved.search + resolved.hash;
|
|
188
237
|
options.setNavigationContext({
|
|
189
238
|
pathname: canonicalPathname,
|
|
190
|
-
searchParams:
|
|
239
|
+
searchParams: getResolvedSearchParams(),
|
|
191
240
|
params: {}
|
|
192
241
|
});
|
|
193
242
|
const preActionMatch = options.matchRoute(cleanPathname);
|
|
@@ -216,53 +265,85 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
216
265
|
middlewareContext,
|
|
217
266
|
mountedSlotsHeader,
|
|
218
267
|
request,
|
|
219
|
-
searchParams:
|
|
268
|
+
searchParams: getResolvedSearchParams()
|
|
220
269
|
});
|
|
221
270
|
if (serverActionResponse) return serverActionResponse;
|
|
222
271
|
let match = preActionMatch;
|
|
223
|
-
|
|
272
|
+
const renderPagesForMatchKind = async (matchKind) => match === null || match.route.isDynamic ? await options.renderPagesFallback?.({
|
|
273
|
+
appRouteMatch: match ?? null,
|
|
274
|
+
allowRscDocumentFallback: didMiddlewareRewrite,
|
|
275
|
+
isRscRequest,
|
|
276
|
+
matchKind,
|
|
277
|
+
middlewareContext,
|
|
278
|
+
pathname: resolvedUrl,
|
|
279
|
+
request,
|
|
280
|
+
url
|
|
281
|
+
}) ?? null : null;
|
|
282
|
+
const staticPagesFallbackResponse = await renderPagesForMatchKind("static");
|
|
283
|
+
if (staticPagesFallbackResponse) {
|
|
284
|
+
options.clearRequestContext();
|
|
285
|
+
return staticPagesFallbackResponse;
|
|
286
|
+
}
|
|
287
|
+
if (!match || match.route.isDynamic) for (const rewrite of options.configRewrites.afterFiles) {
|
|
224
288
|
const afterFilesRewrite = await applyRewrite({
|
|
225
289
|
basePathState,
|
|
226
290
|
clearRequestContext: options.clearRequestContext,
|
|
227
|
-
request:
|
|
228
|
-
requestContext: postMiddlewareRequestContext,
|
|
229
|
-
rewrites:
|
|
291
|
+
request: normalizedUserlandRequest,
|
|
292
|
+
requestContext: requestContextForResolvedUrl(postMiddlewareRequestContext, resolvedUrl, url),
|
|
293
|
+
rewrites: [rewrite]
|
|
230
294
|
}, matchPathname(cleanPathname));
|
|
231
295
|
if (afterFilesRewrite instanceof Response) return afterFilesRewrite;
|
|
232
|
-
if (afterFilesRewrite)
|
|
233
|
-
|
|
234
|
-
|
|
296
|
+
if (!afterFilesRewrite) continue;
|
|
297
|
+
resolvedUrl = mergeRewriteQuery(resolvedUrl, afterFilesRewrite);
|
|
298
|
+
cleanPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
299
|
+
match = options.matchRoute(cleanPathname);
|
|
300
|
+
const rewrittenStaticPagesResponse = await renderPagesForMatchKind("static");
|
|
301
|
+
if (rewrittenStaticPagesResponse) {
|
|
302
|
+
options.clearRequestContext();
|
|
303
|
+
return rewrittenStaticPagesResponse;
|
|
304
|
+
}
|
|
305
|
+
const rewrittenDynamicPagesResponse = await renderPagesForMatchKind("dynamic");
|
|
306
|
+
if (rewrittenDynamicPagesResponse) {
|
|
307
|
+
options.clearRequestContext();
|
|
308
|
+
return rewrittenDynamicPagesResponse;
|
|
235
309
|
}
|
|
310
|
+
if (match) break;
|
|
236
311
|
}
|
|
237
|
-
|
|
312
|
+
const dynamicPagesFallbackResponse = await renderPagesForMatchKind("dynamic");
|
|
313
|
+
if (dynamicPagesFallbackResponse) {
|
|
314
|
+
options.clearRequestContext();
|
|
315
|
+
return dynamicPagesFallbackResponse;
|
|
316
|
+
}
|
|
317
|
+
if (!match) for (const rewrite of options.configRewrites.fallback) {
|
|
238
318
|
const fallbackRewrite = await applyRewrite({
|
|
239
319
|
basePathState,
|
|
240
320
|
clearRequestContext: options.clearRequestContext,
|
|
241
|
-
request:
|
|
242
|
-
requestContext: postMiddlewareRequestContext,
|
|
243
|
-
rewrites:
|
|
321
|
+
request: normalizedUserlandRequest,
|
|
322
|
+
requestContext: requestContextForResolvedUrl(postMiddlewareRequestContext, resolvedUrl, url),
|
|
323
|
+
rewrites: [rewrite]
|
|
244
324
|
}, matchPathname(cleanPathname));
|
|
245
325
|
if (fallbackRewrite instanceof Response) return fallbackRewrite;
|
|
246
|
-
if (fallbackRewrite)
|
|
247
|
-
|
|
248
|
-
|
|
326
|
+
if (!fallbackRewrite) continue;
|
|
327
|
+
resolvedUrl = mergeRewriteQuery(resolvedUrl, fallbackRewrite);
|
|
328
|
+
cleanPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
329
|
+
match = options.matchRoute(cleanPathname);
|
|
330
|
+
const rewrittenStaticPagesResponse = await renderPagesForMatchKind("static");
|
|
331
|
+
if (rewrittenStaticPagesResponse) {
|
|
332
|
+
options.clearRequestContext();
|
|
333
|
+
return rewrittenStaticPagesResponse;
|
|
334
|
+
}
|
|
335
|
+
const rewrittenDynamicPagesResponse = await renderPagesForMatchKind("dynamic");
|
|
336
|
+
if (rewrittenDynamicPagesResponse) {
|
|
337
|
+
options.clearRequestContext();
|
|
338
|
+
return rewrittenDynamicPagesResponse;
|
|
249
339
|
}
|
|
340
|
+
if (match) break;
|
|
250
341
|
}
|
|
251
342
|
if (!match) {
|
|
252
343
|
if (process.env.NODE_ENV !== "production" && canonicalPathname === "/favicon.ico") {
|
|
253
344
|
options.clearRequestContext();
|
|
254
345
|
return new Response("", { status: 404 });
|
|
255
346
|
}
|
|
256
|
-
const pagesFallbackResponse = await options.renderPagesFallback?.({
|
|
257
|
-
isRscRequest,
|
|
258
|
-
middlewareContext,
|
|
259
|
-
request,
|
|
260
|
-
url
|
|
261
|
-
});
|
|
262
|
-
if (pagesFallbackResponse) {
|
|
263
|
-
options.clearRequestContext();
|
|
264
|
-
return pagesFallbackResponse;
|
|
265
|
-
}
|
|
266
347
|
const renderedNotFoundResponse = await options.renderNotFound({
|
|
267
348
|
isRscRequest,
|
|
268
349
|
middlewareContext,
|
|
@@ -278,25 +359,37 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
278
359
|
}
|
|
279
360
|
const { route, params } = match;
|
|
280
361
|
if (options.ensureRouteLoaded) await options.ensureRouteLoaded(route);
|
|
281
|
-
const
|
|
282
|
-
const prerenderRouteParams =
|
|
362
|
+
const prerenderRouteParamsMatch = matchPrerenderRouteParamsPayload(readTrustedPrerenderRouteParams(request), route.pattern, params);
|
|
363
|
+
const prerenderRouteParams = prerenderRouteParamsMatch?.params ?? null;
|
|
364
|
+
const isPrerenderFallbackShell = prerenderRouteParamsMatch?.kind === "fallback-shell";
|
|
283
365
|
const renderParams = prerenderRouteParams ?? params;
|
|
366
|
+
const resolvedSearchParams = getResolvedSearchParams();
|
|
367
|
+
const runtimeFallbackShells = options.cacheComponents === true && request.method === "GET" && !isRscRequest && !isPrerenderFallbackShell && route.params ? createAppPprFallbackShells({
|
|
368
|
+
params: route.params,
|
|
369
|
+
pattern: route.pattern,
|
|
370
|
+
rootParamNames: route.rootParamNames
|
|
371
|
+
}, params) : [];
|
|
284
372
|
options.setNavigationContext({
|
|
285
373
|
pathname: canonicalPathname,
|
|
286
|
-
searchParams:
|
|
374
|
+
searchParams: resolvedSearchParams,
|
|
287
375
|
params: renderParams
|
|
288
376
|
});
|
|
289
377
|
const rootParams = pickRootParams(renderParams, route.rootParamNames);
|
|
290
378
|
setRootParams(rootParams);
|
|
291
379
|
if (route.routeHandler) {
|
|
292
380
|
setCurrentFetchSoftTags(buildPageCacheTags(cleanPathname, [], [...route.routeSegments], "route"));
|
|
381
|
+
const routeHandlerRequest = isEdgeRouteHandler(route.routeHandler) ? userlandRequest : normalizedUserlandRequest;
|
|
382
|
+
const routeHandlerUrl = new URL(routeHandlerRequest.url);
|
|
383
|
+
const internalRscValues = isEdgeRouteHandler(route.routeHandler) ? [] : routeHandlerUrl.searchParams.getAll(VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM);
|
|
384
|
+
routeHandlerUrl.search = resolvedSearchParams.toString();
|
|
385
|
+
for (const internalRscValue of internalRscValues) routeHandlerUrl.searchParams.append(VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM, internalRscValue);
|
|
293
386
|
return options.dispatchMatchedRouteHandler({
|
|
294
387
|
cleanPathname,
|
|
295
388
|
middlewareContext,
|
|
296
389
|
params: route.isDynamic ? renderParams : null,
|
|
297
|
-
request,
|
|
390
|
+
request: new Request(routeHandlerUrl, routeHandlerRequest),
|
|
298
391
|
route,
|
|
299
|
-
searchParams:
|
|
392
|
+
searchParams: resolvedSearchParams
|
|
300
393
|
});
|
|
301
394
|
}
|
|
302
395
|
const pageResponse = await options.dispatchMatchedPage({
|
|
@@ -313,12 +406,19 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
313
406
|
middlewareContext,
|
|
314
407
|
mountedSlotsHeader,
|
|
315
408
|
params: renderParams,
|
|
316
|
-
|
|
409
|
+
pprFallbackCacheShells: runtimeFallbackShells,
|
|
410
|
+
pprFallbackShell: isPrerenderFallbackShell ? {
|
|
411
|
+
fallbackParamNames: prerenderRouteParamsMatch.fallbackParamNames,
|
|
412
|
+
routePattern: route.pattern
|
|
413
|
+
} : void 0,
|
|
414
|
+
renderedConcreteUrlPaths: getRenderedConcreteUrlPathsForRoute(route.pattern),
|
|
415
|
+
skipStaticParamsValidation: isPrerenderFallbackShell,
|
|
416
|
+
staticParamsValidationParams: prerenderRouteParams === null || isPrerenderFallbackShell ? void 0 : params,
|
|
317
417
|
rootParams,
|
|
318
418
|
request,
|
|
319
419
|
route,
|
|
320
420
|
scriptNonce,
|
|
321
|
-
searchParams:
|
|
421
|
+
searchParams: resolvedSearchParams,
|
|
322
422
|
renderMode
|
|
323
423
|
});
|
|
324
424
|
if (isProgressiveActionRender) return applyProgressiveActionSideEffects(pageResponse, progressiveActionResult);
|
|
@@ -29,6 +29,7 @@ type AppRscInterceptForMatching = {
|
|
|
29
29
|
* @see https://github.com/vercel/next.js/blob/canary/packages/next/src/lib/generate-interception-routes-rewrites.ts
|
|
30
30
|
*/
|
|
31
31
|
sourceMatchPattern?: string;
|
|
32
|
+
sourcePageSegments?: readonly string[];
|
|
32
33
|
interceptLayouts: readonly unknown[];
|
|
33
34
|
page: unknown;
|
|
34
35
|
__pageLoader?: (() => Promise<unknown>) | null;
|
|
@@ -41,6 +42,7 @@ type AppRscSlotForMatching = {
|
|
|
41
42
|
type AppRscSiblingInterceptForMatching = {
|
|
42
43
|
targetPattern: string;
|
|
43
44
|
sourceMatchPattern: string | null;
|
|
45
|
+
sourcePageSegments?: readonly string[];
|
|
44
46
|
slotId: string | null;
|
|
45
47
|
interceptLayouts: readonly unknown[];
|
|
46
48
|
page: unknown;
|
|
@@ -63,6 +65,7 @@ type AppRscInterceptLookupEntry = {
|
|
|
63
65
|
targetPatternParts: string[];
|
|
64
66
|
sourceMatchPattern: string | null;
|
|
65
67
|
sourceMatchPatternParts: string[] | null;
|
|
68
|
+
sourcePageSegments: readonly string[] | null;
|
|
66
69
|
interceptLayouts: readonly unknown[];
|
|
67
70
|
page: unknown;
|
|
68
71
|
__pageLoader?: (() => Promise<unknown>) | null;
|
|
@@ -78,6 +78,7 @@ function createInterceptLookup(routes) {
|
|
|
78
78
|
targetPatternParts: intercept.targetPattern.split("/").filter(Boolean),
|
|
79
79
|
sourceMatchPattern,
|
|
80
80
|
sourceMatchPatternParts,
|
|
81
|
+
sourcePageSegments: intercept.sourcePageSegments ?? null,
|
|
81
82
|
interceptLayouts: intercept.interceptLayouts,
|
|
82
83
|
page: intercept.page,
|
|
83
84
|
__pageLoader: intercept.__pageLoader,
|
|
@@ -96,6 +97,7 @@ function createInterceptLookup(routes) {
|
|
|
96
97
|
targetPatternParts: intercept.targetPattern.split("/").filter(Boolean),
|
|
97
98
|
sourceMatchPattern,
|
|
98
99
|
sourceMatchPatternParts,
|
|
100
|
+
sourcePageSegments: intercept.sourcePageSegments ?? null,
|
|
99
101
|
interceptLayouts: intercept.interceptLayouts,
|
|
100
102
|
page: intercept.page,
|
|
101
103
|
__pageLoader: intercept.__pageLoader,
|
|
@@ -33,6 +33,14 @@ type ResolveAppPageSegmentConfigOptions = {
|
|
|
33
33
|
*/
|
|
34
34
|
declare function resolveAppPageSegmentConfig(options: ResolveAppPageSegmentConfigOptions): EffectiveAppPageSegmentConfig;
|
|
35
35
|
declare function resolveAppPageFetchCacheMode(options: ResolveAppPageSegmentConfigOptions): FetchCacheMode | null;
|
|
36
|
+
/**
|
|
37
|
+
* Resolve the `fetchCache` segment config exported by a route handler module.
|
|
38
|
+
*
|
|
39
|
+
* Route handlers have no layout chain, so the module's own export applies
|
|
40
|
+
* directly. Mirrors upstream's app-route module, which copies
|
|
41
|
+
* `userland.fetchCache` into the work store before invoking the handler.
|
|
42
|
+
*/
|
|
43
|
+
declare function resolveAppRouteHandlerFetchCacheMode(handler: Pick<AppRouteSegmentConfigModule, "fetchCache">): FetchCacheMode | null;
|
|
36
44
|
declare function isEdgeRuntime(runtime: string | undefined): boolean;
|
|
37
45
|
//#endregion
|
|
38
|
-
export { isEdgeRuntime, resolveAppPageFetchCacheMode, resolveAppPageSegmentConfig };
|
|
46
|
+
export { isEdgeRuntime, resolveAppPageFetchCacheMode, resolveAppPageSegmentConfig, resolveAppRouteHandlerFetchCacheMode };
|