vinext 1.0.1 → 1.1.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 +72 -1
- package/dist/build/app-page-static-eligibility.d.ts +15 -0
- package/dist/build/app-page-static-eligibility.js +82 -0
- package/dist/build/prerender-paths.js +3 -78
- package/dist/build/prerender.js +33 -8
- package/dist/build/server-manifest.d.ts +7 -0
- package/dist/build/server-manifest.js +11 -1
- package/dist/cache/cache-adapters-virtual.d.ts +7 -1
- package/dist/cache/cache-adapters-virtual.js +3 -3
- package/dist/client/navigation-runtime.d.ts +11 -0
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/config-matchers.js +3 -1
- package/dist/config/next-config.d.ts +7 -0
- package/dist/config/next-config.js +18 -3
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +64 -43
- package/dist/index.d.ts +4 -1
- package/dist/index.js +59 -30
- package/dist/plugins/cache-flight-codec.d.ts +19 -0
- package/dist/plugins/cache-flight-codec.js +68 -0
- package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
- package/dist/plugins/commonjs-esm-facade.js +80 -0
- package/dist/plugins/fonts.d.ts +8 -11
- package/dist/plugins/fonts.js +71 -34
- package/dist/routing/file-matcher.d.ts +1 -0
- package/dist/routing/file-matcher.js +1 -1
- package/dist/server/api-handler.js +17 -7
- package/dist/server/app-browser-entry.js +11 -7
- package/dist/server/app-browser-history-controller.d.ts +2 -0
- package/dist/server/app-browser-history-controller.js +8 -0
- package/dist/server/app-browser-interception-context.js +26 -2
- package/dist/server/app-browser-navigation-controller.d.ts +7 -1
- package/dist/server/app-browser-navigation-controller.js +93 -10
- package/dist/server/app-fallback-renderer.d.ts +2 -0
- package/dist/server/app-fallback-renderer.js +1 -0
- package/dist/server/app-history-state.d.ts +3 -0
- package/dist/server/app-history-state.js +7 -0
- package/dist/server/app-middleware.js +2 -1
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-boundary-render.d.ts +5 -0
- package/dist/server/app-page-boundary-render.js +6 -4
- package/dist/server/app-page-cache-finalizer.d.ts +11 -0
- package/dist/server/app-page-cache-finalizer.js +41 -7
- package/dist/server/app-page-cache-render.d.ts +18 -0
- package/dist/server/app-page-cache-render.js +63 -43
- package/dist/server/app-page-cache.d.ts +5 -0
- package/dist/server/app-page-cache.js +27 -7
- package/dist/server/app-page-dispatch.d.ts +9 -1
- package/dist/server/app-page-dispatch.js +47 -30
- package/dist/server/app-page-element-builder.d.ts +7 -0
- package/dist/server/app-page-element-builder.js +27 -42
- package/dist/server/app-page-execution.d.ts +15 -12
- package/dist/server/app-page-execution.js +30 -40
- package/dist/server/app-page-head.d.ts +5 -0
- package/dist/server/app-page-head.js +9 -3
- package/dist/server/app-page-probe.d.ts +0 -109
- package/dist/server/app-page-probe.js +3 -136
- package/dist/server/app-page-render-identity.d.ts +0 -1
- package/dist/server/app-page-render-identity.js +1 -1
- package/dist/server/app-page-render-observation.js +2 -2
- package/dist/server/app-page-render.d.ts +13 -5
- package/dist/server/app-page-render.js +219 -119
- package/dist/server/app-page-request.d.ts +0 -1
- package/dist/server/app-page-request.js +1 -2
- package/dist/server/app-page-response.d.ts +4 -3
- package/dist/server/app-page-response.js +4 -3
- package/dist/server/app-page-route-wiring.d.ts +17 -5
- package/dist/server/app-page-route-wiring.js +55 -33
- package/dist/server/app-page-rsc-render-status.d.ts +48 -0
- package/dist/server/app-page-rsc-render-status.js +54 -0
- package/dist/server/app-page-stream.d.ts +15 -8
- package/dist/server/app-page-stream.js +6 -0
- package/dist/server/app-request-stage-dispatch.js +1 -1
- package/dist/server/app-request-stage-independent-entry.js +4 -4
- package/dist/server/app-response-header-provenance.d.ts +2 -0
- package/dist/server/app-response-header-provenance.js +10 -4
- package/dist/server/app-route-handler-dispatch.js +1 -1
- package/dist/server/app-router-entry.js +3 -3
- package/dist/server/app-rsc-handler.d.ts +4 -0
- package/dist/server/app-rsc-handler.js +212 -96
- package/dist/server/app-rsc-request-normalization.d.ts +3 -1
- package/dist/server/app-rsc-request-normalization.js +4 -2
- package/dist/server/app-rsc-response-stage.d.ts +1 -1
- package/dist/server/app-rsc-response-stage.js +6 -4
- package/dist/server/app-rsc-route-matching.d.ts +9 -1
- package/dist/server/app-rsc-route-matching.js +36 -19
- package/dist/server/app-server-action-execution.js +1 -1
- package/dist/server/app-ssr-entry.d.ts +3 -2
- package/dist/server/app-ssr-entry.js +6 -4
- package/dist/server/app-ssr-stream.d.ts +6 -1
- package/dist/server/app-ssr-stream.js +34 -15
- package/dist/server/app-worker-stages.d.ts +2 -2
- package/dist/server/app-worker-stages.js +3 -3
- package/dist/server/cacheability-request.js +9 -5
- package/dist/server/config-headers.js +2 -0
- package/dist/server/dev-server.js +12 -2
- package/dist/server/headers.d.ts +14 -0
- package/dist/server/headers.js +15 -1
- package/dist/server/image-optimization.d.ts +16 -0
- package/dist/server/image-optimization.js +26 -6
- package/dist/server/isr-cache.js +2 -2
- package/dist/server/middleware-matcher-pattern.js +8 -4
- package/dist/server/middleware-response-headers.js +2 -0
- package/dist/server/multi-stage.d.ts +8 -0
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/node-response-signal.d.ts +16 -0
- package/dist/server/node-response-signal.js +26 -0
- package/dist/server/open-redirect.d.ts +47 -0
- package/dist/server/open-redirect.js +74 -1
- package/dist/server/pages-page-handler.js +21 -4
- package/dist/server/pages-request-stage-entry.js +8 -4
- package/dist/server/prod-server.d.ts +8 -7
- package/dist/server/prod-server.js +153 -69
- package/dist/server/request-pipeline.d.ts +20 -8
- package/dist/server/request-pipeline.js +21 -7
- package/dist/server/response-compression.d.ts +43 -0
- package/dist/server/response-compression.js +111 -0
- package/dist/server/seed-cache.js +10 -7
- package/dist/server/socket-error-backstop.d.ts +14 -0
- package/dist/server/socket-error-backstop.js +27 -4
- package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
- package/dist/shims/cache-adapter-instantiate.js +118 -0
- package/dist/shims/cache-callable-runtime.d.ts +2 -40
- package/dist/shims/cache-callable-runtime.js +50 -168
- package/dist/shims/cache-flight-arguments.d.ts +22 -0
- package/dist/shims/cache-flight-arguments.js +56 -0
- package/dist/shims/cache-request-state.d.ts +15 -0
- package/dist/shims/cache-request-state.js +31 -8
- package/dist/shims/cache-runtime.d.ts +6 -19
- package/dist/shims/cache-runtime.js +165 -225
- package/dist/shims/cache.d.ts +2 -2
- package/dist/shims/cache.js +5 -4
- package/dist/shims/cacheability-classification.d.ts +7 -0
- package/dist/shims/error-boundary-navigation.d.ts +7 -0
- package/dist/shims/error-boundary-navigation.js +19 -1
- package/dist/shims/error-boundary.d.ts +10 -10
- package/dist/shims/error-boundary.js +26 -7
- package/dist/shims/fetch-cache.d.ts +6 -0
- package/dist/shims/fetch-cache.js +19 -1
- package/dist/shims/form.js +1 -1
- package/dist/shims/headers.d.ts +13 -0
- package/dist/shims/headers.js +47 -4
- package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
- package/dist/shims/internal/app-page-props-cache-key.js +24 -15
- package/dist/shims/internal/headers-state.d.ts +0 -1
- package/dist/shims/metadata.js +3 -3
- package/dist/shims/navigation-errors.d.ts +6 -0
- package/dist/shims/navigation-errors.js +11 -1
- package/dist/shims/navigation.d.ts +7 -0
- package/dist/shims/navigation.js +14 -4
- package/dist/shims/request-context.d.ts +9 -0
- package/dist/shims/thenable-params.d.ts +4 -0
- package/dist/shims/thenable-params.js +25 -3
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/utils/mdx-scan.d.ts +5 -0
- package/dist/utils/mdx-scan.js +8 -1
- package/dist/utils/regex-safety.d.ts +10 -0
- package/dist/utils/regex-safety.js +70 -18
- package/package.json +3 -3
|
@@ -1,32 +1,36 @@
|
|
|
1
1
|
import { preserveFullyBufferedBodyMetadata } from "./fully-buffered-response.js";
|
|
2
2
|
import { bindRequestContext } from "../shims/unified-request-context.js";
|
|
3
|
-
import {
|
|
3
|
+
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
4
|
+
import { VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_RSC_COMPLETION_METADATA_HEADER } from "./headers.js";
|
|
4
5
|
import { internalServerErrorResponse } from "./http-error-responses.js";
|
|
5
6
|
import { isRouteCacheabilityEvaluation, recordRouteCacheabilityClientTraceMetadataMarker } from "../shims/cacheability-classification.js";
|
|
6
7
|
import { NEVER_CACHE_CONTROL, NO_STORE_CACHE_CONTROL, applyCdnResponseHeaders, isCdnResponsePolicyHeader } from "./cache-control.js";
|
|
7
|
-
import { createArtifactCompatibilityEnvelope, createArtifactCompatibilityGraphVersion } from "./artifact-compatibility.js";
|
|
8
|
-
import { AppElementsWire, isAppElementsRecord } from "./app-elements-wire.js";
|
|
9
|
-
import "./app-elements.js";
|
|
10
8
|
import { resolveClientStaleTimeSeconds } from "../utils/cache-control-metadata.js";
|
|
11
|
-
import { isRenderDynamicLatched } from "../shims/internal/headers-state.js";
|
|
12
|
-
import { peekDynamicUsage } from "../shims/headers.js";
|
|
9
|
+
import { isRenderDynamicLatched, markDynamicUsage } from "../shims/internal/headers-state.js";
|
|
10
|
+
import { peekDynamicUsage, runWithDetachedDynamicUsage } from "../shims/headers.js";
|
|
13
11
|
import { runWithFetchDedupe } from "../shims/fetch-cache.js";
|
|
12
|
+
import { setCacheStateHeaders } from "./cache-headers.js";
|
|
14
13
|
import { deferUntilStreamConsumed } from "./defer-until-stream-consumed.js";
|
|
14
|
+
import { createArtifactCompatibilityEnvelope, createArtifactCompatibilityGraphVersion } from "./artifact-compatibility.js";
|
|
15
|
+
import { AppElementsWire, isAppElementsRecord } from "./app-elements-wire.js";
|
|
16
|
+
import "./app-elements.js";
|
|
15
17
|
import { isBailoutToCSRError } from "../shims/navigation-errors.js";
|
|
16
18
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
19
|
+
import { applyPrerenderCacheLifeHeader, applyPrerenderCacheTagsHeader } from "./prerender-cache-life-header.js";
|
|
20
|
+
import { copyLinkHeaderProvenance, getFrameworkLinkHeader } from "./app-response-header-provenance.js";
|
|
21
|
+
import { applyClientStaleTimeHeader, applyEdgeRuntimeHeader, buildAppPageHtmlResponse, buildAppPageRscResponse, resolveAppPageHtmlResponsePolicy, resolveAppPageRscResponsePolicy, resolveUncacheableCacheControl } from "./app-page-response.js";
|
|
22
|
+
import { buildAppPageFontLinkHeader, readAppPageBinaryStream, resolveAppPageShellSpecialError, resolveAppPageSpecialError, resolveAppPageSpecialErrorStoredHeaders, teeAppPageRscStreamForCapture } from "./app-page-execution.js";
|
|
20
23
|
import { probeAppPageBeforeRender } from "./app-page-probe.js";
|
|
21
24
|
import { hasDigest } from "./app-rsc-errors.js";
|
|
22
25
|
import { recordAppPageRenderError, traceAppPageRender } from "./app-page-tracing.js";
|
|
23
26
|
import { traceResponseStartWithCompletion } from "./response-start-tracing.js";
|
|
24
27
|
import { DEFAULT_CACHE_VARIANT_BUDGET, buildCacheVariantWithRouteBudget, buildRenderObservation, buildRenderRequestApiObservations, createStaticLayoutArtifactReuseDecision } from "./cache-proof.js";
|
|
25
28
|
import { createAppPageHtmlOutputScope, createAppPageRenderObservation, createAppPageRscOutputScope } from "./app-page-render-observation.js";
|
|
29
|
+
import { buildAppPageLinkHeader, createAppPageFontData, createAppPageRscErrorTracker, createAppPageSsrErrorHandler, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery } from "./app-page-stream.js";
|
|
30
|
+
import { createAppPageRscRenderStatusResolver } from "./app-page-rsc-render-status.js";
|
|
26
31
|
import { finalizeAppPageCacheabilityEvaluationResponse, finalizeAppPageHtmlCacheResponse, finalizeAppPageRscCacheResponse } from "./app-page-cache-finalizer.js";
|
|
27
32
|
import { createStaticLayoutClientReuseArtifactCompatibility, createStaticLayoutClientReusePayloadHash, createStaticLayoutClientReuseRouteId } from "./static-layout-client-reuse-proof.js";
|
|
28
33
|
import { appendRscCompletionMetadata } from "./rsc-completion-metadata.js";
|
|
29
|
-
import { buildAppPageLinkHeader, createAppPageFontData, createAppPageRscErrorTracker, createAppPageSsrErrorHandler, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery } from "./app-page-stream.js";
|
|
30
34
|
import { getStaticLayoutObservationSkipRejection } from "./app-layout-param-observation.js";
|
|
31
35
|
import { createClientReuseSkipTransportPlan, crossCheckClientReuseManifestEntryWithCache } from "./skip-cache-proof.js";
|
|
32
36
|
//#region src/server/app-page-render.ts
|
|
@@ -70,15 +74,32 @@ function applyRequestCacheLife(options) {
|
|
|
70
74
|
* its response policy, such as error boundaries and special errors, get the
|
|
71
75
|
* same header as the normal render.
|
|
72
76
|
*/
|
|
73
|
-
function applyIneligibleRouteCachePolicy(response, options) {
|
|
77
|
+
function applyIneligibleRouteCachePolicy(response, options, probeCacheLife = null) {
|
|
74
78
|
const cacheControl = resolveEarlyResponseCacheControl(options);
|
|
75
|
-
|
|
79
|
+
const isRscRedirect = options.isRscRequest && response.headers.has("X-Vinext-Rsc-Redirect");
|
|
80
|
+
if (!cacheControl) {
|
|
81
|
+
const staleTimeSeconds = isRscRedirect ? resolveClientStaleTimeSeconds(probeCacheLife) : void 0;
|
|
82
|
+
if (staleTimeSeconds === void 0) return response;
|
|
83
|
+
const stamped = cloneForStamping(response);
|
|
84
|
+
applyClientStaleTimeHeader(stamped.headers, staleTimeSeconds);
|
|
85
|
+
return stamped;
|
|
86
|
+
}
|
|
87
|
+
const dynamicStaleTimeSeconds = isRscRedirect ? options.dynamicStaleTimeSeconds ?? resolveConfiguredDynamicStaleTimeSeconds() : void 0;
|
|
76
88
|
const middlewarePolicy = [...options.middlewareContext.headers ?? []].filter(([name, value]) => isCdnResponsePolicyHeader(name) && response.headers.get(name) === value);
|
|
77
|
-
|
|
89
|
+
const keepsMiddlewareCacheControl = middlewarePolicy.some(([name]) => name === "cache-control");
|
|
90
|
+
if (keepsMiddlewareCacheControl && dynamicStaleTimeSeconds === void 0) return response;
|
|
91
|
+
const stamped = cloneForStamping(response);
|
|
92
|
+
if (!keepsMiddlewareCacheControl) {
|
|
93
|
+
applyCdnResponseHeaders(stamped.headers, { cacheControl });
|
|
94
|
+
for (const [name, value] of middlewarePolicy) stamped.headers.set(name, value);
|
|
95
|
+
}
|
|
96
|
+
if (dynamicStaleTimeSeconds !== void 0) stamped.headers.set(VINEXT_DYNAMIC_STALE_TIME_HEADER, String(dynamicStaleTimeSeconds));
|
|
97
|
+
return stamped;
|
|
98
|
+
}
|
|
99
|
+
/** Some early responses have immutable headers, so stamp a copy. */
|
|
100
|
+
function cloneForStamping(response) {
|
|
78
101
|
const stamped = preserveFullyBufferedBodyMetadata(response, new Response(response.body, response));
|
|
79
102
|
copyLinkHeaderProvenance(response.headers, stamped.headers);
|
|
80
|
-
applyCdnResponseHeaders(stamped.headers, { cacheControl });
|
|
81
|
-
for (const [name, value] of middlewarePolicy) stamped.headers.set(name, value);
|
|
82
103
|
return stamped;
|
|
83
104
|
}
|
|
84
105
|
/** The known-dynamic branches of the RSC and HTML response policies, in their order. */
|
|
@@ -368,32 +389,26 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
|
|
|
368
389
|
}
|
|
369
390
|
return dynamicUsageObserved;
|
|
370
391
|
};
|
|
371
|
-
const
|
|
372
|
-
const probePageBeforeRender = options.isRscRequest || configuredProbePageBeforeRender && !(options.peekDynamicUsage?.() ?? false);
|
|
373
|
-
const preRenderResult = await probeAppPageBeforeRender({
|
|
374
|
-
hasLoadingBoundary: options.hasLoadingBoundary,
|
|
375
|
-
probePageBeforeRender,
|
|
392
|
+
const probeOutcome = await runWithDetachedDynamicUsage(() => probeAppPageBeforeRender({
|
|
376
393
|
skipProbes: options.pprFallbackShellSignal !== void 0,
|
|
377
394
|
layoutCount: options.layoutCount,
|
|
378
395
|
probeLayoutAt(layoutIndex) {
|
|
379
396
|
return options.probeLayoutAt(layoutIndex);
|
|
380
397
|
},
|
|
381
|
-
probePage() {
|
|
382
|
-
return options.probePage();
|
|
383
|
-
},
|
|
384
398
|
renderLayoutSpecialError(specialError, layoutIndex) {
|
|
385
399
|
return options.renderLayoutSpecialError(specialError, layoutIndex);
|
|
386
400
|
},
|
|
387
|
-
renderPageSpecialError(specialError) {
|
|
388
|
-
return options.renderPageSpecialError(specialError);
|
|
389
|
-
},
|
|
390
401
|
resolveSpecialError: resolveAppPageSpecialError,
|
|
391
402
|
runWithSuppressedHookWarning(probe) {
|
|
392
403
|
return options.runWithSuppressedHookWarning(probe);
|
|
393
404
|
},
|
|
394
405
|
classification: options.classification
|
|
395
|
-
});
|
|
396
|
-
|
|
406
|
+
}));
|
|
407
|
+
const preRenderResult = probeOutcome.result;
|
|
408
|
+
if (preRenderResult.response) {
|
|
409
|
+
if (probeOutcome.dynamicDetected) markDynamicUsage();
|
|
410
|
+
return applyIneligibleRouteCachePolicy(preRenderResult.response, options, probeOutcome.cacheLife);
|
|
411
|
+
}
|
|
397
412
|
const layoutFlags = preRenderResult.layoutFlags;
|
|
398
413
|
const artifactCompatibility = createAppPageArtifactCompatibility(options.element, options.routePattern);
|
|
399
414
|
const rootBoundaryId = artifactCompatibility?.rootBoundaryId ?? null;
|
|
@@ -458,7 +473,7 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
|
|
|
458
473
|
if (options.pprFallbackShellSignal) pprFallbackShellRsc = new Uint8Array(await readAppPageBinaryStream(rscStream));
|
|
459
474
|
let revalidateSeconds = options.revalidateSeconds;
|
|
460
475
|
let expireSeconds = options.expireSeconds;
|
|
461
|
-
const shouldWaitForAllReady = options.isPrerender === true && options.isSpeculativePrerender !== true;
|
|
476
|
+
const shouldWaitForAllReady = options.isPrerender === true && options.isSpeculativePrerender !== true || options.renderWholeDocument === true;
|
|
462
477
|
const shouldReadRequestCacheLifeForPrerender = options.isPrerender === true;
|
|
463
478
|
const mayResolveCacheLifeAfterHeaders = options.isProgressiveActionRender !== true && (revalidateSeconds === null || revalidateSeconds > 0) && !options.isDraftMode && !options.isForceDynamic && !shouldBypassRscCache;
|
|
464
479
|
const shouldCaptureRscForCacheMetadata = (options.isProduction || options.isPrerender === true) && mayResolveCacheLifeAfterHeaders && options.isStaticEligible;
|
|
@@ -474,6 +489,16 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
|
|
|
474
489
|
const capturedRscDataRef = { value: null };
|
|
475
490
|
if (rscCapture.sideStream && options.isRscRequest) capturedRscDataRef.value = readAppPageBinaryStream(rscCapture.sideStream);
|
|
476
491
|
if (options.isRscRequest) {
|
|
492
|
+
const resolveRscRenderStatus = options.isProduction && shouldCaptureRscForCacheMetadata && capturedRscDataRef.value !== null && options.isPrerender !== true && options.isRoutePPREnabled !== true ? createAppPageRscRenderStatusResolver({
|
|
493
|
+
basePath: options.basePath,
|
|
494
|
+
capturedRscData: capturedRscDataRef.value,
|
|
495
|
+
getCapturedSpecialError: rscErrorTracker.getCapturedSpecialError,
|
|
496
|
+
getCapturedSpecialErrors: rscErrorTracker.getCapturedSpecialErrors,
|
|
497
|
+
isForceStatic: options.isForceStatic,
|
|
498
|
+
loadSsrHandler: options.loadSsrHandler,
|
|
499
|
+
navigationContext: options.getNavigationContext(),
|
|
500
|
+
rootParams: options.rootParams
|
|
501
|
+
}) : void 0;
|
|
477
502
|
let requestCacheLifeForPrerender = null;
|
|
478
503
|
if (shouldWaitForAllReady) await settleCapturedRscRenderForCacheMetadata(capturedRscDataRef.value);
|
|
479
504
|
if (shouldReadRequestCacheLifeForPrerender) {
|
|
@@ -566,6 +591,7 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
|
|
|
566
591
|
mountedSlotsHeader: options.mountedSlotsHeader,
|
|
567
592
|
omitPendingDynamicCacheState: options.omitPendingDynamicCacheState,
|
|
568
593
|
renderMode: options.renderMode,
|
|
594
|
+
resolveRscRenderStatus,
|
|
569
595
|
preserveClientResponseHeaders: rscResponsePolicy.cacheState !== "MISS",
|
|
570
596
|
expireSeconds,
|
|
571
597
|
isStaticEligible: options.isStaticEligible,
|
|
@@ -591,6 +617,145 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
|
|
|
591
617
|
let requestCacheLifeForPrerender = null;
|
|
592
618
|
let dynamicUsedDuringHtmlRender = false;
|
|
593
619
|
let renderEnd;
|
|
620
|
+
let shellSpecialError = null;
|
|
621
|
+
const resolveHtmlCacheWrite = (dynamicUsedDuringRender) => {
|
|
622
|
+
const htmlResponsePolicy = resolveAppPageHtmlResponsePolicy({
|
|
623
|
+
dynamicUsedDuringRender,
|
|
624
|
+
isProgressiveActionRender: options.isProgressiveActionRender === true,
|
|
625
|
+
hasScriptNonce: Boolean(options.scriptNonce),
|
|
626
|
+
isDraftMode: options.isDraftMode,
|
|
627
|
+
isDynamicError: options.isDynamicError,
|
|
628
|
+
isForceDynamic: options.isForceDynamic,
|
|
629
|
+
isForceStatic: options.isForceStatic,
|
|
630
|
+
isProduction: options.isProduction,
|
|
631
|
+
isStaticEligible: options.isStaticEligible,
|
|
632
|
+
expireSeconds,
|
|
633
|
+
revalidateSeconds
|
|
634
|
+
});
|
|
635
|
+
const shouldSpeculativelyWriteCache = options.isProduction && shouldCaptureRscForCacheMetadata && !options.isEdgeRuntime && revalidateSeconds === null && !options.isDynamicError && !options.isForceStatic && !options.scriptNonce && options.isProgressiveActionRender !== true && !dynamicUsedDuringRender;
|
|
636
|
+
return {
|
|
637
|
+
htmlResponsePolicy,
|
|
638
|
+
shouldWriteHtmlCache: htmlResponsePolicy.shouldWriteToCache || shouldSpeculativelyWriteCache
|
|
639
|
+
};
|
|
640
|
+
};
|
|
641
|
+
const finalizeHtmlCacheWrite = (response, write) => finalizeAppPageHtmlCacheResponse(response, {
|
|
642
|
+
bypassInterceptionContextCache: options.bypassInterceptionContextCache,
|
|
643
|
+
capturedDynamicUsageBeforeContextCleanup: write.capturedDynamicUsageBeforeContextCleanup,
|
|
644
|
+
capturedRscDataPromise: capturedRscDataRef.value,
|
|
645
|
+
cleanPathname: options.cleanPathname,
|
|
646
|
+
clientTraceMetadataMarker,
|
|
647
|
+
consumeDynamicUsage: consumeRenderDynamicUsage,
|
|
648
|
+
consumeRenderObservationState,
|
|
649
|
+
createHtmlRenderObservation(input) {
|
|
650
|
+
return createAppPageRenderObservation({
|
|
651
|
+
boundaryOutcome: { kind: "success" },
|
|
652
|
+
cacheability: "public",
|
|
653
|
+
cacheTags: input.cacheTags,
|
|
654
|
+
cleanPathname: options.cleanPathname,
|
|
655
|
+
completeness: "complete",
|
|
656
|
+
output: htmlOutputScope,
|
|
657
|
+
params: options.navigationParams,
|
|
658
|
+
state: input.state
|
|
659
|
+
});
|
|
660
|
+
},
|
|
661
|
+
createRscRenderObservation(input) {
|
|
662
|
+
return createAppPageRenderObservation({
|
|
663
|
+
boundaryOutcome: { kind: "success" },
|
|
664
|
+
cacheability: "public",
|
|
665
|
+
cacheTags: input.cacheTags,
|
|
666
|
+
cleanPathname: options.cleanPathname,
|
|
667
|
+
completeness: "complete",
|
|
668
|
+
output: rscOutputScope,
|
|
669
|
+
params: options.navigationParams,
|
|
670
|
+
state: input.state
|
|
671
|
+
});
|
|
672
|
+
},
|
|
673
|
+
getPageTags() {
|
|
674
|
+
return options.getPageTags();
|
|
675
|
+
},
|
|
676
|
+
getRequestCacheLife() {
|
|
677
|
+
return readRequestCacheLifeForCachePolicy(options);
|
|
678
|
+
},
|
|
679
|
+
headers: write.headers,
|
|
680
|
+
isrDebug: options.isrDebug,
|
|
681
|
+
isrHtmlKey: options.isrHtmlKey,
|
|
682
|
+
isrRscKey: options.isrRscKey,
|
|
683
|
+
isrSet: options.isrSet,
|
|
684
|
+
interceptionContext: options.interceptionContext,
|
|
685
|
+
interceptionId: options.interceptionId,
|
|
686
|
+
omitPendingDynamicCacheState: options.omitPendingDynamicCacheState,
|
|
687
|
+
preserveClientResponseHeaders: !write.htmlResponsePolicy.shouldWriteToCache,
|
|
688
|
+
expireSeconds,
|
|
689
|
+
isStaticEligible: options.isStaticEligible,
|
|
690
|
+
revalidateSeconds: resolveAppPageCacheWriteRevalidateSeconds({
|
|
691
|
+
isDynamicError: options.isDynamicError,
|
|
692
|
+
isForceStatic: options.isForceStatic,
|
|
693
|
+
isStaticEligible: options.isStaticEligible,
|
|
694
|
+
revalidateSeconds
|
|
695
|
+
}),
|
|
696
|
+
linkHeader: write.linkHeader,
|
|
697
|
+
status: write.status,
|
|
698
|
+
waitUntil(cachePromise) {
|
|
699
|
+
options.waitUntil?.(cachePromise);
|
|
700
|
+
}
|
|
701
|
+
});
|
|
702
|
+
const mayStoreShellSpecialError = () => options.isProduction && shouldCaptureRscForCacheMetadata && options.isPrerender !== true && capturedRscDataRef.value !== null && resolveEarlyResponseCacheControl(options) === null;
|
|
703
|
+
const mayPrerenderShellSpecialError = () => options.isPrerender === true && options.isSpeculativePrerender !== true && options.pprFallbackShellSignal === void 0 && shouldCaptureRscForCacheMetadata && capturedRscDataRef.value !== null && resolveEarlyResponseCacheControl(options) === null;
|
|
704
|
+
const readPrerenderCacheMetadata = () => ({
|
|
705
|
+
cacheTags: options.getPageTags(),
|
|
706
|
+
requestCacheLife: readRequestCacheLifeForPrerender(options)
|
|
707
|
+
});
|
|
708
|
+
let prerenderedSpecialError = null;
|
|
709
|
+
const finalizePrerenderedShellSpecialErrorResponse = async (response, specialError, prerendered) => {
|
|
710
|
+
if (response.status !== specialError.statusCode) return applyIneligibleRouteCachePolicy(response, options);
|
|
711
|
+
const body = await response.arrayBuffer();
|
|
712
|
+
const { cacheTags, requestCacheLife } = prerendered.redirectMetadata ?? readPrerenderCacheMetadata();
|
|
713
|
+
({expireSeconds, revalidateSeconds} = applyRequestCacheLife({
|
|
714
|
+
expireSeconds,
|
|
715
|
+
requestCacheLife,
|
|
716
|
+
revalidateSeconds
|
|
717
|
+
}));
|
|
718
|
+
const { htmlResponsePolicy } = resolveHtmlCacheWrite(prerendered.dynamicUsed || consumeRenderDynamicUsage());
|
|
719
|
+
const headers = new Headers(response.headers);
|
|
720
|
+
if (htmlResponsePolicy.cacheControl && !headers.has("cache-control")) headers.set("Cache-Control", htmlResponsePolicy.cacheControl);
|
|
721
|
+
applyPrerenderCacheLifeHeader(headers, requestCacheLife);
|
|
722
|
+
applyPrerenderCacheTagsHeader(headers, cacheTags);
|
|
723
|
+
getRequestExecutionContext()?.recordPrerenderSpecialError?.({
|
|
724
|
+
headers: resolveAppPageSpecialErrorStoredHeaders(specialError, options.basePath) ?? {},
|
|
725
|
+
status: response.status
|
|
726
|
+
});
|
|
727
|
+
const prerenderResponse = new Response(body, {
|
|
728
|
+
headers,
|
|
729
|
+
status: response.status,
|
|
730
|
+
statusText: response.statusText
|
|
731
|
+
});
|
|
732
|
+
copyLinkHeaderProvenance(response.headers, prerenderResponse.headers);
|
|
733
|
+
return prerenderResponse;
|
|
734
|
+
};
|
|
735
|
+
const finalizeShellSpecialErrorResponse = (response, specialError) => {
|
|
736
|
+
if (response.status !== specialError.statusCode) return applyIneligibleRouteCachePolicy(response, options);
|
|
737
|
+
const dynamicUsedDuringRender = consumeRenderDynamicUsage();
|
|
738
|
+
const { htmlResponsePolicy, shouldWriteHtmlCache } = resolveHtmlCacheWrite(dynamicUsedDuringRender);
|
|
739
|
+
const headers = new Headers(response.headers);
|
|
740
|
+
if (htmlResponsePolicy.cacheControl && !headers.has("cache-control")) headers.set("Cache-Control", htmlResponsePolicy.cacheControl);
|
|
741
|
+
if (htmlResponsePolicy.cacheState) setCacheStateHeaders(headers, htmlResponsePolicy.cacheState);
|
|
742
|
+
const policyResponse = new Response(response.body, {
|
|
743
|
+
headers,
|
|
744
|
+
status: response.status,
|
|
745
|
+
statusText: response.statusText
|
|
746
|
+
});
|
|
747
|
+
copyLinkHeaderProvenance(response.headers, policyResponse.headers);
|
|
748
|
+
if (!shouldWriteHtmlCache) return policyResponse;
|
|
749
|
+
const clientResponse = finalizeHtmlCacheWrite(policyResponse, {
|
|
750
|
+
capturedDynamicUsageBeforeContextCleanup: () => dynamicUsedDuringRender,
|
|
751
|
+
headers: resolveAppPageSpecialErrorStoredHeaders(specialError, options.basePath),
|
|
752
|
+
htmlResponsePolicy,
|
|
753
|
+
linkHeader: getFrameworkLinkHeader(response.headers),
|
|
754
|
+
status: response.status
|
|
755
|
+
});
|
|
756
|
+
copyLinkHeaderProvenance(response.headers, clientResponse.headers);
|
|
757
|
+
return clientResponse;
|
|
758
|
+
};
|
|
594
759
|
const htmlRender = await renderAppPageHtmlStreamWithRecovery({
|
|
595
760
|
onShellRendered() {
|
|
596
761
|
if (!options.isProduction) renderEnd = performance.now();
|
|
@@ -657,30 +822,34 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
|
|
|
657
822
|
isStaticGeneration: options.isPrerender === true,
|
|
658
823
|
isForceStatic: options.isForceStatic,
|
|
659
824
|
isCacheCandidate: isCacheCandidateHtmlRender,
|
|
660
|
-
onSsrError: createAppPageSsrErrorHandler(onSsrError, rscErrorTracker.isCapturedError)
|
|
825
|
+
onSsrError: createAppPageSsrErrorHandler(onSsrError, rscErrorTracker.isCapturedError),
|
|
826
|
+
mirrorNextFlight: () => rscErrorTracker.getCapturedSpecialError() !== null
|
|
661
827
|
});
|
|
662
828
|
},
|
|
663
|
-
renderSpecialErrorResponse(specialError) {
|
|
664
|
-
|
|
829
|
+
async renderSpecialErrorResponse(specialError) {
|
|
830
|
+
shellSpecialError = specialError;
|
|
831
|
+
const mayPrerender = mayPrerenderShellSpecialError();
|
|
832
|
+
if (mayStoreShellSpecialError() || mayPrerender) await settleCapturedRscRenderForCacheMetadata(capturedRscDataRef.value, peekRenderDynamicUsage);
|
|
833
|
+
if (mayPrerender) prerenderedSpecialError = {
|
|
834
|
+
dynamicUsed: consumeRenderDynamicUsage(),
|
|
835
|
+
redirectMetadata: specialError.kind === "redirect" ? readPrerenderCacheMetadata() : null
|
|
836
|
+
};
|
|
837
|
+
return options.renderPageSpecialError(specialError, { isCacheCandidate: isCacheCandidateHtmlRender });
|
|
665
838
|
},
|
|
666
|
-
resolveSpecialError
|
|
839
|
+
resolveSpecialError(error) {
|
|
840
|
+
return resolveAppPageShellSpecialError(error, rscErrorTracker.getCapturedSpecialErrors(error));
|
|
841
|
+
}
|
|
667
842
|
});
|
|
668
843
|
options.onRenderComplete?.(htmlRender.renderComplete);
|
|
669
|
-
if (htmlRender.response)
|
|
844
|
+
if (htmlRender.response) {
|
|
845
|
+
if (shellSpecialError && options.isProduction && options.isPrerender !== true && resolveEarlyResponseCacheControl(options) === null) return finalizeShellSpecialErrorResponse(htmlRender.response, shellSpecialError);
|
|
846
|
+
if (shellSpecialError && prerenderedSpecialError) return finalizePrerenderedShellSpecialErrorResponse(htmlRender.response, shellSpecialError, prerenderedSpecialError);
|
|
847
|
+
return applyIneligibleRouteCachePolicy(htmlRender.response, options);
|
|
848
|
+
}
|
|
670
849
|
let htmlStream = htmlRender.htmlStream;
|
|
671
850
|
if (!htmlStream) throw new Error("[vinext] Expected an HTML stream when no fallback response was returned");
|
|
672
851
|
const linkHeader = buildAppPageLinkHeader(htmlRender.linkHeader, fontLinkHeader, options.reactMaxHeadersLength);
|
|
673
852
|
if (options.isPrerender === true) await htmlRender.metadataReady;
|
|
674
|
-
if (options.hasLoadingBoundary || !probePageBeforeRender) {
|
|
675
|
-
const captured = rscErrorTracker.getCapturedSpecialError();
|
|
676
|
-
if (captured) {
|
|
677
|
-
const specialError = resolveAppPageSpecialError(captured);
|
|
678
|
-
if (specialError) {
|
|
679
|
-
htmlStream.cancel().catch(() => {});
|
|
680
|
-
return applyIneligibleRouteCachePolicy(await options.renderPageSpecialError(specialError), options);
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
853
|
let dynamicUsedDuringRender = consumeRenderDynamicUsage();
|
|
685
854
|
dynamicUsedDuringHtmlRender = dynamicUsedDuringRender;
|
|
686
855
|
const stopSpeculativeMetadataWaitOnDynamicUsage = options.isSpeculativePrerender === true && shouldReadRequestCacheLifeForPrerender ? () => {
|
|
@@ -710,19 +879,7 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
|
|
|
710
879
|
dynamicUsedDuringHtmlRender = dynamicUsedBeforeContextCleanup;
|
|
711
880
|
options.clearRequestContext();
|
|
712
881
|
});
|
|
713
|
-
const htmlResponsePolicy =
|
|
714
|
-
dynamicUsedDuringRender,
|
|
715
|
-
isProgressiveActionRender: options.isProgressiveActionRender === true,
|
|
716
|
-
hasScriptNonce: Boolean(options.scriptNonce),
|
|
717
|
-
isDraftMode: options.isDraftMode,
|
|
718
|
-
isDynamicError: options.isDynamicError,
|
|
719
|
-
isForceDynamic: options.isForceDynamic,
|
|
720
|
-
isForceStatic: options.isForceStatic,
|
|
721
|
-
isProduction: options.isProduction,
|
|
722
|
-
isStaticEligible: options.isStaticEligible,
|
|
723
|
-
expireSeconds,
|
|
724
|
-
revalidateSeconds
|
|
725
|
-
});
|
|
882
|
+
const { htmlResponsePolicy, shouldWriteHtmlCache } = resolveHtmlCacheWrite(dynamicUsedDuringRender);
|
|
726
883
|
const htmlResponseTiming = buildResponseTiming({
|
|
727
884
|
compileEnd,
|
|
728
885
|
handlerStart: options.handlerStart,
|
|
@@ -747,8 +904,7 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
|
|
|
747
904
|
applyCdnResponseHeaders(response.headers, { cacheControl: NEVER_CACHE_CONTROL });
|
|
748
905
|
return response;
|
|
749
906
|
}
|
|
750
|
-
|
|
751
|
-
if (htmlResponsePolicy.shouldWriteToCache || shouldSpeculativelyWriteCache) {
|
|
907
|
+
if (shouldWriteHtmlCache) {
|
|
752
908
|
const isrResponse = buildAppPageHtmlResponse(safeHtmlStream, {
|
|
753
909
|
cacheTags: options.isPrerender === true ? options.getPageTags() : void 0,
|
|
754
910
|
draftCookie,
|
|
@@ -760,66 +916,10 @@ async function renderAppPageLifecycleImpl(options, renderSpan) {
|
|
|
760
916
|
timing: htmlResponseTiming
|
|
761
917
|
});
|
|
762
918
|
if (options.isPrerender === true) return isrResponse;
|
|
763
|
-
return
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
},
|
|
768
|
-
capturedRscDataPromise: capturedRscDataRef.value,
|
|
769
|
-
cleanPathname: options.cleanPathname,
|
|
770
|
-
clientTraceMetadataMarker,
|
|
771
|
-
consumeDynamicUsage: consumeRenderDynamicUsage,
|
|
772
|
-
consumeRenderObservationState,
|
|
773
|
-
createHtmlRenderObservation(input) {
|
|
774
|
-
return createAppPageRenderObservation({
|
|
775
|
-
boundaryOutcome: { kind: "success" },
|
|
776
|
-
cacheability: "public",
|
|
777
|
-
cacheTags: input.cacheTags,
|
|
778
|
-
cleanPathname: options.cleanPathname,
|
|
779
|
-
completeness: "complete",
|
|
780
|
-
output: htmlOutputScope,
|
|
781
|
-
params: options.navigationParams,
|
|
782
|
-
state: input.state
|
|
783
|
-
});
|
|
784
|
-
},
|
|
785
|
-
createRscRenderObservation(input) {
|
|
786
|
-
return createAppPageRenderObservation({
|
|
787
|
-
boundaryOutcome: { kind: "success" },
|
|
788
|
-
cacheability: "public",
|
|
789
|
-
cacheTags: input.cacheTags,
|
|
790
|
-
cleanPathname: options.cleanPathname,
|
|
791
|
-
completeness: "complete",
|
|
792
|
-
output: rscOutputScope,
|
|
793
|
-
params: options.navigationParams,
|
|
794
|
-
state: input.state
|
|
795
|
-
});
|
|
796
|
-
},
|
|
797
|
-
getPageTags() {
|
|
798
|
-
return options.getPageTags();
|
|
799
|
-
},
|
|
800
|
-
getRequestCacheLife() {
|
|
801
|
-
return readRequestCacheLifeForCachePolicy(options);
|
|
802
|
-
},
|
|
803
|
-
isrDebug: options.isrDebug,
|
|
804
|
-
isrHtmlKey: options.isrHtmlKey,
|
|
805
|
-
isrRscKey: options.isrRscKey,
|
|
806
|
-
isrSet: options.isrSet,
|
|
807
|
-
interceptionContext: options.interceptionContext,
|
|
808
|
-
interceptionId: options.interceptionId,
|
|
809
|
-
omitPendingDynamicCacheState: options.omitPendingDynamicCacheState,
|
|
810
|
-
preserveClientResponseHeaders: !htmlResponsePolicy.shouldWriteToCache,
|
|
811
|
-
expireSeconds,
|
|
812
|
-
isStaticEligible: options.isStaticEligible,
|
|
813
|
-
revalidateSeconds: resolveAppPageCacheWriteRevalidateSeconds({
|
|
814
|
-
isDynamicError: options.isDynamicError,
|
|
815
|
-
isForceStatic: options.isForceStatic,
|
|
816
|
-
isStaticEligible: options.isStaticEligible,
|
|
817
|
-
revalidateSeconds
|
|
818
|
-
}),
|
|
819
|
-
linkHeader: linkHeader ?? null,
|
|
820
|
-
waitUntil(cachePromise) {
|
|
821
|
-
options.waitUntil?.(cachePromise);
|
|
822
|
-
}
|
|
919
|
+
return finalizeHtmlCacheWrite(isrResponse, {
|
|
920
|
+
capturedDynamicUsageBeforeContextCleanup: () => dynamicUsedBeforeContextCleanup,
|
|
921
|
+
htmlResponsePolicy,
|
|
922
|
+
linkHeader: linkHeader ?? null
|
|
823
923
|
});
|
|
824
924
|
}
|
|
825
925
|
const response = buildAppPageHtmlResponse(safeHtmlStream, {
|
|
@@ -49,7 +49,6 @@ type ResolveAppPageGenerateStaticParamsSourcesOptions = {
|
|
|
49
49
|
};
|
|
50
50
|
type BuildAppPageElementOptions<TElement> = {
|
|
51
51
|
buildPageElement: () => Promise<TElement>;
|
|
52
|
-
probePageSpecialError?: () => Promise<AppPageSpecialError | null>;
|
|
53
52
|
renderErrorBoundaryPage: (error: unknown) => Promise<Response | null>;
|
|
54
53
|
renderSpecialError: (specialError: AppPageSpecialError) => Promise<Response>;
|
|
55
54
|
resolveSpecialError: (error: unknown) => AppPageSpecialError | null;
|
|
@@ -333,8 +333,7 @@ async function buildAppPageElement(options) {
|
|
|
333
333
|
response: null
|
|
334
334
|
};
|
|
335
335
|
} catch (error) {
|
|
336
|
-
const
|
|
337
|
-
const specialError = (buildSpecialError ? await options.probePageSpecialError?.() : null) ?? buildSpecialError;
|
|
336
|
+
const specialError = options.resolveSpecialError(error);
|
|
338
337
|
if (specialError) return {
|
|
339
338
|
element: null,
|
|
340
339
|
response: await options.renderSpecialError(specialError)
|
|
@@ -71,9 +71,10 @@ type BuildAppPageHtmlResponseOptions = {
|
|
|
71
71
|
timing?: AppPageResponseTiming;
|
|
72
72
|
};
|
|
73
73
|
/**
|
|
74
|
-
* Only ever set from a *completed* render's cacheLife (cache replay
|
|
75
|
-
* prerender seed) — `use cache` scopes
|
|
76
|
-
* so a streaming response can never
|
|
74
|
+
* Only ever set from a *completed* render's cacheLife (cache replay,
|
|
75
|
+
* prerender seed, or a layout probe's early redirect) — `use cache` scopes
|
|
76
|
+
* keep resolving after headers commit, so a streaming response can never
|
|
77
|
+
* carry it.
|
|
77
78
|
*/
|
|
78
79
|
export declare function applyClientStaleTimeHeader(headers: Headers, staleTimeSeconds: number | undefined): void;
|
|
79
80
|
/**
|
|
@@ -18,9 +18,10 @@ function applyDynamicStaleTimeHeader(headers, dynamicStaleTimeSeconds) {
|
|
|
18
18
|
if (dynamicStaleTimeSeconds !== void 0 && Number.isInteger(dynamicStaleTimeSeconds) && dynamicStaleTimeSeconds >= 0) headers.set(VINEXT_DYNAMIC_STALE_TIME_HEADER, String(dynamicStaleTimeSeconds));
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
* Only ever set from a *completed* render's cacheLife (cache replay
|
|
22
|
-
* prerender seed) — `use cache` scopes
|
|
23
|
-
* so a streaming response can never
|
|
21
|
+
* Only ever set from a *completed* render's cacheLife (cache replay,
|
|
22
|
+
* prerender seed, or a layout probe's early redirect) — `use cache` scopes
|
|
23
|
+
* keep resolving after headers commit, so a streaming response can never
|
|
24
|
+
* carry it.
|
|
24
25
|
*/
|
|
25
26
|
function applyClientStaleTimeHeader(headers, staleTimeSeconds) {
|
|
26
27
|
if (staleTimeSeconds === void 0) return;
|
|
@@ -140,14 +140,15 @@ type BuildAppPageRouteElementOptions<TModule extends AppPageModule = AppPageModu
|
|
|
140
140
|
makeThenableParams: MakeThenableParams;
|
|
141
141
|
matchedParams: AppPageParams;
|
|
142
142
|
metadataPlacement?: "body" | "head";
|
|
143
|
-
|
|
143
|
+
/**
|
|
144
|
+
* Starts resolving the page's head. The head, its streamed body tags and its
|
|
145
|
+
* error outlet each call this while Flight renders them, so callers memoise
|
|
146
|
+
* it per render with React's `cache()`. Without it the head has no metadata.
|
|
147
|
+
*/
|
|
148
|
+
resolveHead?: (() => AppPageRouteHead) | null;
|
|
144
149
|
resolvedMetadataPathname?: string;
|
|
145
|
-
resolvedViewport: Viewport;
|
|
146
150
|
scriptNonce?: string;
|
|
147
|
-
streamingMetadata?: Promise<Metadata | null> | null;
|
|
148
|
-
streamingMetadataOutlet?: Promise<unknown> | null;
|
|
149
151
|
streamingMetadataOutletSuspended?: boolean;
|
|
150
|
-
streamingMetadataTags?: Promise<Metadata | null> | null;
|
|
151
152
|
trailingSlash?: boolean;
|
|
152
153
|
rootForbiddenModule?: TModule | null;
|
|
153
154
|
rootNotFoundModule?: TModule | null;
|
|
@@ -158,6 +159,17 @@ type BuildAppPageRouteElementOptions<TModule extends AppPageModule = AppPageModu
|
|
|
158
159
|
searchParams?: unknown;
|
|
159
160
|
slotOverrides?: Readonly<Record<string, AppPageSlotOverride<TModule>>> | null;
|
|
160
161
|
};
|
|
162
|
+
/**
|
|
163
|
+
* A page's head as Flight renders it. `metadata` and `viewport` hold the tags
|
|
164
|
+
* to render, including the HTTP access fallback's when resolution failed, so
|
|
165
|
+
* they never reject. `outlet` rejects with the resolution error so the route's
|
|
166
|
+
* boundaries can handle it.
|
|
167
|
+
*/
|
|
168
|
+
export type AppPageRouteHead = {
|
|
169
|
+
metadata: Promise<Metadata | null>;
|
|
170
|
+
outlet: Promise<null>;
|
|
171
|
+
viewport: Promise<Viewport>;
|
|
172
|
+
};
|
|
161
173
|
type MakeThenableParams = (params: AppPageParams, observer?: ThenableParamsObserver) => unknown;
|
|
162
174
|
type BuildAppPageElementsOptions<TModule extends AppPageModule = AppPageModule, TErrorModule extends AppPageErrorModule = AppPageErrorModule> = BuildAppPageRouteElementOptions<TModule, TErrorModule> & {
|
|
163
175
|
interception?: AppElementsInterception | null;
|