vinext 0.2.0 → 1.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -29
- package/dist/build/client-build-config.d.ts +13 -92
- package/dist/build/client-build-config.js +17 -95
- package/dist/build/css-url-assets.d.ts +3 -1
- package/dist/build/css-url-assets.js +18 -1
- package/dist/build/inject-pregenerated-paths.d.ts +3 -0
- package/dist/build/inject-pregenerated-paths.js +4 -1
- package/dist/build/prerender-paths.d.ts +23 -0
- package/dist/build/prerender-paths.js +296 -0
- package/dist/build/prerender-server-entry.d.ts +1 -0
- package/dist/build/prerender-server-entry.js +49 -0
- package/dist/build/prerender-server-pool.d.ts +44 -0
- package/dist/build/prerender-server-pool.js +194 -0
- package/dist/build/prerender.d.ts +12 -1
- package/dist/build/prerender.js +87 -23
- package/dist/build/run-prerender.js +2 -1
- package/dist/cache/cache-adapters-virtual.d.ts +7 -1
- package/dist/cache/cache-adapters-virtual.js +26 -2
- package/dist/check.d.ts +4 -6
- package/dist/check.js +13 -9
- package/dist/cli.js +34 -54
- package/dist/client/vinext-next-data.d.ts +4 -1
- package/dist/config/config-matchers.js +33 -11
- package/dist/config/next-config.d.ts +36 -6
- package/dist/config/next-config.js +17 -4
- package/dist/config/prerender.d.ts +11 -1
- package/dist/config/prerender.js +19 -1
- package/dist/config/tsconfig-paths.js +5 -1
- package/dist/entries/app-browser-entry.js +5 -1
- package/dist/entries/app-rsc-entry.d.ts +3 -2
- package/dist/entries/app-rsc-entry.js +4 -0
- package/dist/entries/pages-client-entry.js +14 -3
- package/dist/entries/pages-server-entry.js +18 -4
- package/dist/image/image-adapters-virtual.js +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +549 -152
- package/dist/init-cloudflare.js +12 -3
- package/dist/init-platform.d.ts +10 -1
- package/dist/init-platform.js +78 -12
- package/dist/init.d.ts +11 -3
- package/dist/init.js +129 -31
- package/dist/plugins/fonts.js +1 -1
- package/dist/plugins/ignore-dynamic-requests.js +1 -1
- package/dist/plugins/og-assets.js +2 -1
- package/dist/plugins/optimize-imports.js +1 -1
- package/dist/plugins/rsc-reference-validation-normalizer.d.ts +12 -0
- package/dist/plugins/rsc-reference-validation-normalizer.js +48 -0
- package/dist/plugins/sass.d.ts +17 -1
- package/dist/plugins/sass.js +74 -1
- package/dist/plugins/styled-jsx.d.ts +16 -0
- package/dist/plugins/styled-jsx.js +149 -0
- package/dist/routing/app-route-graph.js +22 -16
- package/dist/routing/file-matcher.d.ts +8 -1
- package/dist/routing/file-matcher.js +15 -3
- package/dist/server/app-browser-entry.js +44 -14
- package/dist/server/app-browser-navigation-controller.js +5 -2
- package/dist/server/app-browser-server-action-client.js +5 -3
- package/dist/server/app-browser-state.d.ts +1 -0
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-layout-param-observation.d.ts +1 -1
- package/dist/server/app-page-boundary.js +2 -1
- package/dist/server/app-page-cache-finalizer.d.ts +1 -0
- package/dist/server/app-page-cache-finalizer.js +3 -3
- package/dist/server/app-page-cache-render.d.ts +1 -1
- package/dist/server/app-page-cache.js +23 -6
- package/dist/server/app-page-dispatch.d.ts +2 -1
- package/dist/server/app-page-dispatch.js +27 -10
- package/dist/server/app-page-element-builder.js +1 -0
- package/dist/server/app-page-execution.js +2 -1
- package/dist/server/app-page-render-identity.d.ts +1 -0
- package/dist/server/app-page-render-identity.js +2 -1
- package/dist/server/app-page-render.d.ts +3 -1
- package/dist/server/app-page-render.js +67 -16
- package/dist/server/app-page-response.d.ts +7 -0
- package/dist/server/app-page-response.js +16 -4
- package/dist/server/app-page-route-wiring.js +3 -3
- package/dist/server/app-page-stream.d.ts +2 -1
- package/dist/server/app-page-stream.js +1 -1
- package/dist/server/app-route-handler-execution.d.ts +1 -1
- package/dist/server/app-route-tree-prefetch.d.ts +43 -0
- package/dist/server/app-route-tree-prefetch.js +187 -0
- package/dist/server/app-router-entry.js +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +2 -1
- package/dist/server/app-rsc-cache-busting.js +9 -5
- package/dist/server/app-rsc-handler.d.ts +6 -0
- package/dist/server/app-rsc-handler.js +88 -10
- package/dist/server/app-rsc-render-mode.d.ts +3 -5
- package/dist/server/app-rsc-render-mode.js +5 -12
- package/dist/server/app-rsc-request-normalization.d.ts +3 -4
- package/dist/server/app-rsc-request-normalization.js +4 -5
- package/dist/server/app-server-action-execution.js +6 -5
- package/dist/server/app-ssr-entry.js +1 -1
- package/dist/server/cache-control.d.ts +3 -1
- package/dist/server/cache-control.js +13 -1
- package/dist/server/dev-module-runner.js +1 -1
- package/dist/server/dev-origin-check.d.ts +2 -2
- package/dist/server/dev-origin-check.js +2 -2
- package/dist/server/dev-server.d.ts +11 -1
- package/dist/server/dev-server.js +82 -24
- package/dist/server/headers.d.ts +6 -2
- package/dist/server/headers.js +11 -5
- package/dist/server/image-optimization.d.ts +12 -1
- package/dist/server/image-optimization.js +13 -1
- package/dist/server/isr-cache.d.ts +13 -4
- package/dist/server/isr-cache.js +8 -4
- package/dist/server/pages-data-route.d.ts +4 -2
- package/dist/server/pages-data-route.js +18 -4
- package/dist/server/pages-dev-module-url.d.ts +2 -1
- package/dist/server/pages-dev-module-url.js +6 -3
- package/dist/server/pages-node-compat.d.ts +12 -1
- package/dist/server/pages-node-compat.js +50 -1
- package/dist/server/pages-page-data.d.ts +9 -0
- package/dist/server/pages-page-data.js +18 -10
- package/dist/server/pages-page-handler.js +19 -7
- package/dist/server/pages-page-response.d.ts +1 -0
- package/dist/server/pages-page-response.js +5 -4
- package/dist/server/pages-request-pipeline.d.ts +8 -6
- package/dist/server/pages-request-pipeline.js +31 -7
- package/dist/server/pages-router-entry.js +1 -1
- package/dist/server/prerender-manifest.d.ts +15 -1
- package/dist/server/prerender-manifest.js +29 -1
- package/dist/server/prod-server.d.ts +10 -7
- package/dist/server/prod-server.js +43 -28
- package/dist/server/request-pipeline.js +1 -1
- package/dist/server/static-file-cache.js +1 -1
- package/dist/shims/cache-handler.js +8 -1
- package/dist/shims/cache.d.ts +1 -1
- package/dist/shims/cache.js +3 -0
- package/dist/shims/cdn-cache.d.ts +2 -7
- package/dist/shims/cdn-cache.js +2 -14
- package/dist/shims/fetch-cache.d.ts +3 -1
- package/dist/shims/fetch-cache.js +77 -52
- package/dist/shims/internal/app-prefetch-fetch-queue.d.ts +10 -0
- package/dist/shims/internal/app-prefetch-fetch-queue.js +61 -0
- package/dist/shims/internal/hybrid-client-route-owner.d.ts +2 -1
- package/dist/shims/internal/hybrid-client-route-owner.js +34 -1
- package/dist/shims/internal/pages-data-fetch-dedup.d.ts +2 -1
- package/dist/shims/internal/pages-data-fetch-dedup.js +13 -2
- package/dist/shims/internal/pages-data-target.d.ts +8 -3
- package/dist/shims/internal/pages-data-target.js +9 -4
- package/dist/shims/link.d.ts +1 -1
- package/dist/shims/link.js +179 -42
- package/dist/shims/navigation.d.ts +15 -3
- package/dist/shims/navigation.js +202 -39
- package/dist/shims/request-context.js +18 -0
- package/dist/shims/request-state-types.d.ts +2 -2
- package/dist/shims/router.js +31 -15
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/typegen.js +1 -1
- package/dist/utils/middleware-request-headers.js +1 -1
- package/dist/utils/project.d.ts +1 -1
- package/dist/utils/protocol-headers.d.ts +7 -1
- package/dist/utils/protocol-headers.js +7 -1
- package/dist/utils/vite-version.d.ts +4 -12
- package/dist/utils/vite-version.js +39 -21
- package/package.json +31 -13
- package/dist/cloudflare/index.d.ts +0 -3
- package/dist/cloudflare/index.js +0 -3
- package/dist/packages/cloudflare/src/cache/cdn-adapter.runtime.js +0 -102
- package/dist/packages/cloudflare/src/cache/kv-data-adapter.runtime.d.ts +0 -126
- package/dist/packages/cloudflare/src/cache/kv-data-adapter.runtime.js +0 -435
- package/dist/packages/cloudflare/src/deploy-config.js +0 -150
- package/dist/packages/cloudflare/src/deploy-help.js +0 -55
- package/dist/packages/cloudflare/src/deploy.js +0 -276
- package/dist/packages/cloudflare/src/tpr.d.ts +0 -45
- package/dist/packages/cloudflare/src/tpr.js +0 -561
- package/dist/packages/cloudflare/src/utils/cache-control-metadata.js +0 -20
|
@@ -68,7 +68,7 @@ function resolveServerActionRequestState(options) {
|
|
|
68
68
|
const headers = createRscRequestHeaders();
|
|
69
69
|
headers.set(RSC_ACTION_HEADER, options.actionId);
|
|
70
70
|
headers.set(NEXT_ACTION_HEADER, options.actionId);
|
|
71
|
-
const interceptionContext = resolveInterceptionContextFromPreviousNextUrl(options.previousNextUrl, options.basePath);
|
|
71
|
+
const interceptionContext = resolveInterceptionContextFromPreviousNextUrl(options.previousNextUrl, options.basePath) ?? options.interceptionContext ?? null;
|
|
72
72
|
if (interceptionContext !== null) headers.set(VINEXT_INTERCEPTION_CONTEXT_HEADER, interceptionContext);
|
|
73
73
|
const mountedSlotsHeader = getMountedSlotIdsHeader(options.elements);
|
|
74
74
|
if (mountedSlotsHeader !== null) headers.set(VINEXT_MOUNTED_SLOTS_HEADER, mountedSlotsHeader);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { UnstableCacheObservation } from "../shims/cache-request-state.js";
|
|
2
1
|
import { RenderRequestApiKind } from "./cache-proof.js";
|
|
3
2
|
import { ClientReuseManifestRejectionCode, ClientReuseManifestTraceFields } from "./client-reuse-manifest.js";
|
|
4
3
|
import { ThenableParamsObserver } from "../shims/thenable-params.js";
|
|
4
|
+
import { UnstableCacheObservation } from "../shims/cache-request-state.js";
|
|
5
5
|
|
|
6
6
|
//#region src/server/app-layout-param-observation.d.ts
|
|
7
7
|
type AppLayoutParamAccessObservation = Readonly<{
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { runWithFetchDedupe } from "../shims/fetch-cache.js";
|
|
2
2
|
import { resolveAppPageSegmentParams } from "./app-page-params.js";
|
|
3
|
-
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
|
|
3
|
+
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader } from "./app-rsc-cache-busting.js";
|
|
4
4
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
5
5
|
import { applyEdgeRuntimeHeader } from "./app-page-response.js";
|
|
6
6
|
//#region src/server/app-page-boundary.ts
|
|
@@ -109,6 +109,7 @@ async function renderAppPageBoundaryResponse(options) {
|
|
|
109
109
|
applyEdgeRuntimeHeader(headers, options.isEdgeRuntime);
|
|
110
110
|
mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders ?? null);
|
|
111
111
|
applyRscCompatibilityIdHeader(headers);
|
|
112
|
+
applyRscDeploymentIdHeader(headers);
|
|
112
113
|
return new Response(rscStream, {
|
|
113
114
|
status: options.status,
|
|
114
115
|
headers
|
|
@@ -50,6 +50,7 @@ type ScheduleAppPageRscCacheWriteOptions = {
|
|
|
50
50
|
isrSet: AppPageCacheSetter;
|
|
51
51
|
interceptionContext?: string | null;
|
|
52
52
|
mountedSlotsHeader?: string | null;
|
|
53
|
+
omitPendingDynamicCacheState?: boolean;
|
|
53
54
|
renderMode?: AppRscRenderMode;
|
|
54
55
|
preserveClientResponseHeaders?: boolean;
|
|
55
56
|
expireSeconds?: number;
|
|
@@ -83,7 +83,7 @@ function finalizeAppPageRscCacheResponse(response, options) {
|
|
|
83
83
|
if (!scheduleAppPageRscCacheWrite(options)) return response;
|
|
84
84
|
if (options.preserveClientResponseHeaders === true) return response;
|
|
85
85
|
const clientHeaders = new Headers(response.headers);
|
|
86
|
-
applyPendingDynamicCdnHeaders(clientHeaders, options.getPageTags());
|
|
86
|
+
applyPendingDynamicCdnHeaders(clientHeaders, options.getPageTags(), { omitCacheState: options.omitPendingDynamicCacheState === true });
|
|
87
87
|
return new Response(response.body, {
|
|
88
88
|
status: response.status,
|
|
89
89
|
statusText: response.statusText,
|
|
@@ -92,8 +92,8 @@ function finalizeAppPageRscCacheResponse(response, options) {
|
|
|
92
92
|
}
|
|
93
93
|
function scheduleAppPageRscCacheWrite(options) {
|
|
94
94
|
const capturedRscDataPromise = options.capturedRscDataPromise;
|
|
95
|
-
if (!capturedRscDataPromise || options.dynamicUsedDuringBuild) return false;
|
|
96
|
-
const rscKey = options.isrRscKey(options.cleanPathname,
|
|
95
|
+
if (!capturedRscDataPromise || options.dynamicUsedDuringBuild || options.mountedSlotsHeader) return false;
|
|
96
|
+
const rscKey = options.isrRscKey(options.cleanPathname, null, options.renderMode, options.interceptionContext);
|
|
97
97
|
const cachePromise = (async () => {
|
|
98
98
|
try {
|
|
99
99
|
const rscData = await capturedRscDataPromise;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { CacheControlMetadata } from "../shims/cache-handler.js";
|
|
2
1
|
import { NavigationContext } from "../shims/navigation-context-state.js";
|
|
3
2
|
import { AppPageFontPreload } from "./app-page-execution.js";
|
|
4
3
|
import { RootParams } from "../shims/root-params.js";
|
|
5
4
|
import { AppPageSsrHandler } from "./app-page-stream.js";
|
|
5
|
+
import { CacheControlMetadata } from "../shims/cache-handler.js";
|
|
6
6
|
import { createAppPageRenderObservation } from "./app-page-render-observation.js";
|
|
7
7
|
import { ReactNode } from "react";
|
|
8
8
|
|
|
@@ -4,7 +4,7 @@ import { applyCdnResponseHeaders } from "./cache-control.js";
|
|
|
4
4
|
import { decideIsr } from "./isr-decision.js";
|
|
5
5
|
import { buildAppPageCacheValue } from "./isr-cache.js";
|
|
6
6
|
import { encodeCacheTag } from "../utils/encode-cache-tag.js";
|
|
7
|
-
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
|
|
7
|
+
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader } from "./app-rsc-cache-busting.js";
|
|
8
8
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
9
9
|
import { applyEdgeRuntimeHeader } from "./app-page-response.js";
|
|
10
10
|
import { hasCompleteNegativeRequestApiProof } from "./cache-proof.js";
|
|
@@ -55,6 +55,15 @@ function getCachedAppPageValue(entry) {
|
|
|
55
55
|
function hasQueryInvariantAppPageProof(cachedValue) {
|
|
56
56
|
return cachedValue.renderObservation !== void 0 && hasCompleteNegativeRequestApiProof(cachedValue.renderObservation, ["searchParams"]);
|
|
57
57
|
}
|
|
58
|
+
function resolveRegeneratedAppPageCachePolicy(options) {
|
|
59
|
+
let revalidateSeconds = options.routeRevalidateSeconds;
|
|
60
|
+
const renderRevalidateSeconds = options.renderCacheControl?.revalidate;
|
|
61
|
+
if (renderRevalidateSeconds !== void 0) revalidateSeconds = revalidateSeconds > 0 ? Math.min(revalidateSeconds, renderRevalidateSeconds) : renderRevalidateSeconds;
|
|
62
|
+
return {
|
|
63
|
+
expireSeconds: options.renderCacheControl?.expire ?? options.expireSeconds,
|
|
64
|
+
revalidateSeconds
|
|
65
|
+
};
|
|
66
|
+
}
|
|
58
67
|
function buildAppPageCachedResponse(cachedValue, options) {
|
|
59
68
|
const status = options.middlewareStatus ?? (cachedValue.status || 200);
|
|
60
69
|
const { cacheControl } = decideIsr({
|
|
@@ -75,6 +84,7 @@ function buildAppPageCachedResponse(cachedValue, options) {
|
|
|
75
84
|
mountedSlotsHeader: options.mountedSlotsHeader
|
|
76
85
|
});
|
|
77
86
|
applyRscCompatibilityIdHeader(rscHeaders);
|
|
87
|
+
applyRscDeploymentIdHeader(rscHeaders);
|
|
78
88
|
return new Response(cachedValue.rscData, {
|
|
79
89
|
status,
|
|
80
90
|
headers: rscHeaders
|
|
@@ -118,7 +128,11 @@ async function serveAppPageCachedHtml(options, transformValue) {
|
|
|
118
128
|
return response;
|
|
119
129
|
}
|
|
120
130
|
async function readAppPageCacheResponse(options) {
|
|
121
|
-
|
|
131
|
+
if (options.isRscRequest && options.mountedSlotsHeader) {
|
|
132
|
+
options.isrDebug?.("MISS (mounted slots RSC variant)", options.cleanPathname);
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
const isrKey = options.isRscRequest ? options.isrRscKey(options.cleanPathname, null, options.renderMode, options.interceptionContext) : options.isrHtmlKey(options.cleanPathname);
|
|
122
136
|
const artifact = options.isRscRequest ? "rsc" : "html";
|
|
123
137
|
try {
|
|
124
138
|
const cached = await options.isrGet(isrKey);
|
|
@@ -177,10 +191,13 @@ async function readAppPageCacheResponse(options) {
|
|
|
177
191
|
if (cached?.isStale && cachedValue) {
|
|
178
192
|
options.scheduleBackgroundRegeneration(isrKey, async () => {
|
|
179
193
|
const revalidatedPage = await options.renderFreshPageForCache();
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
194
|
+
const cachePolicy = resolveRegeneratedAppPageCachePolicy({
|
|
195
|
+
expireSeconds: options.expireSeconds,
|
|
196
|
+
renderCacheControl: revalidatedPage.cacheControl,
|
|
197
|
+
routeRevalidateSeconds: options.revalidateSeconds
|
|
198
|
+
});
|
|
199
|
+
const writes = [options.isrSet(options.isRscRequest ? isrKey : options.isrRscKey(options.cleanPathname, null, options.renderMode, options.interceptionContext), buildAppPageCacheValue("", revalidatedPage.rscData, 200, revalidatedPage.rscRenderObservation), cachePolicy.revalidateSeconds, revalidatedPage.tags, cachePolicy.expireSeconds)];
|
|
200
|
+
if (!options.isRscRequest) writes.push(options.isrSet(isrKey, buildAppPageCacheValue(revalidatedPage.html, void 0, 200, revalidatedPage.htmlRenderObservation, revalidatedPage.linkHeader ? { link: revalidatedPage.linkHeader } : void 0), cachePolicy.revalidateSeconds, revalidatedPage.tags, cachePolicy.expireSeconds));
|
|
184
201
|
await Promise.all(writes);
|
|
185
202
|
options.isrDebug?.("regen complete", options.cleanPathname);
|
|
186
203
|
});
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ClassificationReason } from "../build/layout-classification-types.js";
|
|
2
|
-
import { CachedAppPageValue } from "../shims/cache-handler.js";
|
|
3
2
|
import { ClientReuseManifestParseResult } from "./client-reuse-manifest.js";
|
|
4
3
|
import { AppOutgoingElements } from "./app-elements-wire.js";
|
|
5
4
|
import { NavigationContext } from "../shims/navigation-context-state.js";
|
|
@@ -8,6 +7,7 @@ import { AppPageMiddlewareContext } from "./app-page-response.js";
|
|
|
8
7
|
import { RootParams } from "../shims/root-params.js";
|
|
9
8
|
import { AppPageSsrHandler } from "./app-page-stream.js";
|
|
10
9
|
import { AppLayoutParamAccessTracker } from "./app-layout-param-observation.js";
|
|
10
|
+
import { CachedAppPageValue } from "../shims/cache-handler.js";
|
|
11
11
|
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
12
12
|
import { ISRCacheEntry } from "./isr-cache.js";
|
|
13
13
|
import { PprFallbackShellState } from "../shims/ppr-fallback-shell.js";
|
|
@@ -199,6 +199,7 @@ type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
|
|
|
199
199
|
}>;
|
|
200
200
|
request: Request;
|
|
201
201
|
revalidateSeconds: number | null;
|
|
202
|
+
renderedPathAndSearch?: string | null;
|
|
202
203
|
resolveRouteFetchCacheMode?: (route: TRoute) => FetchCacheMode | null;
|
|
203
204
|
resolveRouteDynamicConfig?: (route: TRoute) => string | null | undefined;
|
|
204
205
|
rootForbiddenModule?: AppPageModule | null;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
2
2
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
3
|
+
import "../utils/protocol-headers.js";
|
|
3
4
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
4
|
-
import {
|
|
5
|
+
import { APP_RSC_RENDER_MODE_PREFETCH_DYNAMIC_SHELL } from "./app-rsc-render-mode.js";
|
|
5
6
|
import "./app-elements.js";
|
|
6
7
|
import { consumeDynamicUsage, consumeInvalidDynamicUsageError, getAndClearPendingCookies, getDraftModeCookieHeader, getHeadersContext, isDraftModeRequest, markDynamicUsage, peekDynamicUsage, peekRenderRequestApiUsage, setHeadersContext } from "../shims/headers.js";
|
|
7
8
|
import { _consumeRequestScopedCacheLife, _peekRequestScopedCacheLife } from "../shims/cache-request-state.js";
|
|
8
|
-
import { ensureFetchPatch, getCollectedFetchTags, peekDynamicFetchObservations, runWithFetchDedupe, setCurrentFetchCacheMode, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault } from "../shims/fetch-cache.js";
|
|
9
|
-
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
|
|
9
|
+
import { ensureFetchPatch, getCollectedFetchTags, peekDynamicFetchObservations, runWithFetchDedupe, setCurrentFetchCacheMode, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault, setRefreshStaleFetchesInForeground } from "../shims/fetch-cache.js";
|
|
10
|
+
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader } from "./app-rsc-cache-busting.js";
|
|
10
11
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
11
12
|
import "./app-page-response.js";
|
|
12
13
|
import { buildAppPageSpecialErrorResponse, probeAppPageThrownError, resolveAppPageSpecialError } from "./app-page-execution.js";
|
|
@@ -100,6 +101,10 @@ function getEffectiveLayoutClassifications(route, debugClassification) {
|
|
|
100
101
|
function shouldReadAppPageCache(options) {
|
|
101
102
|
return options.isProduction && !options.isProgressiveActionRender && !options.isDraftMode && !options.isForceDynamic && (options.isRscRequest || !options.scriptNonce) && (options.revalidateSeconds === null || options.revalidateSeconds > 0);
|
|
102
103
|
}
|
|
104
|
+
function resolveAppPageCacheReadRevalidateSeconds(options) {
|
|
105
|
+
if (options.revalidateSeconds === null && (options.isForceStatic || options.isDynamicError)) return Infinity;
|
|
106
|
+
return options.revalidateSeconds ?? 0;
|
|
107
|
+
}
|
|
103
108
|
function hasSearchParams(searchParams) {
|
|
104
109
|
return searchParams !== null && searchParams !== void 0 && searchParams.size > 0;
|
|
105
110
|
}
|
|
@@ -119,6 +124,7 @@ async function runAppPageRevalidationContext(options, renderFn) {
|
|
|
119
124
|
unstableCacheRevalidation: "foreground"
|
|
120
125
|
}), async () => {
|
|
121
126
|
ensureFetchPatch();
|
|
127
|
+
setRefreshStaleFetchesInForeground(process.env.VINEXT_PRERENDER === "1");
|
|
122
128
|
setCurrentFetchSoftTags(buildAppPageTags(options.cleanPathname, [], options.routeSegments));
|
|
123
129
|
options.setNavigationContext({
|
|
124
130
|
pathname: options.displayPathname ?? options.cleanPathname,
|
|
@@ -154,12 +160,14 @@ async function dispatchAppPageInner(options) {
|
|
|
154
160
|
const isForceStatic = dynamicConfig === "force-static";
|
|
155
161
|
const isDynamicError = dynamicConfig === "error";
|
|
156
162
|
const isForceDynamic = dynamicConfig === "force-dynamic";
|
|
163
|
+
const isPrefetchDynamicShell = options.renderMode === APP_RSC_RENDER_MODE_PREFETCH_DYNAMIC_SHELL;
|
|
157
164
|
const isDraftMode = isDraftModeRequest(options.request, options.draftModeSecret);
|
|
158
165
|
const requestHeadersContext = getHeadersContext();
|
|
159
|
-
const
|
|
160
|
-
const
|
|
166
|
+
const shouldUseEmptySearchParams = isForceStatic || isPrefetchDynamicShell;
|
|
167
|
+
const hasRequestSearchParams = !shouldUseEmptySearchParams && hasSearchParams(options.searchParams);
|
|
168
|
+
const pageSearchParams = shouldUseEmptySearchParams ? new URLSearchParams() : options.searchParams;
|
|
161
169
|
const layoutParamAccess = createAppLayoutParamAccessTracker();
|
|
162
|
-
const hasActiveLoadingBoundary =
|
|
170
|
+
const hasActiveLoadingBoundary = Boolean(route.loading?.default);
|
|
163
171
|
setCurrentFetchSoftTags(buildAppPageTags(options.cleanPathname, [], route.routeSegments));
|
|
164
172
|
setCurrentFetchCacheMode(options.fetchCache ?? null);
|
|
165
173
|
setCurrentForceDynamicFetchDefault(isForceDynamic);
|
|
@@ -222,7 +230,11 @@ async function dispatchAppPageInner(options) {
|
|
|
222
230
|
mountedSlotsHeader: options.mountedSlotsHeader,
|
|
223
231
|
renderMode: options.renderMode,
|
|
224
232
|
expireSeconds: options.expireSeconds,
|
|
225
|
-
revalidateSeconds:
|
|
233
|
+
revalidateSeconds: resolveAppPageCacheReadRevalidateSeconds({
|
|
234
|
+
isDynamicError,
|
|
235
|
+
isForceStatic,
|
|
236
|
+
revalidateSeconds: currentRevalidateSeconds
|
|
237
|
+
}),
|
|
226
238
|
renderFreshPageForCache: async () => {
|
|
227
239
|
const revalidationTarget = await resolveAppPageInterceptionRerenderTarget({
|
|
228
240
|
cleanPathname: options.cleanPathname,
|
|
@@ -361,6 +373,7 @@ async function dispatchAppPageInner(options) {
|
|
|
361
373
|
});
|
|
362
374
|
mergeMiddlewareResponseHeaders(interceptHeaders, options.middlewareContext.headers);
|
|
363
375
|
applyRscCompatibilityIdHeader(interceptHeaders);
|
|
376
|
+
applyRscDeploymentIdHeader(interceptHeaders);
|
|
364
377
|
return new Response(interceptStream, {
|
|
365
378
|
status: options.middlewareContext.status ?? 200,
|
|
366
379
|
headers: interceptHeaders
|
|
@@ -388,7 +401,7 @@ async function dispatchAppPageInner(options) {
|
|
|
388
401
|
});
|
|
389
402
|
},
|
|
390
403
|
async probePageSpecialError() {
|
|
391
|
-
if (
|
|
404
|
+
if (route.loading?.default) return null;
|
|
392
405
|
return resolveAppPageSpecialError(await probeAppPageThrownError({
|
|
393
406
|
probePage: () => options.probePage(pageSearchParams),
|
|
394
407
|
runWithSuppressedHookWarning(probe) {
|
|
@@ -428,6 +441,8 @@ async function dispatchAppPageInner(options) {
|
|
|
428
441
|
const activeFallbackShellState = options.pprRuntime?.getState() ?? null;
|
|
429
442
|
const pprFallbackShellSignal = activeFallbackShellState?.abortController.signal;
|
|
430
443
|
const pprFallbackShellReactSignal = activeFallbackShellState?.reactAbortController.signal;
|
|
444
|
+
const isPrerender = process.env.VINEXT_PRERENDER === "1";
|
|
445
|
+
const isSpeculativePrerender = isPrerender && options.request.headers.get("x-vinext-prerender-speculative") === "1";
|
|
431
446
|
return renderAppPageLifecycle({
|
|
432
447
|
basePath: options.basePath,
|
|
433
448
|
clientTraceMetadata: options.clientTraceMetadata,
|
|
@@ -459,7 +474,7 @@ async function dispatchAppPageInner(options) {
|
|
|
459
474
|
},
|
|
460
475
|
handlerStart: options.handlerStart,
|
|
461
476
|
hasLoadingBoundary: hasActiveLoadingBoundary,
|
|
462
|
-
omitPendingDynamicCacheState:
|
|
477
|
+
omitPendingDynamicCacheState: hasRequestSearchParams,
|
|
463
478
|
formState: options.formState ?? null,
|
|
464
479
|
isProgressiveActionRender: options.isProgressiveActionRender === true,
|
|
465
480
|
isDynamicError,
|
|
@@ -467,7 +482,8 @@ async function dispatchAppPageInner(options) {
|
|
|
467
482
|
isForceDynamic,
|
|
468
483
|
isForceStatic,
|
|
469
484
|
isEdgeRuntime: options.isEdgeRuntime === true,
|
|
470
|
-
isPrerender
|
|
485
|
+
isPrerender,
|
|
486
|
+
isSpeculativePrerender,
|
|
471
487
|
isProduction: options.isProduction,
|
|
472
488
|
isRscRequest: options.isRscRequest,
|
|
473
489
|
isrDebug: options.isrDebug,
|
|
@@ -483,6 +499,7 @@ async function dispatchAppPageInner(options) {
|
|
|
483
499
|
params: options.params,
|
|
484
500
|
pprFallbackShellSignal,
|
|
485
501
|
pprFallbackShellReactSignal,
|
|
502
|
+
renderedPathAndSearch: options.renderedPathAndSearch,
|
|
486
503
|
abortPprFallbackShell: activeFallbackShellState ? () => {
|
|
487
504
|
options.pprRuntime.beginFinalRender(activeFallbackShellState);
|
|
488
505
|
} : void 0,
|
|
@@ -51,6 +51,7 @@ async function buildPageElements(options) {
|
|
|
51
51
|
const hasPageModule = !!pageModule;
|
|
52
52
|
const renderIdentity = createAppPageRenderIdentity({
|
|
53
53
|
displayPathname,
|
|
54
|
+
matchedRoutePathname: routePath,
|
|
54
55
|
targetMatchedPathname: routePath,
|
|
55
56
|
interceptionContext: opts?.interceptionContext ?? null,
|
|
56
57
|
interceptSourceMatchedUrl: opts?.interceptSourceMatchedUrl ?? null,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { addBasePathToPathname } from "../utils/base-path.js";
|
|
2
2
|
import { VINEXT_RSC_REDIRECT_HEADER } from "./headers.js";
|
|
3
3
|
import { runWithConnectionProbe } from "../shims/headers.js";
|
|
4
|
-
import { VINEXT_RSC_CONTENT_TYPE, applyRscCompatibilityIdHeader, createRscRedirectLocation } from "./app-rsc-cache-busting.js";
|
|
4
|
+
import { VINEXT_RSC_CONTENT_TYPE, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader, createRscRedirectLocation } from "./app-rsc-cache-busting.js";
|
|
5
5
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
6
6
|
import { applyEdgeRuntimeHeader } from "./app-page-response.js";
|
|
7
7
|
import { parseNextHttpErrorDigest, parseNextRedirectDigest } from "./next-error-digest.js";
|
|
@@ -161,6 +161,7 @@ async function buildAppPageSpecialErrorResponse(options) {
|
|
|
161
161
|
});
|
|
162
162
|
applyEdgeRuntimeHeader(headers, options.isEdgeRuntime);
|
|
163
163
|
applyRscCompatibilityIdHeader(headers);
|
|
164
|
+
applyRscDeploymentIdHeader(headers);
|
|
164
165
|
mergeMiddlewareResponseHeaders(headers, options.middlewareContext?.headers ?? null);
|
|
165
166
|
const pendingCookies = options.getAndClearPendingCookies?.() ?? [];
|
|
166
167
|
for (const cookie of pendingCookies) headers.append("Set-Cookie", cookie);
|
|
@@ -2,6 +2,7 @@ import { AppElementsInterception } from "./app-elements-wire.js";
|
|
|
2
2
|
//#region src/server/app-page-render-identity.d.ts
|
|
3
3
|
type AppPageRenderIdentityInput = {
|
|
4
4
|
displayPathname: string;
|
|
5
|
+
matchedRoutePathname?: string;
|
|
5
6
|
targetMatchedPathname?: string;
|
|
6
7
|
interceptionContext?: string | null;
|
|
7
8
|
interceptSourceMatchedUrl?: string | null;
|
|
@@ -14,9 +14,10 @@ function normalizeAppPageInterceptionProofPathname(pathname) {
|
|
|
14
14
|
function createAppPageRenderIdentity(input) {
|
|
15
15
|
const interceptionContext = input.interceptionContext ?? null;
|
|
16
16
|
const targetMatchedPathname = normalizeAppPageRenderMatchedPathname(input.targetMatchedPathname ?? input.displayPathname);
|
|
17
|
+
const requestedMatchedRoutePathname = normalizeAppPageRenderMatchedPathname(input.matchedRoutePathname ?? input.targetMatchedPathname ?? input.displayPathname);
|
|
17
18
|
const sourceMatchedPathname = normalizeAppPageInterceptionProofPathname(input.interceptSourceMatchedUrl ?? null);
|
|
18
19
|
const slotId = input.interceptSlotId ?? null;
|
|
19
|
-
const matchedRoutePathname = sourceMatchedPathname ??
|
|
20
|
+
const matchedRoutePathname = sourceMatchedPathname ?? requestedMatchedRoutePathname;
|
|
20
21
|
const routeId = AppElementsWire.encodeRouteId(matchedRoutePathname, null);
|
|
21
22
|
const pageId = AppElementsWire.encodePageId(matchedRoutePathname, null);
|
|
22
23
|
const interception = sourceMatchedPathname === null || slotId === null ? null : {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { CachedAppPageValue } from "../shims/cache-handler.js";
|
|
2
1
|
import { ClientReuseManifestParseResult, ClientReuseManifestSkipDisposition } from "./client-reuse-manifest.js";
|
|
3
2
|
import { AppOutgoingElements } from "./app-elements-wire.js";
|
|
4
3
|
import { NavigationContext } from "../shims/navigation-context-state.js";
|
|
@@ -7,6 +6,7 @@ import { AppPageMiddlewareContext } from "./app-page-response.js";
|
|
|
7
6
|
import { RootParams } from "../shims/root-params.js";
|
|
8
7
|
import { AppPageSsrHandler } from "./app-page-stream.js";
|
|
9
8
|
import { AppLayoutParamAccessTracker } from "./app-layout-param-observation.js";
|
|
9
|
+
import { CachedAppPageValue } from "../shims/cache-handler.js";
|
|
10
10
|
import { AppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
11
11
|
import { AppPageRenderObservationState } from "./app-page-render-observation.js";
|
|
12
12
|
import { ReactNode } from "react";
|
|
@@ -60,6 +60,7 @@ type RenderAppPageLifecycleOptions = {
|
|
|
60
60
|
isForceStatic: boolean;
|
|
61
61
|
isProgressiveActionRender?: boolean;
|
|
62
62
|
isPrerender?: boolean;
|
|
63
|
+
isSpeculativePrerender?: boolean;
|
|
63
64
|
isProduction: boolean;
|
|
64
65
|
probePageBeforeRender?: boolean;
|
|
65
66
|
omitPendingDynamicCacheState?: boolean;
|
|
@@ -103,6 +104,7 @@ type RenderAppPageLifecycleOptions = {
|
|
|
103
104
|
clientReuseManifest?: ClientReuseManifestParseResult;
|
|
104
105
|
skipDisposition?: ClientReuseManifestSkipDisposition;
|
|
105
106
|
mountedSlotsHeader?: string | null;
|
|
107
|
+
renderedPathAndSearch?: string | null;
|
|
106
108
|
renderMode?: AppRscRenderMode;
|
|
107
109
|
waitUntil?: (promise: Promise<void>) => void;
|
|
108
110
|
layoutParamAccess?: AppLayoutParamAccessTracker;
|
|
@@ -27,8 +27,14 @@ function buildResponseTiming(options) {
|
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
function readRequestCacheLifeForPrerender(options) {
|
|
30
|
+
if (options.isEdgeRuntime && options.revalidateSeconds === null) return (options.peekRequestCacheLife?.() ?? options.getRequestCacheLife())?.revalidate !== void 0 ? { revalidate: 0 } : null;
|
|
30
31
|
return options.peekRequestCacheLife?.() ?? options.getRequestCacheLife();
|
|
31
32
|
}
|
|
33
|
+
function readRequestCacheLifeForCachePolicy(options) {
|
|
34
|
+
const requestCacheLife = options.getRequestCacheLife();
|
|
35
|
+
if (options.isEdgeRuntime && options.revalidateSeconds === null) return null;
|
|
36
|
+
return requestCacheLife;
|
|
37
|
+
}
|
|
32
38
|
function applyRequestCacheLife(options) {
|
|
33
39
|
let revalidateSeconds = options.revalidateSeconds;
|
|
34
40
|
let expireSeconds = options.expireSeconds;
|
|
@@ -40,6 +46,10 @@ function applyRequestCacheLife(options) {
|
|
|
40
46
|
revalidateSeconds
|
|
41
47
|
};
|
|
42
48
|
}
|
|
49
|
+
function resolveAppPageCacheWriteRevalidateSeconds(options) {
|
|
50
|
+
if (options.revalidateSeconds === null && (options.isForceStatic || options.isDynamicError)) return Infinity;
|
|
51
|
+
return options.revalidateSeconds;
|
|
52
|
+
}
|
|
43
53
|
function readRootBoundaryId(element) {
|
|
44
54
|
const rootLayoutTreePath = element[AppElementsWire.keys.rootLayout];
|
|
45
55
|
return typeof rootLayoutTreePath === "string" ? rootLayoutTreePath : null;
|
|
@@ -338,6 +348,8 @@ async function renderAppPageLifecycle(options) {
|
|
|
338
348
|
if (options.pprFallbackShellSignal) pprFallbackShellRsc = new Uint8Array(await readAppPageBinaryStream(rscStream));
|
|
339
349
|
let revalidateSeconds = options.revalidateSeconds;
|
|
340
350
|
let expireSeconds = options.expireSeconds;
|
|
351
|
+
const shouldWaitForAllReady = options.isPrerender === true && options.isSpeculativePrerender !== true;
|
|
352
|
+
const shouldReadRequestCacheLifeForPrerender = options.isPrerender === true;
|
|
341
353
|
const shouldCaptureRscForCacheMetadata = options.isProgressiveActionRender !== true && (options.isProduction || options.isPrerender === true) && (revalidateSeconds === null || revalidateSeconds > 0 && revalidateSeconds !== Infinity) && !options.isDraftMode && !options.isForceDynamic && !shouldBypassRscCacheForSkipTransport;
|
|
342
354
|
const createBufferedRscStream = (close) => new ReadableStream({ start(controller) {
|
|
343
355
|
if (pprFallbackShellRsc) controller.enqueue(pprFallbackShellRsc);
|
|
@@ -351,11 +363,13 @@ async function renderAppPageLifecycle(options) {
|
|
|
351
363
|
const capturedRscDataRef = { value: null };
|
|
352
364
|
if (rscCapture.sideStream && options.isRscRequest) capturedRscDataRef.value = readAppPageBinaryStream(rscCapture.sideStream);
|
|
353
365
|
if (options.isRscRequest) {
|
|
354
|
-
|
|
355
|
-
|
|
366
|
+
let requestCacheLifeForPrerender = null;
|
|
367
|
+
if (shouldWaitForAllReady) await settleCapturedRscRenderForCacheMetadata(capturedRscDataRef.value);
|
|
368
|
+
if (shouldReadRequestCacheLifeForPrerender) {
|
|
369
|
+
requestCacheLifeForPrerender = readRequestCacheLifeForPrerender(options);
|
|
356
370
|
({expireSeconds, revalidateSeconds} = applyRequestCacheLife({
|
|
357
371
|
expireSeconds,
|
|
358
|
-
requestCacheLife:
|
|
372
|
+
requestCacheLife: requestCacheLifeForPrerender,
|
|
359
373
|
revalidateSeconds
|
|
360
374
|
}));
|
|
361
375
|
}
|
|
@@ -378,6 +392,8 @@ async function renderAppPageLifecycle(options) {
|
|
|
378
392
|
mountedSlotsHeader: options.mountedSlotsHeader,
|
|
379
393
|
params: options.navigationParams,
|
|
380
394
|
policy: rscResponsePolicy,
|
|
395
|
+
renderedPathAndSearch: options.renderedPathAndSearch,
|
|
396
|
+
requestCacheLife: requestCacheLifeForPrerender,
|
|
381
397
|
timing: buildResponseTiming({
|
|
382
398
|
compileEnd,
|
|
383
399
|
handlerStart: options.handlerStart,
|
|
@@ -407,17 +423,22 @@ async function renderAppPageLifecycle(options) {
|
|
|
407
423
|
return options.getPageTags();
|
|
408
424
|
},
|
|
409
425
|
getRequestCacheLife() {
|
|
410
|
-
return options
|
|
426
|
+
return readRequestCacheLifeForCachePolicy(options);
|
|
411
427
|
},
|
|
412
428
|
isrDebug: options.isrDebug,
|
|
413
429
|
isrRscKey: options.isrRscKey,
|
|
414
430
|
isrSet: options.isrSet,
|
|
415
431
|
interceptionContext: options.interceptionContext,
|
|
416
432
|
mountedSlotsHeader: options.mountedSlotsHeader,
|
|
433
|
+
omitPendingDynamicCacheState: options.omitPendingDynamicCacheState,
|
|
417
434
|
renderMode: options.renderMode,
|
|
418
435
|
preserveClientResponseHeaders: rscResponsePolicy.cacheState !== "MISS",
|
|
419
436
|
expireSeconds,
|
|
420
|
-
revalidateSeconds
|
|
437
|
+
revalidateSeconds: resolveAppPageCacheWriteRevalidateSeconds({
|
|
438
|
+
isDynamicError: options.isDynamicError,
|
|
439
|
+
isForceStatic: options.isForceStatic,
|
|
440
|
+
revalidateSeconds
|
|
441
|
+
}),
|
|
421
442
|
waitUntil(promise) {
|
|
422
443
|
options.waitUntil?.(promise);
|
|
423
444
|
}
|
|
@@ -469,7 +490,8 @@ async function renderAppPageLifecycle(options) {
|
|
|
469
490
|
scriptNonce: options.scriptNonce,
|
|
470
491
|
sideStream: rscCapture.sideStream,
|
|
471
492
|
ssrHandler,
|
|
472
|
-
|
|
493
|
+
fallbackToErrorDocumentOnShellError: options.isPrerender === true && options.isSpeculativePrerender === true ? false : void 0,
|
|
494
|
+
waitForAllReady: shouldWaitForAllReady
|
|
473
495
|
});
|
|
474
496
|
},
|
|
475
497
|
renderSpecialErrorResponse(specialError) {
|
|
@@ -492,15 +514,27 @@ async function renderAppPageLifecycle(options) {
|
|
|
492
514
|
}
|
|
493
515
|
}
|
|
494
516
|
}
|
|
495
|
-
|
|
496
|
-
|
|
517
|
+
let requestCacheLifeForPrerender = null;
|
|
518
|
+
let dynamicUsedDuringRender = options.consumeDynamicUsage();
|
|
519
|
+
dynamicUsedDuringHtmlRender = dynamicUsedDuringRender;
|
|
520
|
+
const stopSpeculativeMetadataWaitOnDynamicUsage = options.isSpeculativePrerender === true && shouldReadRequestCacheLifeForPrerender ? () => {
|
|
521
|
+
if (dynamicUsedDuringRender || (options.peekDynamicUsage?.() ?? peekDynamicUsage())) {
|
|
522
|
+
dynamicUsedDuringRender = true;
|
|
523
|
+
dynamicUsedDuringHtmlRender = true;
|
|
524
|
+
return true;
|
|
525
|
+
}
|
|
526
|
+
return false;
|
|
527
|
+
} : void 0;
|
|
528
|
+
if (shouldWaitForAllReady || shouldReadRequestCacheLifeForPrerender) await settleCapturedRscRenderForCacheMetadata(htmlRender.capturedRscData, stopSpeculativeMetadataWaitOnDynamicUsage);
|
|
529
|
+
if (shouldReadRequestCacheLifeForPrerender) {
|
|
530
|
+
requestCacheLifeForPrerender = readRequestCacheLifeForPrerender(options);
|
|
497
531
|
({expireSeconds, revalidateSeconds} = applyRequestCacheLife({
|
|
498
532
|
expireSeconds,
|
|
499
|
-
requestCacheLife:
|
|
533
|
+
requestCacheLife: requestCacheLifeForPrerender,
|
|
500
534
|
revalidateSeconds
|
|
501
535
|
}));
|
|
502
536
|
}
|
|
503
|
-
|
|
537
|
+
dynamicUsedDuringRender = dynamicUsedDuringRender || options.consumeDynamicUsage();
|
|
504
538
|
dynamicUsedDuringHtmlRender = dynamicUsedDuringRender;
|
|
505
539
|
const draftCookie = options.getDraftModeCookieHeader();
|
|
506
540
|
let dynamicUsedBeforeContextCleanup = dynamicUsedDuringRender;
|
|
@@ -538,12 +572,13 @@ async function renderAppPageLifecycle(options) {
|
|
|
538
572
|
status: 500
|
|
539
573
|
},
|
|
540
574
|
policy: { cacheControl: NEVER_CACHE_CONTROL },
|
|
575
|
+
requestCacheLife: requestCacheLifeForPrerender,
|
|
541
576
|
timing: htmlResponseTiming
|
|
542
577
|
});
|
|
543
578
|
applyCdnResponseHeaders(response.headers, { cacheControl: NEVER_CACHE_CONTROL });
|
|
544
579
|
return response;
|
|
545
580
|
}
|
|
546
|
-
const shouldSpeculativelyWriteCache = options.isProduction && shouldCaptureRscForCacheMetadata && revalidateSeconds === null && !options.isDynamicError && !options.isForceStatic && !options.scriptNonce && options.isProgressiveActionRender !== true && !dynamicUsedDuringRender;
|
|
581
|
+
const shouldSpeculativelyWriteCache = options.isProduction && shouldCaptureRscForCacheMetadata && !options.isEdgeRuntime && revalidateSeconds === null && !options.isDynamicError && !options.isForceStatic && !options.scriptNonce && options.isProgressiveActionRender !== true && !dynamicUsedDuringRender;
|
|
547
582
|
if (htmlResponsePolicy.shouldWriteToCache || shouldSpeculativelyWriteCache) {
|
|
548
583
|
const isrResponse = buildAppPageHtmlResponse(safeHtmlStream, {
|
|
549
584
|
draftCookie,
|
|
@@ -551,6 +586,7 @@ async function renderAppPageLifecycle(options) {
|
|
|
551
586
|
isEdgeRuntime: options.isEdgeRuntime,
|
|
552
587
|
middlewareContext: options.middlewareContext,
|
|
553
588
|
policy: htmlResponsePolicy,
|
|
589
|
+
requestCacheLife: requestCacheLifeForPrerender,
|
|
554
590
|
timing: htmlResponseTiming
|
|
555
591
|
});
|
|
556
592
|
if (options.isPrerender === true) return isrResponse;
|
|
@@ -590,7 +626,7 @@ async function renderAppPageLifecycle(options) {
|
|
|
590
626
|
return options.getPageTags();
|
|
591
627
|
},
|
|
592
628
|
getRequestCacheLife() {
|
|
593
|
-
return options
|
|
629
|
+
return readRequestCacheLifeForCachePolicy(options);
|
|
594
630
|
},
|
|
595
631
|
isrDebug: options.isrDebug,
|
|
596
632
|
isrHtmlKey: options.isrHtmlKey,
|
|
@@ -600,7 +636,11 @@ async function renderAppPageLifecycle(options) {
|
|
|
600
636
|
omitPendingDynamicCacheState: options.omitPendingDynamicCacheState,
|
|
601
637
|
preserveClientResponseHeaders: !htmlResponsePolicy.shouldWriteToCache,
|
|
602
638
|
expireSeconds,
|
|
603
|
-
revalidateSeconds
|
|
639
|
+
revalidateSeconds: resolveAppPageCacheWriteRevalidateSeconds({
|
|
640
|
+
isDynamicError: options.isDynamicError,
|
|
641
|
+
isForceStatic: options.isForceStatic,
|
|
642
|
+
revalidateSeconds
|
|
643
|
+
}),
|
|
604
644
|
waitUntil(cachePromise) {
|
|
605
645
|
options.waitUntil?.(cachePromise);
|
|
606
646
|
}
|
|
@@ -612,14 +652,25 @@ async function renderAppPageLifecycle(options) {
|
|
|
612
652
|
isEdgeRuntime: options.isEdgeRuntime,
|
|
613
653
|
middlewareContext: options.middlewareContext,
|
|
614
654
|
policy: htmlResponsePolicy,
|
|
655
|
+
requestCacheLife: requestCacheLifeForPrerender,
|
|
615
656
|
timing: htmlResponseTiming
|
|
616
657
|
});
|
|
617
658
|
}
|
|
618
|
-
async function settleCapturedRscRenderForCacheMetadata(capturedRscDataPromise) {
|
|
659
|
+
async function settleCapturedRscRenderForCacheMetadata(capturedRscDataPromise, shouldStopWaiting) {
|
|
619
660
|
if (!capturedRscDataPromise) return;
|
|
661
|
+
if (!shouldStopWaiting) {
|
|
662
|
+
try {
|
|
663
|
+
await capturedRscDataPromise;
|
|
664
|
+
} catch {}
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
let settled = false;
|
|
668
|
+
const settledPromise = capturedRscDataPromise.catch(() => {}).then(() => {
|
|
669
|
+
settled = true;
|
|
670
|
+
});
|
|
620
671
|
try {
|
|
621
|
-
await
|
|
622
|
-
}
|
|
672
|
+
while (!settled && !shouldStopWaiting()) await Promise.race([settledPromise, new Promise((resolve) => setTimeout(resolve, 0))]);
|
|
673
|
+
} finally {}
|
|
623
674
|
}
|
|
624
675
|
//#endregion
|
|
625
676
|
export { renderAppPageLifecycle };
|
|
@@ -15,6 +15,10 @@ type AppPageResponsePolicy = {
|
|
|
15
15
|
cacheControl?: string;
|
|
16
16
|
cacheState?: "MISS" | "STATIC";
|
|
17
17
|
};
|
|
18
|
+
type AppPagePrerenderCacheLife = {
|
|
19
|
+
expire?: number;
|
|
20
|
+
revalidate?: number;
|
|
21
|
+
};
|
|
18
22
|
type ResolveAppPageResponsePolicyBaseOptions = {
|
|
19
23
|
isDraftMode: boolean;
|
|
20
24
|
isDynamicError: boolean;
|
|
@@ -42,6 +46,8 @@ type BuildAppPageRscResponseOptions = {
|
|
|
42
46
|
mountedSlotsHeader?: string | null;
|
|
43
47
|
params?: Record<string, unknown>;
|
|
44
48
|
policy: AppPageResponsePolicy;
|
|
49
|
+
renderedPathAndSearch?: string | null;
|
|
50
|
+
requestCacheLife?: AppPagePrerenderCacheLife | null;
|
|
45
51
|
timing?: AppPageResponseTiming;
|
|
46
52
|
};
|
|
47
53
|
type BuildAppPageHtmlResponseOptions = {
|
|
@@ -50,6 +56,7 @@ type BuildAppPageHtmlResponseOptions = {
|
|
|
50
56
|
isEdgeRuntime?: boolean;
|
|
51
57
|
middlewareContext: AppPageMiddlewareContext;
|
|
52
58
|
policy: AppPageResponsePolicy;
|
|
59
|
+
requestCacheLife?: AppPagePrerenderCacheLife | null;
|
|
53
60
|
timing?: AppPageResponseTiming;
|
|
54
61
|
};
|
|
55
62
|
declare function resolveAppPageRscResponsePolicy(options: ResolveAppPageRscResponsePolicyOptions): AppPageResponsePolicy;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_PARAMS_HEADER, VINEXT_TIMING_HEADER } from "./headers.js";
|
|
1
|
+
import { VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_CACHE_LIFE_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_TIMING_HEADER } from "./headers.js";
|
|
2
2
|
import { setCacheStateHeaders } from "./cache-headers.js";
|
|
3
3
|
import { NO_STORE_CACHE_CONTROL, STATIC_CACHE_CONTROL, buildRevalidateCacheControl } from "./cache-control.js";
|
|
4
|
-
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
|
|
4
|
+
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader } from "./app-rsc-cache-busting.js";
|
|
5
5
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
6
6
|
//#region src/server/app-page-response.ts
|
|
7
7
|
function applyTimingHeader(headers, timing) {
|
|
@@ -14,6 +14,14 @@ function applyTimingHeader(headers, timing) {
|
|
|
14
14
|
function applyDynamicStaleTimeHeader(headers, dynamicStaleTimeSeconds) {
|
|
15
15
|
if (dynamicStaleTimeSeconds !== void 0 && Number.isInteger(dynamicStaleTimeSeconds) && dynamicStaleTimeSeconds >= 0) headers.set(VINEXT_DYNAMIC_STALE_TIME_HEADER, String(dynamicStaleTimeSeconds));
|
|
16
16
|
}
|
|
17
|
+
function applyPrerenderCacheLifeHeader(headers, requestCacheLife) {
|
|
18
|
+
if (!requestCacheLife) return;
|
|
19
|
+
const payload = {};
|
|
20
|
+
if (typeof requestCacheLife.revalidate === "number" && Number.isFinite(requestCacheLife.revalidate)) payload.revalidate = requestCacheLife.revalidate;
|
|
21
|
+
if (typeof requestCacheLife.expire === "number" && Number.isFinite(requestCacheLife.expire)) payload.expire = requestCacheLife.expire;
|
|
22
|
+
if (payload.revalidate === void 0 && payload.expire === void 0) return;
|
|
23
|
+
headers.set(VINEXT_PRERENDER_CACHE_LIFE_HEADER, JSON.stringify(payload));
|
|
24
|
+
}
|
|
17
25
|
function resolveAppPageRscResponsePolicy(options) {
|
|
18
26
|
if (options.isDraftMode) return { cacheControl: NO_STORE_CACHE_CONTROL };
|
|
19
27
|
if (options.isForceDynamic || options.dynamicUsedDuringBuild) return { cacheControl: NO_STORE_CACHE_CONTROL };
|
|
@@ -51,8 +59,8 @@ function resolveAppPageHtmlResponsePolicy(options) {
|
|
|
51
59
|
};
|
|
52
60
|
if ((options.isForceStatic || options.isDynamicError) && options.revalidateSeconds === null) return {
|
|
53
61
|
cacheControl: STATIC_CACHE_CONTROL,
|
|
54
|
-
cacheState: "STATIC",
|
|
55
|
-
shouldWriteToCache:
|
|
62
|
+
cacheState: options.isProduction ? "MISS" : "STATIC",
|
|
63
|
+
shouldWriteToCache: options.isProduction
|
|
56
64
|
};
|
|
57
65
|
if (options.dynamicUsedDuringRender) return {
|
|
58
66
|
cacheControl: NO_STORE_CACHE_CONTROL,
|
|
@@ -92,7 +100,10 @@ function buildAppPageRscResponse(body, options) {
|
|
|
92
100
|
if (options.policy.cacheControl) headers.set("Cache-Control", options.policy.cacheControl);
|
|
93
101
|
if (options.policy.cacheState) setCacheStateHeaders(headers, options.policy.cacheState);
|
|
94
102
|
mergeMiddlewareResponseHeaders(headers, options.middlewareContext.headers);
|
|
103
|
+
if (options.renderedPathAndSearch) headers.set(VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, encodeURIComponent(options.renderedPathAndSearch));
|
|
95
104
|
applyRscCompatibilityIdHeader(headers);
|
|
105
|
+
applyRscDeploymentIdHeader(headers);
|
|
106
|
+
applyPrerenderCacheLifeHeader(headers, options.requestCacheLife);
|
|
96
107
|
applyTimingHeader(headers, options.timing);
|
|
97
108
|
return new Response(body, {
|
|
98
109
|
status: options.middlewareContext.status ?? 200,
|
|
@@ -110,6 +121,7 @@ function buildAppPageHtmlResponse(body, options) {
|
|
|
110
121
|
if (options.draftCookie) headers.append("Set-Cookie", options.draftCookie);
|
|
111
122
|
if (options.linkHeader) headers.set("Link", options.linkHeader);
|
|
112
123
|
mergeMiddlewareResponseHeaders(headers, options.middlewareContext.headers);
|
|
124
|
+
applyPrerenderCacheLifeHeader(headers, options.requestCacheLife);
|
|
113
125
|
applyTimingHeader(headers, options.timing);
|
|
114
126
|
return new Response(body, {
|
|
115
127
|
status: options.middlewareContext.status ?? 200,
|