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,91 @@
|
|
|
1
|
+
import { consumeDynamicUsage, consumeInvalidDynamicUsageError } from "../shims/headers.js";
|
|
2
|
+
import { _consumeRequestScopedCacheLife } from "../shims/cache.js";
|
|
3
|
+
import { getCollectedFetchTags } from "../shims/fetch-cache.js";
|
|
4
|
+
import { readStreamAsText } from "../utils/text-stream.js";
|
|
5
|
+
import { teeAppPageRscStreamForCapture } from "./app-page-execution.js";
|
|
6
|
+
import { consumeAppPageRenderObservationState, createAppPageHtmlOutputScope, createAppPageRenderObservation, createAppPageRscOutputScope } from "./app-page-render-observation.js";
|
|
7
|
+
import { isAppSsrRenderResult } from "./app-page-stream.js";
|
|
8
|
+
import { buildAppPageTags } from "./implicit-tags.js";
|
|
9
|
+
//#region src/server/app-page-cache-render.ts
|
|
10
|
+
/**
|
|
11
|
+
* Render an App page element to HTML (and optionally its RSC payload) for cache
|
|
12
|
+
* storage. Combines the RSC stream, SSR handler, observation consumption, and
|
|
13
|
+
* cache-tag construction used by both normal ISR revalidation and PPR fallback
|
|
14
|
+
* shell regeneration.
|
|
15
|
+
*/
|
|
16
|
+
async function renderAppPageCacheArtifacts(options) {
|
|
17
|
+
const rscCapture = teeAppPageRscStreamForCapture(options.renderToReadableStream(options.element, { onError: options.onError }), options.captureRscData);
|
|
18
|
+
const capturedRscDataRef = { value: null };
|
|
19
|
+
const htmlResult = await (await options.loadSsrHandler()).handleSsr(rscCapture.ssrStream, options.getNavigationContext(), {
|
|
20
|
+
links: options.getFontLinks(),
|
|
21
|
+
styles: options.getFontStyles(),
|
|
22
|
+
preloads: options.getFontPreloads()
|
|
23
|
+
}, {
|
|
24
|
+
basePath: options.basePath,
|
|
25
|
+
clientTraceMetadata: options.clientTraceMetadata,
|
|
26
|
+
reactMaxHeadersLength: options.reactMaxHeadersLength,
|
|
27
|
+
rootParams: options.rootParams,
|
|
28
|
+
waitForAllReady: options.waitForAllReady,
|
|
29
|
+
...rscCapture.sideStream ? {
|
|
30
|
+
sideStream: rscCapture.sideStream,
|
|
31
|
+
capturedRscDataRef
|
|
32
|
+
} : {}
|
|
33
|
+
});
|
|
34
|
+
const html = await readStreamAsText(isAppSsrRenderResult(htmlResult) ? htmlResult.htmlStream : htmlResult);
|
|
35
|
+
let rscData;
|
|
36
|
+
if (options.captureRscData) {
|
|
37
|
+
const capturedPromise = capturedRscDataRef.value;
|
|
38
|
+
if (!capturedPromise) throw new Error("[vinext] Expected captured RSC data while rendering app page cache artifacts");
|
|
39
|
+
rscData = await capturedPromise;
|
|
40
|
+
}
|
|
41
|
+
const cacheLife = _consumeRequestScopedCacheLife();
|
|
42
|
+
const tags = buildAppPageTags(options.cleanPathname, getCollectedFetchTags(), options.route.routeSegments);
|
|
43
|
+
const observationState = consumeAppPageRenderObservationState();
|
|
44
|
+
consumeInvalidDynamicUsageError();
|
|
45
|
+
consumeDynamicUsage();
|
|
46
|
+
const result = {
|
|
47
|
+
html,
|
|
48
|
+
htmlRenderObservation: createAppPageRenderObservation({
|
|
49
|
+
boundaryOutcome: { kind: "success" },
|
|
50
|
+
cacheability: "public",
|
|
51
|
+
cacheTags: tags,
|
|
52
|
+
cleanPathname: options.cleanPathname,
|
|
53
|
+
completeness: "complete",
|
|
54
|
+
output: createAppPageHtmlOutputScope({
|
|
55
|
+
element: options.element,
|
|
56
|
+
renderEpoch: null,
|
|
57
|
+
rootBoundaryId: null,
|
|
58
|
+
routePattern: options.route.pattern
|
|
59
|
+
}),
|
|
60
|
+
params: options.navigationParams,
|
|
61
|
+
state: observationState
|
|
62
|
+
}),
|
|
63
|
+
tags,
|
|
64
|
+
cacheControl: typeof cacheLife?.revalidate === "number" ? {
|
|
65
|
+
revalidate: cacheLife.revalidate,
|
|
66
|
+
expire: cacheLife.expire
|
|
67
|
+
} : void 0
|
|
68
|
+
};
|
|
69
|
+
if (options.captureRscData) {
|
|
70
|
+
result.rscData = rscData;
|
|
71
|
+
result.rscRenderObservation = createAppPageRenderObservation({
|
|
72
|
+
boundaryOutcome: { kind: "success" },
|
|
73
|
+
cacheability: "public",
|
|
74
|
+
cacheTags: tags,
|
|
75
|
+
cleanPathname: options.cleanPathname,
|
|
76
|
+
completeness: "complete",
|
|
77
|
+
output: createAppPageRscOutputScope({
|
|
78
|
+
element: options.element,
|
|
79
|
+
mountedSlotsHeader: options.mountedSlotsHeader,
|
|
80
|
+
renderEpoch: null,
|
|
81
|
+
rootBoundaryId: null,
|
|
82
|
+
routePattern: options.route.pattern
|
|
83
|
+
}),
|
|
84
|
+
params: options.navigationParams,
|
|
85
|
+
state: observationState
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
export { renderAppPageCacheArtifacts };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { RenderObservation } from "./cache-proof.js";
|
|
2
2
|
import { CacheControlMetadata, CachedAppPageValue } from "../shims/cache.js";
|
|
3
|
+
import { AppPageRenderObservationState } from "./app-page-render-observation.js";
|
|
3
4
|
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
4
5
|
import { ISRCacheEntry } from "./isr-cache.js";
|
|
5
|
-
import { AppPageRenderObservationState } from "./app-page-render-observation.js";
|
|
6
6
|
|
|
7
7
|
//#region src/server/app-page-cache.d.ts
|
|
8
8
|
type AppPageDebugLogger = (event: string, detail: string) => void;
|
|
@@ -70,6 +70,19 @@ type ReadAppPageCacheResponseOptions = {
|
|
|
70
70
|
renderFreshPageForCache: () => Promise<AppPageCacheRenderResult>;
|
|
71
71
|
scheduleBackgroundRegeneration: AppPageBackgroundRegenerator;
|
|
72
72
|
};
|
|
73
|
+
type ReadAppPageFallbackShellCacheResponseOptions = {
|
|
74
|
+
clearRequestContext: () => void;
|
|
75
|
+
expireSeconds?: number;
|
|
76
|
+
fallbackPathname: string;
|
|
77
|
+
isEdgeRuntime?: boolean;
|
|
78
|
+
isrDebug?: AppPageDebugLogger;
|
|
79
|
+
isrGet: AppPageCacheGetter;
|
|
80
|
+
isrHtmlKey: (pathname: string) => string;
|
|
81
|
+
middlewareHeaders?: Headers | null;
|
|
82
|
+
middlewareStatus?: number | null;
|
|
83
|
+
revalidateSeconds: number;
|
|
84
|
+
rewriteHtml: (html: string) => string;
|
|
85
|
+
};
|
|
73
86
|
type FinalizeAppPageHtmlCacheResponseOptions = {
|
|
74
87
|
capturedDynamicUsageBeforeContextCleanup?: () => boolean;
|
|
75
88
|
capturedRscDataPromise: Promise<ArrayBuffer> | null;
|
|
@@ -113,8 +126,9 @@ type ScheduleAppPageRscCacheWriteOptions = {
|
|
|
113
126
|
declare function buildAppPageCacheTags(pathname: string, extraTags: readonly string[]): string[];
|
|
114
127
|
declare function buildAppPageCachedResponse(cachedValue: CachedAppPageValue, options: BuildAppPageCachedResponseOptions): Response | null;
|
|
115
128
|
declare function readAppPageCacheResponse(options: ReadAppPageCacheResponseOptions): Promise<Response | null>;
|
|
129
|
+
declare function readAppPageFallbackShellCacheResponse(options: ReadAppPageFallbackShellCacheResponseOptions): Promise<Response | null>;
|
|
116
130
|
declare function finalizeAppPageHtmlCacheResponse(response: Response, options: FinalizeAppPageHtmlCacheResponseOptions): Response;
|
|
117
131
|
declare function finalizeAppPageRscCacheResponse(response: Response, options: ScheduleAppPageRscCacheWriteOptions): Response;
|
|
118
132
|
declare function scheduleAppPageRscCacheWrite(options: ScheduleAppPageRscCacheWriteOptions): boolean;
|
|
119
133
|
//#endregion
|
|
120
|
-
export { AppPageCacheOutcomeMetric, buildAppPageCacheTags, buildAppPageCachedResponse, finalizeAppPageHtmlCacheResponse, finalizeAppPageRscCacheResponse, readAppPageCacheResponse, scheduleAppPageRscCacheWrite };
|
|
134
|
+
export { AppPageCacheOutcomeMetric, buildAppPageCacheTags, buildAppPageCachedResponse, finalizeAppPageHtmlCacheResponse, finalizeAppPageRscCacheResponse, readAppPageCacheResponse, readAppPageFallbackShellCacheResponse, scheduleAppPageRscCacheWrite };
|
|
@@ -10,6 +10,7 @@ import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js
|
|
|
10
10
|
import { applyEdgeRuntimeHeader } from "./app-page-response.js";
|
|
11
11
|
import { hasCompleteNegativeRequestApiProof } from "./cache-proof.js";
|
|
12
12
|
import { createEmptyAppPageRenderObservationState } from "./app-page-render-observation.js";
|
|
13
|
+
import { isAppPprDynamicFallbackShellHtml } from "./app-ppr-fallback-shell.js";
|
|
13
14
|
//#region src/server/app-page-cache.ts
|
|
14
15
|
/**
|
|
15
16
|
* Apply the CDN cache adapter's headers to a freshly-streamed response whose
|
|
@@ -121,6 +122,29 @@ function buildAppPageCachedResponse(cachedValue, options) {
|
|
|
121
122
|
headers: htmlHeaders
|
|
122
123
|
});
|
|
123
124
|
}
|
|
125
|
+
async function serveAppPageCachedHtml(options, transformValue) {
|
|
126
|
+
if (typeof options.cachedValue.html !== "string" || options.cachedValue.html.length === 0) {
|
|
127
|
+
if (options.cached?.isStale) options.scheduleRegeneration();
|
|
128
|
+
options.isrDebug?.(options.emptyDebugMessage, options.pathname);
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
const cacheState = options.cached?.isStale ? "STALE" : "HIT";
|
|
132
|
+
if (options.cached?.isStale) options.scheduleRegeneration();
|
|
133
|
+
const response = buildAppPageCachedResponse(transformValue ? transformValue(options.cachedValue) : options.cachedValue, {
|
|
134
|
+
cacheState,
|
|
135
|
+
cacheControl: options.cached?.value.cacheControl,
|
|
136
|
+
expireSeconds: options.expireSeconds,
|
|
137
|
+
isEdgeRuntime: options.isEdgeRuntime,
|
|
138
|
+
isRscRequest: false,
|
|
139
|
+
middlewareHeaders: options.middlewareHeaders,
|
|
140
|
+
middlewareStatus: options.middlewareStatus,
|
|
141
|
+
revalidateSeconds: options.revalidateSeconds
|
|
142
|
+
});
|
|
143
|
+
if (!response) return null;
|
|
144
|
+
options.isrDebug?.(`${cacheState} (${options.stateDebugLabel})`, options.pathname);
|
|
145
|
+
options.clearRequestContext();
|
|
146
|
+
return response;
|
|
147
|
+
}
|
|
124
148
|
async function readAppPageCacheResponse(options) {
|
|
125
149
|
const isrKey = options.isRscRequest ? options.isrRscKey(options.cleanPathname, options.mountedSlotsHeader, options.renderMode, options.interceptionContext) : options.isrHtmlKey(options.cleanPathname);
|
|
126
150
|
const artifact = options.isRscRequest ? "rsc" : "html";
|
|
@@ -239,6 +263,43 @@ async function readAppPageCacheResponse(options) {
|
|
|
239
263
|
}
|
|
240
264
|
return null;
|
|
241
265
|
}
|
|
266
|
+
async function readAppPageFallbackShellCacheResponse(options) {
|
|
267
|
+
const isrKey = options.isrHtmlKey(options.fallbackPathname);
|
|
268
|
+
try {
|
|
269
|
+
const cached = await options.isrGet(isrKey);
|
|
270
|
+
const cachedValue = getCachedAppPageValue(cached);
|
|
271
|
+
if (!cachedValue) {
|
|
272
|
+
options.isrDebug?.("MISS (fallback shell)", options.fallbackPathname);
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
if (isAppPprDynamicFallbackShellHtml(cachedValue.html)) {
|
|
276
|
+
options.isrDebug?.("MISS (dynamic fallback shell requires resume)", options.fallbackPathname);
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
return await serveAppPageCachedHtml({
|
|
280
|
+
cached,
|
|
281
|
+
cachedValue,
|
|
282
|
+
clearRequestContext: options.clearRequestContext,
|
|
283
|
+
emptyDebugMessage: "MISS (empty fallback shell)",
|
|
284
|
+
expireSeconds: options.expireSeconds,
|
|
285
|
+
isEdgeRuntime: options.isEdgeRuntime,
|
|
286
|
+
isrDebug: options.isrDebug,
|
|
287
|
+
middlewareHeaders: options.middlewareHeaders,
|
|
288
|
+
middlewareStatus: options.middlewareStatus,
|
|
289
|
+
pathname: options.fallbackPathname,
|
|
290
|
+
revalidateSeconds: options.revalidateSeconds,
|
|
291
|
+
scheduleRegeneration() {},
|
|
292
|
+
stateDebugLabel: "fallback shell"
|
|
293
|
+
}, (value) => ({
|
|
294
|
+
...value,
|
|
295
|
+
html: options.rewriteHtml(value.html)
|
|
296
|
+
}));
|
|
297
|
+
} catch (isrReadError) {
|
|
298
|
+
options.isrDebug?.("MISS (fallback shell read error)", options.fallbackPathname);
|
|
299
|
+
console.error("[vinext] ISR fallback shell cache read error:", isrReadError);
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
242
303
|
function finalizeAppPageHtmlCacheResponse(response, options) {
|
|
243
304
|
if (!response.body) return response;
|
|
244
305
|
const [streamForClient, streamForCache] = response.body.tee();
|
|
@@ -334,4 +395,4 @@ function scheduleAppPageRscCacheWrite(options) {
|
|
|
334
395
|
return true;
|
|
335
396
|
}
|
|
336
397
|
//#endregion
|
|
337
|
-
export { buildAppPageCacheTags, buildAppPageCachedResponse, finalizeAppPageHtmlCacheResponse, finalizeAppPageRscCacheResponse, readAppPageCacheResponse, scheduleAppPageRscCacheWrite };
|
|
398
|
+
export { buildAppPageCacheTags, buildAppPageCachedResponse, finalizeAppPageHtmlCacheResponse, finalizeAppPageRscCacheResponse, readAppPageCacheResponse, readAppPageFallbackShellCacheResponse, scheduleAppPageRscCacheWrite };
|
|
@@ -11,6 +11,7 @@ import { AppLayoutParamAccessTracker } from "./app-layout-param-observation.js";
|
|
|
11
11
|
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
12
12
|
import { ISRCacheEntry } from "./isr-cache.js";
|
|
13
13
|
import { FetchCacheMode } from "../shims/fetch-cache.js";
|
|
14
|
+
import { AppPagePprFallbackCacheShell } from "./app-ppr-fallback-shell.js";
|
|
14
15
|
import { ValidateAppPageDynamicParamsOptions } from "./app-page-request.js";
|
|
15
16
|
import { ReactNode } from "react";
|
|
16
17
|
import { ReactFormState } from "react-dom/client";
|
|
@@ -36,6 +37,7 @@ type AppPageDispatchIntercept<TPage = unknown> = {
|
|
|
36
37
|
slotId?: string | null;
|
|
37
38
|
slotKey: string;
|
|
38
39
|
sourceRouteIndex: number;
|
|
40
|
+
sourcePageSegments?: readonly string[] | null;
|
|
39
41
|
};
|
|
40
42
|
type AppPageDispatchInterceptOptions<TPage = unknown> = {
|
|
41
43
|
interceptionContext: string | null;
|
|
@@ -45,6 +47,7 @@ type AppPageDispatchInterceptOptions<TPage = unknown> = {
|
|
|
45
47
|
interceptSlotId?: string | null;
|
|
46
48
|
interceptSlotKey: string;
|
|
47
49
|
interceptSourceMatchedUrl?: string | null;
|
|
50
|
+
interceptSourcePageSegments?: readonly string[] | null;
|
|
48
51
|
};
|
|
49
52
|
type AppPageModule = {
|
|
50
53
|
default?: unknown;
|
|
@@ -120,6 +123,7 @@ type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
|
|
|
120
123
|
getNavigationContext: () => NavigationContext | null;
|
|
121
124
|
getSourceRoute: (sourceRouteIndex: number) => TRoute | undefined;
|
|
122
125
|
hasGenerateStaticParams: boolean;
|
|
126
|
+
hasCustomGlobalError?: boolean;
|
|
123
127
|
hasPageDefaultExport: boolean;
|
|
124
128
|
hasPageModule: boolean;
|
|
125
129
|
handlerStart: number;
|
|
@@ -138,6 +142,20 @@ type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
|
|
|
138
142
|
middlewareContext: AppPageMiddlewareContext;
|
|
139
143
|
mountedSlotsHeader?: string | null;
|
|
140
144
|
params: AppPageParams;
|
|
145
|
+
pprFallbackCacheShells?: readonly AppPagePprFallbackCacheShell[] | null;
|
|
146
|
+
pprFallbackShell?: {
|
|
147
|
+
fallbackParamNames: readonly string[];
|
|
148
|
+
routePattern: string;
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* Set of concrete URL paths that were pre-rendered at build time for this
|
|
152
|
+
* route. When the exact cache entry for a known pregenerated path is absent
|
|
153
|
+
* (evicted, stale-empty, cold start, read error), the fallback shell must
|
|
154
|
+
* NOT be served — the route is a valid generated route whose cache merely
|
|
155
|
+
* has a transient gap. Falls through to a fresh render instead.
|
|
156
|
+
*/
|
|
157
|
+
renderedConcreteUrlPaths?: ReadonlySet<string>;
|
|
158
|
+
skipStaticParamsValidation?: boolean;
|
|
141
159
|
staticParamsValidationParams?: AppPageParams;
|
|
142
160
|
rootParams?: RootParams;
|
|
143
161
|
probeLayoutAt: (layoutIndex: number, layoutParamAccess?: AppLayoutParamAccessTracker) => unknown;
|
|
@@ -152,10 +170,18 @@ type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
|
|
|
152
170
|
}, middlewareContext: AppPageMiddlewareContext | null) => Promise<Response | null>;
|
|
153
171
|
renderToReadableStream: (element: AppPageRenderableElement, options: {
|
|
154
172
|
onError: AppPageBoundaryOnError;
|
|
173
|
+
signal?: AbortSignal;
|
|
155
174
|
}) => ReadableStream<Uint8Array>;
|
|
175
|
+
prerenderToReadableStream?: (element: AppPageRenderableElement, options: {
|
|
176
|
+
onError: AppPageBoundaryOnError;
|
|
177
|
+
signal?: AbortSignal;
|
|
178
|
+
}) => Promise<{
|
|
179
|
+
prelude: ReadableStream<Uint8Array>;
|
|
180
|
+
}>;
|
|
156
181
|
request: Request;
|
|
157
182
|
revalidateSeconds: number | null;
|
|
158
183
|
resolveRouteFetchCacheMode?: (route: TRoute) => FetchCacheMode | null;
|
|
184
|
+
resolveRouteDynamicConfig?: (route: TRoute) => string | null | undefined;
|
|
159
185
|
rootForbiddenModule?: AppPageModule | null;
|
|
160
186
|
rootNotFoundModule?: AppPageModule | null;
|
|
161
187
|
rootUnauthorizedModule?: AppPageModule | null;
|
|
@@ -1,29 +1,31 @@
|
|
|
1
1
|
import { createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
2
2
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
3
|
-
import {
|
|
3
|
+
import { beginPprFallbackShellFinalRender, createPprFallbackShellState, getPprFallbackShellState, runWithPprFallbackShellState } from "../shims/ppr-fallback-shell.js";
|
|
4
|
+
import { consumeDynamicUsage, consumeInvalidDynamicUsageError, getAndClearPendingCookies, getDraftModeCookieHeader, isDraftModeRequest, markDynamicUsage, peekRenderRequestApiUsage, setHeadersContext } from "../shims/headers.js";
|
|
4
5
|
import { _consumeRequestScopedCacheLife, _peekRequestScopedCacheLife } from "../shims/cache.js";
|
|
5
6
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
6
7
|
import { shouldSuppressLoadingBoundaries } from "./app-rsc-render-mode.js";
|
|
7
8
|
import "./app-elements.js";
|
|
8
|
-
import {
|
|
9
|
+
import { ensureFetchPatch, getCollectedFetchTags, peekDynamicFetchObservations, runWithFetchDedupe, setCurrentFetchCacheMode, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault } from "../shims/fetch-cache.js";
|
|
9
10
|
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
|
|
10
|
-
import { readStreamAsText } from "../utils/text-stream.js";
|
|
11
11
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
12
12
|
import "./app-page-response.js";
|
|
13
|
-
import { buildAppPageSpecialErrorResponse,
|
|
13
|
+
import { buildAppPageSpecialErrorResponse, probeAppPageThrownError, resolveAppPageSpecialError } from "./app-page-execution.js";
|
|
14
14
|
import { createAppPageTreePath } from "./app-page-route-wiring.js";
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
15
|
+
import { consumeAppPageRenderObservationState, discardAppPageRenderState } from "./app-page-render-observation.js";
|
|
16
|
+
import { rewriteAppPprFallbackShellHtmlNavigation } from "./app-ppr-fallback-shell.js";
|
|
17
|
+
import { readAppPageCacheResponse, readAppPageFallbackShellCacheResponse } from "./app-page-cache.js";
|
|
17
18
|
import { resolveAppPageParentHttpAccessBoundary, resolveAppPageParentHttpAccessBoundaryModule } from "./app-page-boundary.js";
|
|
18
|
-
import { isAppSsrRenderResult } from "./app-page-stream.js";
|
|
19
19
|
import { createAppLayoutParamAccessTracker, isAppLayoutObservationUnsafeForStaticReuse } from "./app-layout-param-observation.js";
|
|
20
|
+
import { buildAppPageTags } from "./implicit-tags.js";
|
|
21
|
+
import { renderAppPageCacheArtifacts } from "./app-page-cache-render.js";
|
|
22
|
+
import { warmPprFallbackShellCaches } from "./app-ppr-fallback-shell-render.js";
|
|
20
23
|
import { resolveAppPageMethodResponse } from "./app-page-method.js";
|
|
21
24
|
import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
|
|
22
25
|
import { resolveAppPageNavigationParams } from "./app-page-element-builder.js";
|
|
23
26
|
import { buildAppPageElement, resolveAppPageIntercept, resolveAppPageInterceptionRerenderTarget, validateAppPageDynamicParams } from "./app-page-request.js";
|
|
24
27
|
import { renderAppPageLifecycle } from "./app-page-render.js";
|
|
25
28
|
import { createStaticGenerationHeadersContext } from "./app-static-generation.js";
|
|
26
|
-
import { buildPageCacheTags } from "./implicit-tags.js";
|
|
27
29
|
import React from "react";
|
|
28
30
|
//#region src/server/app-page-dispatch.ts
|
|
29
31
|
function resolveAppPageRouteBoundaryModule(route, statusCode) {
|
|
@@ -107,9 +109,6 @@ function shouldReadAppPageCache(options) {
|
|
|
107
109
|
function hasSearchParams(searchParams) {
|
|
108
110
|
return searchParams !== null && searchParams !== void 0 && searchParams.size > 0;
|
|
109
111
|
}
|
|
110
|
-
function buildAppPageTags(cleanPathname, extraTags, routeSegments) {
|
|
111
|
-
return buildPageCacheTags(cleanPathname, extraTags, [...routeSegments], "page");
|
|
112
|
-
}
|
|
113
112
|
async function runAppPageRevalidationContext(options, renderFn) {
|
|
114
113
|
return runWithRequestContext(createRequestContext({
|
|
115
114
|
headersContext: createStaticGenerationHeadersContext({
|
|
@@ -119,6 +118,7 @@ async function runAppPageRevalidationContext(options, renderFn) {
|
|
|
119
118
|
routePattern: options.routePattern
|
|
120
119
|
}),
|
|
121
120
|
currentFetchCacheMode: options.currentFetchCacheMode ?? null,
|
|
121
|
+
currentForceDynamicFetchDefault: options.dynamicConfig === "force-dynamic",
|
|
122
122
|
executionContext: getRequestExecutionContext(),
|
|
123
123
|
unstableCacheRevalidation: "foreground"
|
|
124
124
|
}), async () => {
|
|
@@ -132,10 +132,6 @@ async function runAppPageRevalidationContext(options, renderFn) {
|
|
|
132
132
|
return await runWithFetchDedupe(renderFn);
|
|
133
133
|
});
|
|
134
134
|
}
|
|
135
|
-
function getCapturedRscDataPromise(capturedRscDataPromise) {
|
|
136
|
-
if (!capturedRscDataPromise) throw new Error("[vinext] Expected captured RSC data while regenerating an app page cache entry");
|
|
137
|
-
return capturedRscDataPromise;
|
|
138
|
-
}
|
|
139
135
|
function toInterceptOptions(interceptionContext, intercept) {
|
|
140
136
|
return {
|
|
141
137
|
interceptionContext,
|
|
@@ -144,11 +140,77 @@ function toInterceptOptions(interceptionContext, intercept) {
|
|
|
144
140
|
interceptParams: intercept.matchedParams,
|
|
145
141
|
interceptSlotId: intercept.slotId ?? null,
|
|
146
142
|
interceptSlotKey: intercept.slotKey,
|
|
147
|
-
interceptSourceMatchedUrl: interceptionContext
|
|
143
|
+
interceptSourceMatchedUrl: interceptionContext,
|
|
144
|
+
interceptSourcePageSegments: intercept.sourcePageSegments ?? null
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Request-phase fallback-shell gate. Callers must run the exact cache read and
|
|
149
|
+
* static-param validation before this classification step.
|
|
150
|
+
*/
|
|
151
|
+
function classifyPprFallbackShellEligibility(options, currentRevalidateSeconds, isDraftMode, isForceStatic, isForceDynamic) {
|
|
152
|
+
if (options.renderedConcreteUrlPaths?.has(options.cleanPathname) === true) return { kind: "skip-known-pregenerated-route" };
|
|
153
|
+
const fallbackShells = options.pprFallbackCacheShells;
|
|
154
|
+
if (!fallbackShells || fallbackShells.length === 0) return { kind: "skip-no-fallback-shells" };
|
|
155
|
+
if (options.isRscRequest) return { kind: "skip-rsc-request" };
|
|
156
|
+
if (options.request.method !== "GET") return { kind: "skip-non-get" };
|
|
157
|
+
if (!isForceStatic && hasSearchParams(options.searchParams)) return { kind: "skip-search-params" };
|
|
158
|
+
if (!shouldReadAppPageCache({
|
|
159
|
+
isDraftMode,
|
|
160
|
+
isForceDynamic,
|
|
161
|
+
isProgressiveActionRender: options.isProgressiveActionRender === true,
|
|
162
|
+
isProduction: options.isProduction,
|
|
163
|
+
isRscRequest: false,
|
|
164
|
+
revalidateSeconds: currentRevalidateSeconds,
|
|
165
|
+
scriptNonce: options.scriptNonce
|
|
166
|
+
})) return { kind: "skip-cache-disabled" };
|
|
167
|
+
return {
|
|
168
|
+
kind: "probe-fallback-shells",
|
|
169
|
+
fallbackShells
|
|
148
170
|
};
|
|
149
171
|
}
|
|
172
|
+
async function probePprFallbackShellCache(options, route, fallbackShells, currentRevalidateSeconds) {
|
|
173
|
+
for (const fallbackShell of fallbackShells) {
|
|
174
|
+
const fallbackShellResponse = await readAppPageFallbackShellCacheResponse({
|
|
175
|
+
clearRequestContext: options.clearRequestContext,
|
|
176
|
+
expireSeconds: options.expireSeconds,
|
|
177
|
+
fallbackPathname: fallbackShell.pathname,
|
|
178
|
+
isEdgeRuntime: options.isEdgeRuntime,
|
|
179
|
+
isrDebug: options.isrDebug,
|
|
180
|
+
isrGet: options.isrGet,
|
|
181
|
+
isrHtmlKey: options.isrHtmlKey,
|
|
182
|
+
middlewareHeaders: options.middlewareContext.headers,
|
|
183
|
+
middlewareStatus: options.middlewareContext.status,
|
|
184
|
+
revalidateSeconds: currentRevalidateSeconds ?? 0,
|
|
185
|
+
rewriteHtml(html) {
|
|
186
|
+
return rewriteAppPprFallbackShellHtmlNavigation({
|
|
187
|
+
html,
|
|
188
|
+
params: options.params,
|
|
189
|
+
pathname: options.cleanPathname,
|
|
190
|
+
searchParams: options.searchParams
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
if (fallbackShellResponse) return fallbackShellResponse;
|
|
195
|
+
}
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
async function tryServePprFallbackShell(options, route, currentRevalidateSeconds, isDraftMode, isForceStatic, isForceDynamic) {
|
|
199
|
+
const decision = classifyPprFallbackShellEligibility(options, currentRevalidateSeconds, isDraftMode, isForceStatic, isForceDynamic);
|
|
200
|
+
switch (decision.kind) {
|
|
201
|
+
case "skip-known-pregenerated-route":
|
|
202
|
+
case "skip-no-fallback-shells":
|
|
203
|
+
case "skip-rsc-request":
|
|
204
|
+
case "skip-non-get":
|
|
205
|
+
case "skip-search-params":
|
|
206
|
+
case "skip-cache-disabled": return null;
|
|
207
|
+
case "probe-fallback-shells": return await probePprFallbackShellCache(options, route, decision.fallbackShells, currentRevalidateSeconds);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
150
210
|
async function dispatchAppPage(options) {
|
|
151
|
-
|
|
211
|
+
const dispatch = () => runWithFetchDedupe(() => dispatchAppPageInner(options));
|
|
212
|
+
if (!options.pprFallbackShell) return await dispatch();
|
|
213
|
+
return await runWithPprFallbackShellState(createPprFallbackShellState(options.pprFallbackShell), dispatch);
|
|
152
214
|
}
|
|
153
215
|
async function dispatchAppPageInner(options) {
|
|
154
216
|
const route = options.route;
|
|
@@ -161,6 +223,7 @@ async function dispatchAppPageInner(options) {
|
|
|
161
223
|
const layoutParamAccess = createAppLayoutParamAccessTracker();
|
|
162
224
|
setCurrentFetchSoftTags(buildAppPageTags(options.cleanPathname, [], route.routeSegments));
|
|
163
225
|
setCurrentFetchCacheMode(options.fetchCache ?? null);
|
|
226
|
+
setCurrentForceDynamicFetchDefault(isForceDynamic);
|
|
164
227
|
if (options.hasPageModule && !options.hasPageDefaultExport) {
|
|
165
228
|
options.clearRequestContext();
|
|
166
229
|
return new Response("Page has no default export", { status: 500 });
|
|
@@ -242,7 +305,7 @@ async function dispatchAppPageInner(options) {
|
|
|
242
305
|
displayPathname: options.displayPathname,
|
|
243
306
|
currentFetchCacheMode: options.resolveRouteFetchCacheMode?.(revalidationTarget.route) ?? (revalidationTarget.route === route ? options.fetchCache ?? null : null),
|
|
244
307
|
draftModeSecret: options.draftModeSecret,
|
|
245
|
-
dynamicConfig,
|
|
308
|
+
dynamicConfig: options.resolveRouteDynamicConfig?.(revalidationTarget.route) ?? (revalidationTarget.route === route ? dynamicConfig : void 0),
|
|
246
309
|
params: revalidationTarget.navigationParams,
|
|
247
310
|
routePattern: revalidationTarget.route.pattern,
|
|
248
311
|
routeSegments: revalidationTarget.route.routeSegments,
|
|
@@ -250,72 +313,34 @@ async function dispatchAppPageInner(options) {
|
|
|
250
313
|
}, async () => {
|
|
251
314
|
const revalidatedElement = await options.buildPageElement(revalidationTarget.route, revalidationTarget.params, revalidationTarget.interceptOpts, new URLSearchParams());
|
|
252
315
|
const revalidatedOnError = options.createRscOnErrorHandler(options.cleanPathname, revalidationTarget.route.pattern);
|
|
253
|
-
const
|
|
254
|
-
const revalidatedSsrEntry = await options.loadSsrHandler();
|
|
255
|
-
const revalidatedCapturedRscRef = { value: null };
|
|
256
|
-
const revalidatedHtmlResult = await revalidatedSsrEntry.handleSsr(revalidatedRscCapture.ssrStream, options.getNavigationContext(), {
|
|
257
|
-
links: options.getFontLinks(),
|
|
258
|
-
styles: options.getFontStyles(),
|
|
259
|
-
preloads: options.getFontPreloads()
|
|
260
|
-
}, {
|
|
316
|
+
const rendered = await renderAppPageCacheArtifacts({
|
|
261
317
|
basePath: options.basePath,
|
|
318
|
+
captureRscData: true,
|
|
319
|
+
cleanPathname: options.cleanPathname,
|
|
262
320
|
clientTraceMetadata: options.clientTraceMetadata,
|
|
321
|
+
element: revalidatedElement,
|
|
322
|
+
getFontLinks: options.getFontLinks,
|
|
323
|
+
getFontPreloads: options.getFontPreloads,
|
|
324
|
+
getFontStyles: options.getFontStyles,
|
|
325
|
+
getNavigationContext: options.getNavigationContext,
|
|
326
|
+
loadSsrHandler: options.loadSsrHandler,
|
|
327
|
+
mountedSlotsHeader: options.mountedSlotsHeader,
|
|
328
|
+
navigationParams: revalidationTarget.navigationParams,
|
|
329
|
+
onError: revalidatedOnError,
|
|
263
330
|
reactMaxHeadersLength: options.reactMaxHeadersLength,
|
|
331
|
+
renderToReadableStream: options.renderToReadableStream,
|
|
264
332
|
rootParams: options.rootParams,
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
sideStream: revalidatedRscCapture.sideStream,
|
|
268
|
-
capturedRscDataRef: revalidatedCapturedRscRef
|
|
269
|
-
} : {}
|
|
333
|
+
route: revalidationTarget.route,
|
|
334
|
+
waitForAllReady: true
|
|
270
335
|
});
|
|
271
|
-
const html = await readStreamAsText(isAppSsrRenderResult(revalidatedHtmlResult) ? revalidatedHtmlResult.htmlStream : revalidatedHtmlResult);
|
|
272
|
-
const rscData = await getCapturedRscDataPromise(revalidatedCapturedRscRef.value);
|
|
273
|
-
const cacheLife = _consumeRequestScopedCacheLife();
|
|
274
336
|
options.clearRequestContext();
|
|
275
|
-
const tags = buildAppPageTags(options.cleanPathname, getCollectedFetchTags(), revalidationTarget.route.routeSegments);
|
|
276
|
-
const observationState = {
|
|
277
|
-
dynamicFetches: consumeDynamicFetchObservations(),
|
|
278
|
-
requestApis: consumeRenderRequestApiUsage()
|
|
279
|
-
};
|
|
280
337
|
return {
|
|
281
|
-
html,
|
|
282
|
-
htmlRenderObservation:
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
completeness: "complete",
|
|
288
|
-
output: createAppPageHtmlOutputScope({
|
|
289
|
-
element: revalidatedElement,
|
|
290
|
-
renderEpoch: null,
|
|
291
|
-
rootBoundaryId: null,
|
|
292
|
-
routePattern: revalidationTarget.route.pattern
|
|
293
|
-
}),
|
|
294
|
-
params: revalidationTarget.navigationParams,
|
|
295
|
-
state: observationState
|
|
296
|
-
}),
|
|
297
|
-
rscData,
|
|
298
|
-
rscRenderObservation: createAppPageRenderObservation({
|
|
299
|
-
boundaryOutcome: { kind: "success" },
|
|
300
|
-
cacheability: "public",
|
|
301
|
-
cacheTags: tags,
|
|
302
|
-
cleanPathname: options.cleanPathname,
|
|
303
|
-
completeness: "complete",
|
|
304
|
-
output: createAppPageRscOutputScope({
|
|
305
|
-
element: revalidatedElement,
|
|
306
|
-
mountedSlotsHeader: options.mountedSlotsHeader,
|
|
307
|
-
renderEpoch: null,
|
|
308
|
-
rootBoundaryId: null,
|
|
309
|
-
routePattern: revalidationTarget.route.pattern
|
|
310
|
-
}),
|
|
311
|
-
params: revalidationTarget.navigationParams,
|
|
312
|
-
state: observationState
|
|
313
|
-
}),
|
|
314
|
-
tags,
|
|
315
|
-
cacheControl: typeof cacheLife?.revalidate === "number" ? {
|
|
316
|
-
revalidate: cacheLife.revalidate,
|
|
317
|
-
expire: cacheLife.expire
|
|
318
|
-
} : void 0
|
|
338
|
+
html: rendered.html,
|
|
339
|
+
htmlRenderObservation: rendered.htmlRenderObservation,
|
|
340
|
+
rscData: rendered.rscData,
|
|
341
|
+
rscRenderObservation: rendered.rscRenderObservation,
|
|
342
|
+
tags: rendered.tags,
|
|
343
|
+
cacheControl: rendered.cacheControl
|
|
319
344
|
};
|
|
320
345
|
});
|
|
321
346
|
},
|
|
@@ -329,18 +354,23 @@ async function dispatchAppPageInner(options) {
|
|
|
329
354
|
});
|
|
330
355
|
if (cachedPageResponse) return cachedPageResponse;
|
|
331
356
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
357
|
+
if (options.skipStaticParamsValidation !== true) {
|
|
358
|
+
const dynamicParamsResponse = await validateAppPageDynamicParams({
|
|
359
|
+
clearRequestContext: options.clearRequestContext,
|
|
360
|
+
enforceStaticParamsOnly: options.dynamicParamsConfig === false,
|
|
361
|
+
generateStaticParams: options.generateStaticParams,
|
|
362
|
+
isDynamicRoute: route.isDynamic,
|
|
363
|
+
params: options.staticParamsValidationParams ?? options.params
|
|
364
|
+
});
|
|
365
|
+
if (dynamicParamsResponse) return dynamicParamsResponse;
|
|
366
|
+
}
|
|
367
|
+
const fallbackShellResponse = await tryServePprFallbackShell(options, route, currentRevalidateSeconds, isDraftMode, isForceStatic, isForceDynamic);
|
|
368
|
+
if (fallbackShellResponse) return fallbackShellResponse;
|
|
340
369
|
const interceptResult = await resolveAppPageIntercept({
|
|
341
370
|
async buildPageElement(interceptRoute, interceptParams, interceptOpts, interceptSearchParams, interceptLayoutParamAccess) {
|
|
342
371
|
await options.ensureRouteLoaded?.(interceptRoute);
|
|
343
372
|
setCurrentFetchCacheMode(options.resolveRouteFetchCacheMode?.(interceptRoute) ?? null);
|
|
373
|
+
setCurrentForceDynamicFetchDefault(options.resolveRouteDynamicConfig?.(interceptRoute) === "force-dynamic");
|
|
344
374
|
return options.buildPageElement(interceptRoute, interceptParams, interceptOpts, interceptSearchParams, interceptLayoutParamAccess);
|
|
345
375
|
},
|
|
346
376
|
cleanPathname: options.cleanPathname,
|
|
@@ -380,11 +410,20 @@ async function dispatchAppPageInner(options) {
|
|
|
380
410
|
}
|
|
381
411
|
});
|
|
382
412
|
if (interceptResult.response) return interceptResult.response;
|
|
383
|
-
const
|
|
413
|
+
const buildCurrentPageElement = () => buildAppPageElement({
|
|
384
414
|
buildPageElement() {
|
|
385
415
|
if (options.actionFailed) throw options.actionError;
|
|
386
416
|
return options.buildPageElement(route, options.params, interceptResult.interceptOpts, options.searchParams, layoutParamAccess);
|
|
387
417
|
},
|
|
418
|
+
async probePageSpecialError() {
|
|
419
|
+
if (!shouldSuppressLoadingBoundaries(options.renderMode ?? "navigation") && route.loading?.default) return null;
|
|
420
|
+
return resolveAppPageSpecialError(await probeAppPageThrownError({
|
|
421
|
+
probePage: options.probePage,
|
|
422
|
+
runWithSuppressedHookWarning(probe) {
|
|
423
|
+
return options.runWithSuppressedHookWarning(probe);
|
|
424
|
+
}
|
|
425
|
+
}));
|
|
426
|
+
},
|
|
388
427
|
renderErrorBoundaryPage(buildError) {
|
|
389
428
|
return options.renderErrorBoundaryPage(buildError);
|
|
390
429
|
},
|
|
@@ -393,6 +432,19 @@ async function dispatchAppPageInner(options) {
|
|
|
393
432
|
},
|
|
394
433
|
resolveSpecialError: resolveAppPageSpecialError
|
|
395
434
|
});
|
|
435
|
+
const fallbackShellState = getPprFallbackShellState();
|
|
436
|
+
if (fallbackShellState && process.env.VINEXT_PRERENDER === "1" && !options.isRscRequest) {
|
|
437
|
+
const warmupBuildResult = await buildCurrentPageElement();
|
|
438
|
+
if (warmupBuildResult.response) return warmupBuildResult.response;
|
|
439
|
+
await warmPprFallbackShellCaches({
|
|
440
|
+
element: warmupBuildResult.element,
|
|
441
|
+
onError: options.createRscOnErrorHandler(options.cleanPathname, route.pattern),
|
|
442
|
+
renderToReadableStream: options.renderToReadableStream,
|
|
443
|
+
state: fallbackShellState
|
|
444
|
+
});
|
|
445
|
+
discardAppPageRenderState();
|
|
446
|
+
}
|
|
447
|
+
const pageBuildResult = await buildCurrentPageElement();
|
|
396
448
|
if (pageBuildResult.response) return pageBuildResult.response;
|
|
397
449
|
const navigationParams = resolveAppPageNavigationParams(route, options.params, options.cleanPathname, interceptResult.interceptOpts);
|
|
398
450
|
options.setNavigationContext({
|
|
@@ -401,6 +453,9 @@ async function dispatchAppPageInner(options) {
|
|
|
401
453
|
params: navigationParams
|
|
402
454
|
});
|
|
403
455
|
const layoutClassifications = getEffectiveLayoutClassifications(route, options.debugClassification);
|
|
456
|
+
const activeFallbackShellState = getPprFallbackShellState();
|
|
457
|
+
const pprFallbackShellSignal = activeFallbackShellState?.abortController.signal;
|
|
458
|
+
const pprFallbackShellReactSignal = activeFallbackShellState?.reactAbortController.signal;
|
|
404
459
|
return renderAppPageLifecycle({
|
|
405
460
|
basePath: options.basePath,
|
|
406
461
|
clientTraceMetadata: options.clientTraceMetadata,
|
|
@@ -409,12 +464,7 @@ async function dispatchAppPageInner(options) {
|
|
|
409
464
|
clearRequestContext: options.clearRequestContext,
|
|
410
465
|
consumeDynamicUsage,
|
|
411
466
|
consumeInvalidDynamicUsageError,
|
|
412
|
-
consumeRenderObservationState
|
|
413
|
-
return {
|
|
414
|
-
dynamicFetches: consumeDynamicFetchObservations(),
|
|
415
|
-
requestApis: consumeRenderRequestApiUsage()
|
|
416
|
-
};
|
|
417
|
-
},
|
|
467
|
+
consumeRenderObservationState: consumeAppPageRenderObservationState,
|
|
418
468
|
createRscOnErrorHandler(pathname, routePath) {
|
|
419
469
|
return options.createRscOnErrorHandler(pathname, routePath);
|
|
420
470
|
},
|
|
@@ -457,6 +507,11 @@ async function dispatchAppPageInner(options) {
|
|
|
457
507
|
middlewareContext: options.middlewareContext,
|
|
458
508
|
navigationParams,
|
|
459
509
|
params: options.params,
|
|
510
|
+
pprFallbackShellSignal,
|
|
511
|
+
pprFallbackShellReactSignal,
|
|
512
|
+
abortPprFallbackShell: activeFallbackShellState ? () => {
|
|
513
|
+
beginPprFallbackShellFinalRender(activeFallbackShellState);
|
|
514
|
+
} : void 0,
|
|
460
515
|
layoutParamAccess,
|
|
461
516
|
rootParams: options.rootParams,
|
|
462
517
|
peekRenderObservationState() {
|
|
@@ -509,6 +564,8 @@ async function dispatchAppPageInner(options) {
|
|
|
509
564
|
return renderPageSpecialError(options, specialError);
|
|
510
565
|
},
|
|
511
566
|
renderToReadableStream: options.renderToReadableStream,
|
|
567
|
+
hasCustomGlobalError: options.hasCustomGlobalError,
|
|
568
|
+
prerenderToReadableStream: options.prerenderToReadableStream,
|
|
512
569
|
routePattern: route.pattern,
|
|
513
570
|
runWithSuppressedHookWarning(probe) {
|
|
514
571
|
return options.runWithSuppressedHookWarning(probe);
|