vinext 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build/client-build-config.d.ts +11 -2
- package/dist/build/client-build-config.js +17 -6
- package/dist/build/prerender.d.ts +9 -1
- package/dist/build/prerender.js +42 -12
- package/dist/build/run-prerender.d.ts +10 -2
- package/dist/build/run-prerender.js +15 -1
- package/dist/client/app-nav-failure-handler.d.ts +8 -0
- package/dist/client/app-nav-failure-handler.js +44 -0
- package/dist/client/pages-router-link-navigation.d.ts +33 -7
- package/dist/client/pages-router-link-navigation.js +32 -2
- package/dist/client/vinext-next-data.d.ts +18 -1
- package/dist/client/vinext-next-data.js +2 -0
- package/dist/client/window-next.d.ts +2 -1
- package/dist/client/window-next.js +12 -1
- package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
- package/dist/config/config-matchers.d.ts +11 -1
- package/dist/config/config-matchers.js +87 -16
- package/dist/config/next-config.d.ts +46 -4
- package/dist/config/next-config.js +147 -48
- package/dist/config/tsconfig-paths.js +14 -1
- package/dist/deploy.d.ts +30 -11
- package/dist/deploy.js +200 -112
- package/dist/entries/app-browser-entry.d.ts +9 -3
- package/dist/entries/app-browser-entry.js +21 -3
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +65 -5
- package/dist/entries/app-rsc-manifest.js +2 -0
- package/dist/entries/app-ssr-entry.js +1 -1
- package/dist/entries/pages-client-entry.js +66 -20
- package/dist/entries/pages-server-entry.js +47 -31
- package/dist/index.js +417 -102
- package/dist/plugins/dynamic-preload-metadata.js +2 -4
- package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
- package/dist/plugins/extensionless-dynamic-import.js +152 -0
- package/dist/plugins/fonts.js +5 -4
- package/dist/plugins/optimize-imports.d.ts +2 -1
- package/dist/plugins/optimize-imports.js +11 -9
- package/dist/plugins/postcss.js +7 -7
- package/dist/plugins/strip-server-exports.d.ts +9 -7
- package/dist/plugins/strip-server-exports.js +493 -46
- package/dist/plugins/typeof-window.d.ts +14 -0
- package/dist/plugins/typeof-window.js +150 -0
- package/dist/routing/app-route-graph.d.ts +2 -1
- package/dist/routing/app-route-graph.js +46 -16
- package/dist/routing/file-matcher.d.ts +10 -1
- package/dist/routing/file-matcher.js +22 -1
- package/dist/routing/pages-router.js +3 -3
- package/dist/routing/utils.d.ts +35 -6
- package/dist/routing/utils.js +59 -7
- package/dist/server/api-handler.d.ts +6 -1
- package/dist/server/api-handler.js +21 -15
- package/dist/server/app-browser-action-result.d.ts +19 -6
- package/dist/server/app-browser-action-result.js +20 -11
- package/dist/server/app-browser-entry.js +175 -91
- package/dist/server/app-browser-error.d.ts +10 -6
- package/dist/server/app-browser-error.js +43 -8
- package/dist/server/app-browser-hydration.d.ts +2 -0
- package/dist/server/app-browser-hydration.js +1 -0
- package/dist/server/app-browser-navigation-controller.d.ts +5 -3
- package/dist/server/app-browser-navigation-controller.js +23 -2
- package/dist/server/app-browser-server-action-navigation.d.ts +6 -0
- package/dist/server/app-browser-server-action-navigation.js +9 -0
- package/dist/server/app-browser-state.d.ts +1 -1
- package/dist/server/app-browser-state.js +19 -11
- package/dist/server/app-browser-stream.js +86 -43
- package/dist/server/app-browser-visible-commit.d.ts +1 -1
- package/dist/server/app-elements-wire.d.ts +6 -1
- package/dist/server/app-elements-wire.js +14 -4
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-fallback-renderer.d.ts +1 -0
- package/dist/server/app-fallback-renderer.js +3 -1
- package/dist/server/app-optimistic-routing.js +2 -2
- package/dist/server/app-page-boundary-render.d.ts +1 -0
- package/dist/server/app-page-boundary-render.js +27 -14
- package/dist/server/app-page-cache-render.d.ts +53 -0
- package/dist/server/app-page-cache-render.js +91 -0
- package/dist/server/app-page-cache.d.ts +16 -2
- package/dist/server/app-page-cache.js +62 -1
- package/dist/server/app-page-dispatch.d.ts +26 -0
- package/dist/server/app-page-dispatch.js +149 -92
- package/dist/server/app-page-element-builder.d.ts +1 -0
- package/dist/server/app-page-element-builder.js +5 -2
- package/dist/server/app-page-execution.d.ts +6 -1
- package/dist/server/app-page-execution.js +21 -1
- package/dist/server/app-page-probe.d.ts +1 -0
- package/dist/server/app-page-probe.js +4 -0
- package/dist/server/app-page-render-observation.d.ts +3 -1
- package/dist/server/app-page-render-observation.js +17 -1
- package/dist/server/app-page-render.d.ts +12 -1
- package/dist/server/app-page-render.js +42 -4
- package/dist/server/app-page-request.d.ts +2 -0
- package/dist/server/app-page-request.js +2 -1
- package/dist/server/app-page-route-wiring.d.ts +3 -1
- package/dist/server/app-page-route-wiring.js +14 -5
- package/dist/server/app-page-stream.d.ts +15 -3
- package/dist/server/app-page-stream.js +11 -5
- package/dist/server/app-pages-bridge.d.ts +23 -1
- package/dist/server/app-pages-bridge.js +26 -17
- package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
- package/dist/server/app-ppr-fallback-shell-render.js +26 -0
- package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
- package/dist/server/app-ppr-fallback-shell.js +8 -1
- package/dist/server/app-route-handler-dispatch.js +9 -2
- package/dist/server/app-route-handler-policy.d.ts +1 -0
- package/dist/server/app-router-entry.js +5 -0
- package/dist/server/app-rsc-cache-busting.js +2 -0
- package/dist/server/app-rsc-handler.d.ts +28 -0
- package/dist/server/app-rsc-handler.js +195 -59
- package/dist/server/app-rsc-route-matching.d.ts +3 -0
- package/dist/server/app-rsc-route-matching.js +8 -2
- package/dist/server/app-segment-config.d.ts +9 -1
- package/dist/server/app-segment-config.js +12 -3
- package/dist/server/app-server-action-execution.d.ts +1 -0
- package/dist/server/app-server-action-execution.js +47 -15
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +84 -39
- package/dist/server/before-interactive-head.d.ts +17 -0
- package/dist/server/before-interactive-head.js +35 -0
- package/dist/server/cache-control.js +4 -0
- package/dist/server/csp.js +1 -4
- package/dist/server/dev-server.d.ts +2 -2
- package/dist/server/dev-server.js +321 -83
- package/dist/server/hybrid-route-priority.d.ts +22 -0
- package/dist/server/hybrid-route-priority.js +33 -0
- package/dist/server/image-optimization.d.ts +18 -9
- package/dist/server/image-optimization.js +37 -23
- package/dist/server/implicit-tags.d.ts +2 -1
- package/dist/server/implicit-tags.js +4 -1
- package/dist/server/middleware-matcher.js +12 -3
- package/dist/server/middleware-runtime.d.ts +3 -4
- package/dist/server/middleware-runtime.js +2 -0
- package/dist/server/navigation-planner.d.ts +135 -41
- package/dist/server/navigation-planner.js +138 -0
- package/dist/server/navigation-trace.d.ts +9 -1
- package/dist/server/navigation-trace.js +9 -1
- package/dist/server/operation-token.d.ts +40 -0
- package/dist/server/operation-token.js +85 -0
- package/dist/server/pages-api-route.d.ts +6 -0
- package/dist/server/pages-api-route.js +13 -2
- package/dist/server/pages-asset-tags.d.ts +2 -1
- package/dist/server/pages-asset-tags.js +6 -2
- package/dist/server/pages-data-route.d.ts +9 -2
- package/dist/server/pages-data-route.js +18 -6
- package/dist/server/pages-dev-module-url.d.ts +4 -0
- package/dist/server/pages-dev-module-url.js +15 -0
- package/dist/server/pages-document-initial-props.d.ts +4 -15
- package/dist/server/pages-document-initial-props.js +27 -56
- package/dist/server/pages-get-initial-props.d.ts +54 -4
- package/dist/server/pages-get-initial-props.js +43 -1
- package/dist/server/pages-i18n.js +2 -2
- package/dist/server/pages-node-compat.js +2 -2
- package/dist/server/pages-page-data.d.ts +11 -2
- package/dist/server/pages-page-data.js +207 -34
- package/dist/server/pages-page-handler.d.ts +4 -2
- package/dist/server/pages-page-handler.js +62 -23
- package/dist/server/pages-page-response.d.ts +4 -1
- package/dist/server/pages-page-response.js +11 -8
- package/dist/server/pages-readiness.js +1 -1
- package/dist/server/pages-request-pipeline.d.ts +8 -7
- package/dist/server/pages-request-pipeline.js +126 -47
- package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
- package/dist/server/pregenerated-concrete-paths.js +2 -19
- package/dist/server/prerender-manifest.d.ts +33 -0
- package/dist/server/prerender-manifest.js +54 -0
- package/dist/server/prerender-route-params.d.ts +1 -2
- package/dist/server/prod-server.d.ts +3 -1
- package/dist/server/prod-server.js +50 -13
- package/dist/server/request-pipeline.d.ts +3 -15
- package/dist/server/request-pipeline.js +58 -47
- package/dist/server/rsc-stream-hints.d.ts +5 -1
- package/dist/server/rsc-stream-hints.js +6 -1
- package/dist/server/seed-cache.js +10 -18
- package/dist/server/static-file-cache.js +16 -4
- package/dist/shims/app-router-scroll-state.d.ts +3 -1
- package/dist/shims/app-router-scroll-state.js +14 -2
- package/dist/shims/app-router-scroll.d.ts +3 -0
- package/dist/shims/app-router-scroll.js +28 -18
- package/dist/shims/before-interactive-context.d.ts +14 -3
- package/dist/shims/cache-runtime.js +3 -2
- package/dist/shims/cache.d.ts +1 -0
- package/dist/shims/cache.js +1 -1
- package/dist/shims/cdn-cache.d.ts +5 -5
- package/dist/shims/document.d.ts +15 -20
- package/dist/shims/document.js +5 -8
- package/dist/shims/dynamic-preload-chunks.js +6 -4
- package/dist/shims/error-boundary.d.ts +2 -0
- package/dist/shims/error-boundary.js +7 -0
- package/dist/shims/error.js +3 -2
- package/dist/shims/error.react-server.d.ts +9 -0
- package/dist/shims/error.react-server.js +6 -0
- package/dist/shims/fetch-cache.d.ts +3 -1
- package/dist/shims/fetch-cache.js +45 -20
- package/dist/shims/hash-scroll.js +6 -1
- package/dist/shims/headers.js +29 -4
- package/dist/shims/image.js +9 -2
- package/dist/shims/internal/als-registry.js +28 -1
- package/dist/shims/internal/app-route-detection.js +8 -17
- package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
- package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
- package/dist/shims/internal/navigation-untracked.d.ts +35 -0
- package/dist/shims/internal/navigation-untracked.js +55 -0
- package/dist/shims/internal/pages-data-fetch-dedup.d.ts +6 -7
- package/dist/shims/internal/pages-data-fetch-dedup.js +67 -14
- package/dist/shims/internal/pages-data-target.d.ts +7 -2
- package/dist/shims/internal/pages-data-target.js +17 -8
- package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
- package/dist/shims/internal/pages-router-accessor.js +13 -0
- package/dist/shims/internal/router-context.d.ts +2 -1
- package/dist/shims/internal/router-context.js +3 -1
- package/dist/shims/link.js +47 -19
- package/dist/shims/metadata.js +4 -4
- package/dist/shims/navigation.d.ts +8 -2
- package/dist/shims/navigation.js +63 -31
- package/dist/shims/ppr-fallback-shell.d.ts +5 -1
- package/dist/shims/ppr-fallback-shell.js +28 -7
- package/dist/shims/router.d.ts +18 -3
- package/dist/shims/router.js +512 -142
- package/dist/shims/script.js +8 -4
- package/dist/shims/server.d.ts +16 -1
- package/dist/shims/server.js +44 -12
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/utils/built-asset-url.d.ts +4 -0
- package/dist/utils/built-asset-url.js +11 -0
- package/dist/utils/commonjs-loader.d.ts +16 -0
- package/dist/utils/commonjs-loader.js +100 -0
- package/dist/utils/deployment-id.d.ts +8 -0
- package/dist/utils/deployment-id.js +22 -0
- package/dist/utils/has-trailing-comma.d.ts +24 -0
- package/dist/utils/has-trailing-comma.js +62 -0
- package/dist/utils/html-limited-bots.d.ts +18 -1
- package/dist/utils/html-limited-bots.js +23 -1
- package/dist/utils/parse-cookie.d.ts +13 -0
- package/dist/utils/parse-cookie.js +52 -0
- package/dist/utils/path.d.ts +7 -1
- package/dist/utils/path.js +9 -1
- package/dist/utils/text-stream.d.ts +1 -1
- package/dist/utils/text-stream.js +2 -2
- package/dist/utils/vite-version.d.ts +12 -1
- package/dist/utils/vite-version.js +9 -1
- package/package.json +2 -2
- package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
- package/dist/shims/internal/parse-cookie-header.js +0 -30
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NO_STORE_CACHE_CONTROL } from "./cache-control.js";
|
|
1
|
+
import { NEVER_CACHE_CONTROL, NO_STORE_CACHE_CONTROL, applyCdnResponseHeaders } from "./cache-control.js";
|
|
2
2
|
import { createArtifactCompatibilityEnvelope, createArtifactCompatibilityGraphVersion } from "./artifact-compatibility.js";
|
|
3
3
|
import { AppElementsWire, isAppElementsRecord } from "./app-elements-wire.js";
|
|
4
4
|
import "./app-elements.js";
|
|
@@ -249,6 +249,7 @@ function wrapRscResponseForDevErrorReporting(response, consumeInvalidDynamicUsag
|
|
|
249
249
|
async function renderAppPageLifecycle(options) {
|
|
250
250
|
const preRenderResult = await probeAppPageBeforeRender({
|
|
251
251
|
hasLoadingBoundary: options.hasLoadingBoundary,
|
|
252
|
+
skipProbes: options.pprFallbackShellSignal !== void 0,
|
|
252
253
|
layoutCount: options.layoutCount,
|
|
253
254
|
probeLayoutAt(layoutIndex) {
|
|
254
255
|
return options.probeLayoutAt(layoutIndex);
|
|
@@ -315,11 +316,31 @@ async function renderAppPageLifecycle(options) {
|
|
|
315
316
|
});
|
|
316
317
|
const compileEnd = options.isProduction ? void 0 : performance.now();
|
|
317
318
|
const rscErrorTracker = createAppPageRscErrorTracker(options.createRscOnErrorHandler(options.cleanPathname, options.routePattern));
|
|
318
|
-
|
|
319
|
+
let rscStream = await runWithFetchDedupe(async () => {
|
|
320
|
+
if (options.pprFallbackShellSignal && options.prerenderToReadableStream) {
|
|
321
|
+
const reactSignal = options.pprFallbackShellReactSignal ?? options.pprFallbackShellSignal;
|
|
322
|
+
const pendingResult = options.prerenderToReadableStream(outgoingElement, {
|
|
323
|
+
onError: rscErrorTracker.onRenderError,
|
|
324
|
+
signal: reactSignal
|
|
325
|
+
});
|
|
326
|
+
if (options.abortPprFallbackShell) setTimeout(options.abortPprFallbackShell, 0);
|
|
327
|
+
return (await pendingResult).prelude;
|
|
328
|
+
}
|
|
329
|
+
return options.renderToReadableStream(outgoingElement, { onError: rscErrorTracker.onRenderError });
|
|
330
|
+
});
|
|
331
|
+
let pprFallbackShellRsc = null;
|
|
332
|
+
if (options.pprFallbackShellSignal) pprFallbackShellRsc = new Uint8Array(await readAppPageBinaryStream(rscStream));
|
|
319
333
|
let revalidateSeconds = options.revalidateSeconds;
|
|
320
334
|
let expireSeconds = options.expireSeconds;
|
|
321
335
|
const shouldCaptureRscForCacheMetadata = options.isProgressiveActionRender !== true && (options.isProduction || options.isPrerender === true) && (revalidateSeconds === null || revalidateSeconds > 0 && revalidateSeconds !== Infinity) && !options.isDraftMode && !options.isForceDynamic && !shouldBypassRscCacheForSkipTransport;
|
|
322
|
-
const
|
|
336
|
+
const createBufferedRscStream = (close) => new ReadableStream({ start(controller) {
|
|
337
|
+
if (pprFallbackShellRsc) controller.enqueue(pprFallbackShellRsc);
|
|
338
|
+
if (close) controller.close();
|
|
339
|
+
} });
|
|
340
|
+
const rscCapture = pprFallbackShellRsc ? {
|
|
341
|
+
ssrStream: createBufferedRscStream(false),
|
|
342
|
+
...shouldCaptureRscForCacheMetadata ? { sideStream: createBufferedRscStream(true) } : {}
|
|
343
|
+
} : teeAppPageRscStreamForCapture(rscStream, shouldCaptureRscForCacheMetadata);
|
|
323
344
|
const rscForResponse = rscCapture.ssrStream;
|
|
324
345
|
const capturedRscDataRef = { value: null };
|
|
325
346
|
if (rscCapture.sideStream && options.isRscRequest) capturedRscDataRef.value = readAppPageBinaryStream(rscCapture.sideStream);
|
|
@@ -415,17 +436,19 @@ async function renderAppPageLifecycle(options) {
|
|
|
415
436
|
return renderAppPageHtmlStream({
|
|
416
437
|
capturedRscDataRef,
|
|
417
438
|
fontData,
|
|
439
|
+
hasCustomGlobalError: options.hasCustomGlobalError,
|
|
418
440
|
navigationContext: options.getNavigationContext(),
|
|
419
441
|
basePath: options.basePath,
|
|
420
442
|
clientTraceMetadata: options.clientTraceMetadata,
|
|
421
443
|
reactMaxHeadersLength: options.reactMaxHeadersLength,
|
|
422
444
|
rootParams: options.rootParams,
|
|
445
|
+
pprFallbackShellSignal: options.pprFallbackShellSignal,
|
|
423
446
|
formState: options.formState ?? null,
|
|
424
447
|
rscStream: rscForResponse,
|
|
425
448
|
scriptNonce: options.scriptNonce,
|
|
426
449
|
sideStream: rscCapture.sideStream,
|
|
427
450
|
ssrHandler,
|
|
428
|
-
waitForAllReady: options.isPrerender
|
|
451
|
+
waitForAllReady: options.isPrerender === true
|
|
429
452
|
});
|
|
430
453
|
},
|
|
431
454
|
renderSpecialErrorResponse(specialError) {
|
|
@@ -482,6 +505,21 @@ async function renderAppPageLifecycle(options) {
|
|
|
482
505
|
renderEnd,
|
|
483
506
|
responseKind: "html"
|
|
484
507
|
});
|
|
508
|
+
if (htmlRender.shellErrorRecovered) {
|
|
509
|
+
const response = buildAppPageHtmlResponse(safeHtmlStream, {
|
|
510
|
+
draftCookie,
|
|
511
|
+
linkHeader,
|
|
512
|
+
isEdgeRuntime: options.isEdgeRuntime,
|
|
513
|
+
middlewareContext: {
|
|
514
|
+
headers: options.middlewareContext.headers,
|
|
515
|
+
status: 500
|
|
516
|
+
},
|
|
517
|
+
policy: { cacheControl: NEVER_CACHE_CONTROL },
|
|
518
|
+
timing: htmlResponseTiming
|
|
519
|
+
});
|
|
520
|
+
applyCdnResponseHeaders(response.headers, { cacheControl: NEVER_CACHE_CONTROL });
|
|
521
|
+
return response;
|
|
522
|
+
}
|
|
485
523
|
const shouldSpeculativelyWriteCache = options.isProduction && shouldCaptureRscForCacheMetadata && revalidateSeconds === null && !options.isDynamicError && !options.isForceStatic && !options.scriptNonce && options.isProgressiveActionRender !== true && !dynamicUsedDuringRender;
|
|
486
524
|
if (htmlResponsePolicy.shouldWriteToCache || shouldSpeculativelyWriteCache) {
|
|
487
525
|
const isrResponse = buildAppPageHtmlResponse(safeHtmlStream, {
|
|
@@ -29,6 +29,7 @@ type ResolveAppPageGenerateStaticParamsSourcesOptions = {
|
|
|
29
29
|
};
|
|
30
30
|
type BuildAppPageElementOptions<TElement> = {
|
|
31
31
|
buildPageElement: () => Promise<TElement>;
|
|
32
|
+
probePageSpecialError?: () => Promise<AppPageSpecialError | null>;
|
|
32
33
|
renderErrorBoundaryPage: (error: unknown) => Promise<Response | null>;
|
|
33
34
|
renderSpecialError: (specialError: AppPageSpecialError) => Promise<Response>;
|
|
34
35
|
resolveSpecialError: (error: unknown) => AppPageSpecialError | null;
|
|
@@ -44,6 +45,7 @@ type AppPageInterceptMatch<TPage = unknown> = {
|
|
|
44
45
|
slotId?: string | null;
|
|
45
46
|
slotKey: string;
|
|
46
47
|
sourceRouteIndex: number;
|
|
48
|
+
sourcePageSegments?: readonly string[] | null;
|
|
47
49
|
};
|
|
48
50
|
type ResolveAppPageInterceptMatchOptions<TRoute, TPage, TInterceptOpts> = {
|
|
49
51
|
cleanPathname: string;
|
|
@@ -180,7 +180,8 @@ async function buildAppPageElement(options) {
|
|
|
180
180
|
response: null
|
|
181
181
|
};
|
|
182
182
|
} catch (error) {
|
|
183
|
-
const
|
|
183
|
+
const buildSpecialError = options.resolveSpecialError(error);
|
|
184
|
+
const specialError = (buildSpecialError ? await options.probePageSpecialError?.() : null) ?? buildSpecialError;
|
|
184
185
|
if (specialError) return {
|
|
185
186
|
element: null,
|
|
186
187
|
response: await options.renderSpecialError(specialError)
|
|
@@ -130,6 +130,7 @@ type BuildAppPageElementsOptions<TModule extends AppPageModule = AppPageModule,
|
|
|
130
130
|
renderIdentity?: AppPageRenderIdentity;
|
|
131
131
|
renderMode?: AppRscRenderMode;
|
|
132
132
|
routePath: string;
|
|
133
|
+
sourcePageSegments?: readonly string[] | null;
|
|
133
134
|
};
|
|
134
135
|
declare function createAppPageTreePath(routeSegments: readonly string[] | null | undefined, treePosition: number): string;
|
|
135
136
|
declare function probeAppPageLayoutWithTracking<TModule extends AppPageModule>(options: {
|
|
@@ -143,7 +144,8 @@ declare function createAppPageLayoutEntries<TModule extends AppPageModule, TErro
|
|
|
143
144
|
forbiddens?: readonly (TModule | null | undefined)[] | null;
|
|
144
145
|
unauthorizeds?: readonly (TModule | null | undefined)[] | null;
|
|
145
146
|
}): AppPageLayoutEntry<TModule, TErrorModule>[];
|
|
147
|
+
declare function createAppPageSourcePage(routeSegments: readonly string[] | null | undefined): string;
|
|
146
148
|
declare function createAppPageRouteBodyMetadata(metadata: Metadata | null, pathname: string, metadataPlacement: "body" | "head", trailingSlash?: boolean): ReactNode;
|
|
147
149
|
declare function buildAppPageElements<TModule extends AppPageModule, TErrorModule extends AppPageErrorModule>(options: BuildAppPageElementsOptions<TModule, TErrorModule>): AppElements;
|
|
148
150
|
//#endregion
|
|
149
|
-
export { AppPageErrorModule, AppPageModule, AppPageRouteWiringRoute, AppPageSlotOverride, buildAppPageElements, createAppPageLayoutEntries, createAppPageRouteBodyMetadata, createAppPageTreePath, probeAppPageLayoutWithTracking, resolveAppPageChildSegments };
|
|
151
|
+
export { AppPageErrorModule, AppPageModule, AppPageRouteWiringRoute, AppPageSlotOverride, buildAppPageElements, createAppPageLayoutEntries, createAppPageRouteBodyMetadata, createAppPageSourcePage, createAppPageTreePath, probeAppPageLayoutWithTracking, resolveAppPageChildSegments };
|
|
@@ -2,7 +2,8 @@ import { createAppRenderDependency, registerAppElementRenderDependencies, render
|
|
|
2
2
|
import { APP_STATIC_SIBLINGS_KEY, AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
|
|
3
3
|
import { APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL, shouldSuppressLoadingBoundaries } from "./app-rsc-render-mode.js";
|
|
4
4
|
import { APP_PREFETCH_LOADING_SHELL_MARKER_KEY } from "./app-elements.js";
|
|
5
|
-
import
|
|
5
|
+
import DefaultGlobalError from "../shims/default-global-error.js";
|
|
6
|
+
import { ErrorBoundary, ForbiddenBoundary, GlobalErrorBoundary, NotFoundBoundary, RedirectBoundary, UnauthorizedBoundary } from "../shims/error-boundary.js";
|
|
6
7
|
import { AppRouterScrollTarget } from "../shims/app-router-scroll.js";
|
|
7
8
|
import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
|
|
8
9
|
import { MetadataHead, ViewportHead, renderMetadataToHtml } from "../shims/metadata.js";
|
|
@@ -14,6 +15,7 @@ import { Fragment, Suspense } from "react";
|
|
|
14
15
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
15
16
|
//#region src/server/app-page-route-wiring.tsx
|
|
16
17
|
const APP_PAGE_LAYOUT_PROBE_CHILD = /* @__PURE__ */ jsx(Fragment, {});
|
|
18
|
+
const DEFAULT_GLOBAL_ERROR_COMPONENT = DefaultGlobalError;
|
|
17
19
|
function getDefaultExport(module) {
|
|
18
20
|
return module?.default ?? null;
|
|
19
21
|
}
|
|
@@ -85,6 +87,9 @@ function createAppPageTemplateEntries(route) {
|
|
|
85
87
|
};
|
|
86
88
|
});
|
|
87
89
|
}
|
|
90
|
+
function createAppPageSourcePage(routeSegments) {
|
|
91
|
+
return `/${[...routeSegments ?? [], "page"].join("/")}`;
|
|
92
|
+
}
|
|
88
93
|
function createAppPageErrorEntries(route) {
|
|
89
94
|
return (route.errorPaths ?? route.errors ?? []).flatMap((errorModule, index) => {
|
|
90
95
|
if (!errorModule) return [];
|
|
@@ -206,6 +211,7 @@ function buildAppPageElements(options) {
|
|
|
206
211
|
layoutIds: options.route.ids?.layouts ?? layoutEntries.map((entry) => entry.id),
|
|
207
212
|
rootLayoutTreePath,
|
|
208
213
|
routeId,
|
|
214
|
+
sourcePage: createAppPageSourcePage(options.sourcePageSegments ?? routeSegments),
|
|
209
215
|
slotBindings: createAppPageSlotBindings(options.route, layoutEntries, resolveSlotOverride, {
|
|
210
216
|
interception: renderIdentity?.interception ?? options.interception ?? null,
|
|
211
217
|
interceptionContext,
|
|
@@ -427,9 +433,12 @@ function buildAppPageElements(options) {
|
|
|
427
433
|
});
|
|
428
434
|
}
|
|
429
435
|
const globalErrorComponent = getErrorBoundaryExport(options.globalErrorModule);
|
|
430
|
-
|
|
431
|
-
fallback:
|
|
432
|
-
children:
|
|
436
|
+
routeChildren = /* @__PURE__ */ jsx(GlobalErrorBoundary, {
|
|
437
|
+
fallback: DEFAULT_GLOBAL_ERROR_COMPONENT,
|
|
438
|
+
children: globalErrorComponent ? /* @__PURE__ */ jsx(ErrorBoundary, {
|
|
439
|
+
fallback: globalErrorComponent,
|
|
440
|
+
children: routeChildren
|
|
441
|
+
}) : routeChildren
|
|
433
442
|
});
|
|
434
443
|
elements[routeId] = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
435
444
|
createAppPageRouteHead(options.resolvedMetadata, options.resolvedViewport, options.resolvedMetadataPathname ?? options.routePath, metadataPlacement, options.trailingSlash),
|
|
@@ -440,4 +449,4 @@ function buildAppPageElements(options) {
|
|
|
440
449
|
return elements;
|
|
441
450
|
}
|
|
442
451
|
//#endregion
|
|
443
|
-
export { buildAppPageElements, createAppPageLayoutEntries, createAppPageRouteBodyMetadata, createAppPageTreePath, probeAppPageLayoutWithTracking, resolveAppPageChildSegments };
|
|
452
|
+
export { buildAppPageElements, createAppPageLayoutEntries, createAppPageRouteBodyMetadata, createAppPageSourcePage, createAppPageTreePath, probeAppPageLayoutWithTracking, resolveAppPageChildSegments };
|
|
@@ -18,6 +18,7 @@ type AppSsrRenderResult = {
|
|
|
18
18
|
htmlStream: ReadableStream<Uint8Array>;
|
|
19
19
|
metadataReady: Promise<void>;
|
|
20
20
|
capturedRscData: Promise<ArrayBuffer> | null;
|
|
21
|
+
shellErrorRecovered?: boolean;
|
|
21
22
|
/**
|
|
22
23
|
* Preload `Link` header value emitted by React during SSR (via `onHeaders`),
|
|
23
24
|
* already capped to `reactMaxHeadersLength`. Empty/undefined when React
|
|
@@ -62,9 +63,14 @@ type AppPageSsrHandler = {
|
|
|
62
63
|
sideStream?: ReadableStream<Uint8Array>;
|
|
63
64
|
capturedRscDataRef?: {
|
|
64
65
|
value: Promise<ArrayBuffer> | null;
|
|
65
|
-
}; /**
|
|
66
|
+
}; /** Abort signal for a build-time PPR fallback-shell static render. */
|
|
67
|
+
pprFallbackShellSignal?: AbortSignal; /** When true, wait for the full React tree before emitting bytes. */
|
|
66
68
|
waitForAllReady?: boolean; /** Dev-only: original server error to surface in the browser overlay. */
|
|
67
69
|
initialDevServerError?: unknown;
|
|
70
|
+
/** When true, an SSR-phase-only shell render error resolves to the
|
|
71
|
+
* default `__next_error__` error-document shell (with the original
|
|
72
|
+
* flight payload and bootstrap) instead of rejecting. See handleSsr. */
|
|
73
|
+
fallbackToErrorDocumentOnShellError?: boolean;
|
|
68
74
|
}) => Promise<ReadableStream<Uint8Array> | AppSsrRenderResult>;
|
|
69
75
|
};
|
|
70
76
|
type RenderAppPageHtmlStreamOptions = {
|
|
@@ -93,9 +99,14 @@ type RenderAppPageHtmlStreamOptions = {
|
|
|
93
99
|
sideStream?: ReadableStream<Uint8Array>; /** Out-parameter filled with accumulated raw RSC bytes after stream consumption. */
|
|
94
100
|
capturedRscDataRef?: {
|
|
95
101
|
value: Promise<ArrayBuffer> | null;
|
|
96
|
-
}; /**
|
|
102
|
+
}; /** Abort signal for a build-time PPR fallback-shell static render. */
|
|
103
|
+
pprFallbackShellSignal?: AbortSignal; /** When true, wait for the full React tree before emitting bytes. */
|
|
97
104
|
waitForAllReady?: boolean; /** Dev-only: original server error to surface in the browser overlay. */
|
|
98
105
|
initialDevServerError?: unknown;
|
|
106
|
+
/** True when the app supplies a custom global-error.tsx. Disables the
|
|
107
|
+
* default error-document shell fallback so SSR shell errors keep driving
|
|
108
|
+
* the server-rendered global-error boundary re-render. */
|
|
109
|
+
hasCustomGlobalError?: boolean;
|
|
99
110
|
};
|
|
100
111
|
type RenderAppPageHtmlResponseOptions = {
|
|
101
112
|
clearRequestContext: () => void;
|
|
@@ -108,7 +119,8 @@ type AppPageHtmlStreamRecoveryResult = {
|
|
|
108
119
|
htmlStream: ReadableStream<Uint8Array> | null;
|
|
109
120
|
response: Response | null;
|
|
110
121
|
metadataReady: Promise<void>;
|
|
111
|
-
capturedRscData: Promise<ArrayBuffer> | null;
|
|
122
|
+
capturedRscData: Promise<ArrayBuffer> | null;
|
|
123
|
+
shellErrorRecovered: boolean; /** React-emitted preload `Link` header (already capped). */
|
|
112
124
|
linkHeader?: string;
|
|
113
125
|
};
|
|
114
126
|
type RenderAppPageHtmlStreamWithRecoveryOptions<TSpecialError> = {
|
|
@@ -11,7 +11,8 @@ function normalizeAppSsrRenderResult(raw, fallbackCapturedRscData = null) {
|
|
|
11
11
|
return {
|
|
12
12
|
htmlStream: raw,
|
|
13
13
|
metadataReady: resolvedMetadataReady,
|
|
14
|
-
capturedRscData: fallbackCapturedRscData
|
|
14
|
+
capturedRscData: fallbackCapturedRscData,
|
|
15
|
+
shellErrorRecovered: false
|
|
15
16
|
};
|
|
16
17
|
}
|
|
17
18
|
/**
|
|
@@ -62,8 +63,10 @@ async function renderAppPageHtmlStream(options) {
|
|
|
62
63
|
rootParams: options.rootParams,
|
|
63
64
|
sideStream: options.sideStream,
|
|
64
65
|
capturedRscDataRef: options.capturedRscDataRef,
|
|
66
|
+
pprFallbackShellSignal: options.pprFallbackShellSignal,
|
|
65
67
|
waitForAllReady: options.waitForAllReady,
|
|
66
|
-
initialDevServerError: options.initialDevServerError
|
|
68
|
+
initialDevServerError: options.initialDevServerError,
|
|
69
|
+
fallbackToErrorDocumentOnShellError: options.waitForAllReady !== true && options.hasCustomGlobalError === false
|
|
67
70
|
};
|
|
68
71
|
return normalizeAppSsrRenderResult(await options.ssrHandler.handleSsr(options.rscStream, options.navigationContext, options.fontData, ssrOptions), options.capturedRscDataRef?.value ?? null);
|
|
69
72
|
}
|
|
@@ -121,13 +124,14 @@ async function renderAppPageHtmlResponse(options) {
|
|
|
121
124
|
}
|
|
122
125
|
async function renderAppPageHtmlStreamWithRecovery(options) {
|
|
123
126
|
try {
|
|
124
|
-
const { htmlStream, metadataReady, capturedRscData, linkHeader } = normalizeAppSsrRenderResult(await options.renderHtmlStream());
|
|
127
|
+
const { htmlStream, metadataReady, capturedRscData, linkHeader, shellErrorRecovered } = normalizeAppSsrRenderResult(await options.renderHtmlStream());
|
|
125
128
|
options.onShellRendered?.();
|
|
126
129
|
return {
|
|
127
130
|
htmlStream,
|
|
128
131
|
response: null,
|
|
129
132
|
metadataReady,
|
|
130
133
|
capturedRscData,
|
|
134
|
+
shellErrorRecovered: shellErrorRecovered === true,
|
|
131
135
|
linkHeader
|
|
132
136
|
};
|
|
133
137
|
} catch (error) {
|
|
@@ -136,14 +140,16 @@ async function renderAppPageHtmlStreamWithRecovery(options) {
|
|
|
136
140
|
htmlStream: null,
|
|
137
141
|
response: await options.renderSpecialErrorResponse(specialError),
|
|
138
142
|
metadataReady: resolvedMetadataReady,
|
|
139
|
-
capturedRscData: null
|
|
143
|
+
capturedRscData: null,
|
|
144
|
+
shellErrorRecovered: false
|
|
140
145
|
};
|
|
141
146
|
const boundaryResponse = await options.renderErrorBoundaryResponse(error);
|
|
142
147
|
if (boundaryResponse) return {
|
|
143
148
|
htmlStream: null,
|
|
144
149
|
response: boundaryResponse,
|
|
145
150
|
metadataReady: resolvedMetadataReady,
|
|
146
|
-
capturedRscData: null
|
|
151
|
+
capturedRscData: null,
|
|
152
|
+
shellErrorRecovered: false
|
|
147
153
|
};
|
|
148
154
|
throw error;
|
|
149
155
|
}
|
|
@@ -3,7 +3,23 @@ import { AppMiddlewareContext } from "./app-middleware.js";
|
|
|
3
3
|
//#region src/server/app-pages-bridge.d.ts
|
|
4
4
|
type PagesEntry = {
|
|
5
5
|
handleApiRoute?: (request: Request, url: string) => Promise<Response> | Response;
|
|
6
|
-
|
|
6
|
+
matchApiRoute?: (url: string, request: Request) => PagesRouteMatch | null;
|
|
7
|
+
matchPageRoute?: (url: string, request: Request) => PagesRouteMatch | null;
|
|
8
|
+
renderPage?: (request: Request, url: string, query: Record<string, unknown>, parsedUrl: unknown, middlewareRequestHeaders?: Headers | null, options?: {
|
|
9
|
+
isDataReq?: boolean;
|
|
10
|
+
}) => Promise<Response> | Response;
|
|
11
|
+
};
|
|
12
|
+
type PagesRouteMatch = {
|
|
13
|
+
route: {
|
|
14
|
+
isDynamic: boolean;
|
|
15
|
+
pattern: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
type AppRouteMatch = {
|
|
19
|
+
route: {
|
|
20
|
+
isDynamic: boolean;
|
|
21
|
+
pattern: string;
|
|
22
|
+
};
|
|
7
23
|
};
|
|
8
24
|
type RenderPagesFallbackDependencies = {
|
|
9
25
|
loadPagesEntry: () => Promise<PagesEntry> | PagesEntry;
|
|
@@ -28,8 +44,14 @@ type RenderPagesFallbackDependencies = {
|
|
|
28
44
|
getDraftModeCookieHeader: () => string | null | undefined;
|
|
29
45
|
};
|
|
30
46
|
type RenderPagesFallbackOptions = {
|
|
47
|
+
allowRscDocumentFallback?: boolean;
|
|
48
|
+
appRouteMatch?: AppRouteMatch | null;
|
|
49
|
+
isDataRequest?: boolean;
|
|
31
50
|
isRscRequest: boolean;
|
|
51
|
+
matchKind?: "dynamic" | "static";
|
|
32
52
|
middlewareContext: AppMiddlewareContext;
|
|
53
|
+
pathname?: string;
|
|
54
|
+
pagesDataRequest?: Request | null;
|
|
33
55
|
request: Request;
|
|
34
56
|
url: URL;
|
|
35
57
|
};
|
|
@@ -1,36 +1,45 @@
|
|
|
1
|
+
import { cloneRequestWithHeaders, cloneRequestWithUrl } from "./request-pipeline.js";
|
|
2
|
+
import { pagesRouteHasPriorityOverAppRoute } from "./hybrid-route-priority.js";
|
|
1
3
|
//#region src/server/app-pages-bridge.ts
|
|
2
4
|
/**
|
|
3
5
|
* Fallback handler to route App Router requests to the Pages Router when no App Router route matches.
|
|
4
6
|
*/
|
|
5
7
|
async function renderPagesFallback(options, dependencies) {
|
|
6
|
-
const { isRscRequest, middlewareContext, request, url } = options;
|
|
8
|
+
const { allowRscDocumentFallback = false, appRouteMatch = null, isDataRequest = false, isRscRequest, matchKind, middlewareContext, pathname = options.url.pathname, pagesDataRequest = null, request, url } = options;
|
|
7
9
|
const { loadPagesEntry, buildRequestHeaders, decodePathParams, applyRouteHandlerMiddlewareContext, getDraftModeCookieHeader } = dependencies;
|
|
8
|
-
if (isRscRequest) return null;
|
|
10
|
+
if (isRscRequest && !allowRscDocumentFallback) return null;
|
|
9
11
|
const pagesEntry = await loadPagesEntry();
|
|
10
12
|
const pagesRequestHeaders = middlewareContext.requestHeaders ? buildRequestHeaders(request.headers, middlewareContext.requestHeaders) : null;
|
|
11
13
|
let pagesRequest = request;
|
|
12
|
-
if (pagesRequestHeaders)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (request.method !== "GET" && request.method !== "HEAD") {
|
|
18
|
-
pagesRequestInit.body = request.body;
|
|
19
|
-
pagesRequestInit.duplex = "half";
|
|
20
|
-
}
|
|
21
|
-
pagesRequest = new Request(request.url, pagesRequestInit);
|
|
22
|
-
}
|
|
23
|
-
const pagesUrl = decodePathParams(url.pathname) + (url.search || "");
|
|
24
|
-
const pagesPathname = url.pathname;
|
|
14
|
+
if (pagesRequestHeaders) pagesRequest = cloneRequestWithHeaders(request, pagesRequestHeaders);
|
|
15
|
+
const queryIndex = pathname.indexOf("?");
|
|
16
|
+
const pagesPathname = queryIndex === -1 ? pathname : pathname.slice(0, queryIndex);
|
|
17
|
+
const pagesSearch = queryIndex === -1 ? url.search || "" : pathname.slice(queryIndex);
|
|
18
|
+
const pagesUrl = decodePathParams(pagesPathname) + pagesSearch;
|
|
25
19
|
if (pagesPathname.startsWith("/api/") || pagesPathname === "/api") {
|
|
26
20
|
if (typeof pagesEntry.handleApiRoute !== "function") return null;
|
|
21
|
+
const hasApiMatcher = typeof pagesEntry.matchApiRoute === "function";
|
|
22
|
+
const apiMatch = hasApiMatcher ? pagesEntry.matchApiRoute?.(pagesUrl, pagesRequest) ?? null : null;
|
|
23
|
+
if (hasApiMatcher && apiMatch === null) return null;
|
|
24
|
+
if (apiMatch !== null && matchKind === "static" && apiMatch.route.isDynamic) return null;
|
|
25
|
+
if (apiMatch !== null && matchKind === "dynamic" && !apiMatch.route.isDynamic) return null;
|
|
26
|
+
if (appRouteMatch !== null) {
|
|
27
|
+
if (apiMatch === null || !pagesRouteHasPriorityOverAppRoute(apiMatch.route, appRouteMatch.route)) return null;
|
|
28
|
+
}
|
|
27
29
|
const pagesApiResponse = await pagesEntry.handleApiRoute(pagesRequest, pagesUrl);
|
|
28
30
|
const draftCookie = getDraftModeCookieHeader();
|
|
29
31
|
return applyDraftModeCookie(applyRouteHandlerMiddlewareContext(pagesApiResponse, middlewareContext), draftCookie);
|
|
30
32
|
}
|
|
31
33
|
if (typeof pagesEntry.renderPage !== "function") return null;
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
+
const hasPageMatcher = typeof pagesEntry.matchPageRoute === "function";
|
|
35
|
+
const pageMatch = hasPageMatcher ? pagesEntry.matchPageRoute?.(pagesUrl, pagesRequest) ?? null : null;
|
|
36
|
+
if (hasPageMatcher && pageMatch === null) return null;
|
|
37
|
+
if (pageMatch !== null && matchKind === "static" && pageMatch.route.isDynamic) return null;
|
|
38
|
+
if (pageMatch !== null && matchKind === "dynamic" && !pageMatch.route.isDynamic) return null;
|
|
39
|
+
if (appRouteMatch !== null && (pageMatch === null || !pagesRouteHasPriorityOverAppRoute(pageMatch.route, appRouteMatch.route))) return null;
|
|
40
|
+
const renderRequest = pagesDataRequest ? cloneRequestWithUrl(pagesRequest, pagesDataRequest.url) : pagesRequest;
|
|
41
|
+
const pagesRes = isDataRequest ? await pagesEntry.renderPage(renderRequest, pagesUrl, {}, void 0, middlewareContext.requestHeaders, { isDataReq: true }) : await pagesEntry.renderPage(renderRequest, pagesUrl, {}, void 0, middlewareContext.requestHeaders);
|
|
42
|
+
if (pagesRes.status === 404 && pageMatch === null) return null;
|
|
34
43
|
return applyDraftModeCookie(pagesRes, getDraftModeCookieHeader());
|
|
35
44
|
}
|
|
36
45
|
/**
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { PprFallbackShellState } from "../shims/ppr-fallback-shell.js";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
|
|
4
|
+
//#region src/server/app-ppr-fallback-shell-render.d.ts
|
|
5
|
+
type AppPageBoundaryOnError = (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown;
|
|
6
|
+
type AppPageRenderableElement = ReactNode | Record<string, ReactNode>;
|
|
7
|
+
declare function warmPprFallbackShellCaches(options: {
|
|
8
|
+
element: AppPageRenderableElement;
|
|
9
|
+
onError: AppPageBoundaryOnError;
|
|
10
|
+
renderToReadableStream: (element: AppPageRenderableElement, options: {
|
|
11
|
+
onError: AppPageBoundaryOnError;
|
|
12
|
+
signal?: AbortSignal;
|
|
13
|
+
}) => ReadableStream<Uint8Array>;
|
|
14
|
+
state: PprFallbackShellState;
|
|
15
|
+
}): Promise<void>;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { warmPprFallbackShellCaches };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { isPprFallbackShellAbortError, preparePprFallbackShellFinalRender, waitForPprFallbackShellCacheReady } from "../shims/ppr-fallback-shell.js";
|
|
2
|
+
import { readAppPageBinaryStream } from "./app-page-execution.js";
|
|
3
|
+
//#region src/server/app-ppr-fallback-shell-render.ts
|
|
4
|
+
async function warmPprFallbackShellCaches(options) {
|
|
5
|
+
let warmupError = null;
|
|
6
|
+
const warmupDrain = readAppPageBinaryStream(options.renderToReadableStream(options.element, {
|
|
7
|
+
signal: options.state.abortController.signal,
|
|
8
|
+
onError(error, requestInfo, errorContext) {
|
|
9
|
+
if (options.state.abortController.signal.aborted || isPprFallbackShellAbortError(error)) return;
|
|
10
|
+
return options.onError(error, requestInfo, errorContext);
|
|
11
|
+
}
|
|
12
|
+
})).catch((error) => {
|
|
13
|
+
if (options.state.abortController.signal.aborted || isPprFallbackShellAbortError(error)) return;
|
|
14
|
+
warmupError = error;
|
|
15
|
+
});
|
|
16
|
+
try {
|
|
17
|
+
await waitForPprFallbackShellCacheReady(options.state);
|
|
18
|
+
} finally {
|
|
19
|
+
options.state.abortController.abort();
|
|
20
|
+
await warmupDrain;
|
|
21
|
+
preparePprFallbackShellFinalRender(options.state);
|
|
22
|
+
}
|
|
23
|
+
if (warmupError) throw warmupError;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { warmPprFallbackShellCaches };
|
|
@@ -9,6 +9,18 @@ type AppPprFallbackShell = {
|
|
|
9
9
|
pathname: string;
|
|
10
10
|
params: Record<string, string | string[]>;
|
|
11
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* A fallback-shell cache entry as consumed by the dispatch layer.
|
|
14
|
+
* Produced at build time by the PPR prerender and served at request time
|
|
15
|
+
* when the exact cache entry for a dynamic child param is missing.
|
|
16
|
+
*/
|
|
17
|
+
type AppPagePprFallbackCacheShell = {
|
|
18
|
+
fallbackParamNames: readonly string[];
|
|
19
|
+
params: Record<string, string | string[]>;
|
|
20
|
+
pathname: string;
|
|
21
|
+
};
|
|
22
|
+
declare function markAppPprDynamicFallbackShellHtml(html: string): string;
|
|
23
|
+
declare function isAppPprDynamicFallbackShellHtml(html: string): boolean;
|
|
12
24
|
declare function createAppPprFallbackShell(route: AppPprFallbackShellRoute, matchedParams: Record<string, string | string[]>): AppPprFallbackShell | null;
|
|
13
25
|
declare function createAppPprFallbackShells(route: AppPprFallbackShellRoute, matchedParams: Record<string, string | string[]>): AppPprFallbackShell[];
|
|
14
26
|
declare function rewriteAppPprFallbackShellHtmlNavigation(options: {
|
|
@@ -18,4 +30,4 @@ declare function rewriteAppPprFallbackShellHtmlNavigation(options: {
|
|
|
18
30
|
searchParams: URLSearchParams;
|
|
19
31
|
}): string;
|
|
20
32
|
//#endregion
|
|
21
|
-
export { createAppPprFallbackShell, createAppPprFallbackShells, rewriteAppPprFallbackShellHtmlNavigation };
|
|
33
|
+
export { AppPagePprFallbackCacheShell, createAppPprFallbackShell, createAppPprFallbackShells, isAppPprDynamicFallbackShellHtml, markAppPprDynamicFallbackShellHtml, rewriteAppPprFallbackShellHtmlNavigation };
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { createInlineScriptTag } from "./html.js";
|
|
2
2
|
import { createNavigationRuntimeRscMetadataScript } from "./app-ssr-stream.js";
|
|
3
3
|
//#region src/server/app-ppr-fallback-shell.ts
|
|
4
|
+
const PPR_DYNAMIC_FALLBACK_SHELL_MARKER = "<!--vinext-ppr-dynamic-fallback-shell-->";
|
|
5
|
+
function markAppPprDynamicFallbackShellHtml(html) {
|
|
6
|
+
return html + PPR_DYNAMIC_FALLBACK_SHELL_MARKER;
|
|
7
|
+
}
|
|
8
|
+
function isAppPprDynamicFallbackShellHtml(html) {
|
|
9
|
+
return html.includes(PPR_DYNAMIC_FALLBACK_SHELL_MARKER);
|
|
10
|
+
}
|
|
4
11
|
function routeRootParamNames(route) {
|
|
5
12
|
return new Set(route.rootParamNames ?? []);
|
|
6
13
|
}
|
|
@@ -79,4 +86,4 @@ function rewriteAppPprFallbackShellHtmlNavigation(options) {
|
|
|
79
86
|
return metadataScript + options.html;
|
|
80
87
|
}
|
|
81
88
|
//#endregion
|
|
82
|
-
export { createAppPprFallbackShell, createAppPprFallbackShells, rewriteAppPprFallbackShellHtmlNavigation };
|
|
89
|
+
export { createAppPprFallbackShell, createAppPprFallbackShells, isAppPprDynamicFallbackShellHtml, markAppPprDynamicFallbackShellHtml, rewriteAppPprFallbackShellHtmlNavigation };
|
|
@@ -2,16 +2,17 @@ import { createRequestContext, runWithRequestContext } from "../shims/unified-re
|
|
|
2
2
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
3
3
|
import { reportRequestError } from "./instrumentation.js";
|
|
4
4
|
import { consumeDynamicUsage, getAndClearPendingCookies, getDraftModeCookieHeader, markDynamicUsage, setHeadersAccessPhase } from "../shims/headers.js";
|
|
5
|
-
import { ensureFetchPatch, getCollectedFetchTags, setCurrentFetchSoftTags } from "../shims/fetch-cache.js";
|
|
5
|
+
import { ensureFetchPatch, getCollectedFetchTags, setCurrentFetchCacheMode, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault } from "../shims/fetch-cache.js";
|
|
6
6
|
import { setNavigationContext } from "../shims/navigation.js";
|
|
7
7
|
import { makeThenableParams } from "../shims/thenable-params.js";
|
|
8
|
+
import { buildPageCacheTags } from "./implicit-tags.js";
|
|
8
9
|
import { isKnownDynamicAppRoute, isValidHTTPMethod } from "./app-route-handler-runtime.js";
|
|
9
10
|
import { getAppRouteHandlerRevalidateSeconds, hasAppRouteHandlerDefaultExport, resolveAppRouteHandlerMethod, shouldReadAppRouteHandlerCache } from "./app-route-handler-policy.js";
|
|
10
11
|
import { createStaticGenerationHeadersContext } from "./app-static-generation.js";
|
|
11
|
-
import { buildPageCacheTags } from "./implicit-tags.js";
|
|
12
12
|
import { applyRouteHandlerMiddlewareContext } from "./app-route-handler-response.js";
|
|
13
13
|
import { executeAppRouteHandler } from "./app-route-handler-execution.js";
|
|
14
14
|
import { readAppRouteHandlerCacheResponse } from "./app-route-handler-cache.js";
|
|
15
|
+
import { resolveAppRouteHandlerFetchCacheMode } from "./app-segment-config.js";
|
|
15
16
|
//#region src/server/app-route-handler-dispatch.ts
|
|
16
17
|
function isAppRouteHandlerFunction(value) {
|
|
17
18
|
return typeof value === "function";
|
|
@@ -32,6 +33,8 @@ async function runInRouteHandlerRevalidationContext(options, renderFn) {
|
|
|
32
33
|
}), async () => {
|
|
33
34
|
ensureFetchPatch();
|
|
34
35
|
setCurrentFetchSoftTags(buildRouteHandlerPageCacheTags(options.cleanPathname, [], options.routeSegments));
|
|
36
|
+
setCurrentFetchCacheMode(options.fetchCacheMode);
|
|
37
|
+
setCurrentForceDynamicFetchDefault(options.dynamicConfig === "force-dynamic");
|
|
35
38
|
await renderFn();
|
|
36
39
|
});
|
|
37
40
|
}
|
|
@@ -56,6 +59,9 @@ async function dispatchAppRouteHandler(options) {
|
|
|
56
59
|
}), options.middlewareContext);
|
|
57
60
|
}
|
|
58
61
|
const resolvedHandlerFn = isAppRouteHandlerFunction(handlerFn) ? handlerFn : void 0;
|
|
62
|
+
const fetchCacheMode = resolveAppRouteHandlerFetchCacheMode(handler);
|
|
63
|
+
setCurrentFetchCacheMode(fetchCacheMode);
|
|
64
|
+
setCurrentForceDynamicFetchDefault(handler.dynamic === "force-dynamic");
|
|
59
65
|
if (revalidateSeconds !== null && shouldReadAppRouteHandlerCache({
|
|
60
66
|
dynamicConfig: handler.dynamic,
|
|
61
67
|
handlerFn: resolvedHandlerFn,
|
|
@@ -96,6 +102,7 @@ async function dispatchAppRouteHandler(options) {
|
|
|
96
102
|
cleanPathname: options.cleanPathname,
|
|
97
103
|
draftModeSecret: options.draftModeSecret,
|
|
98
104
|
dynamicConfig: handler.dynamic,
|
|
105
|
+
fetchCacheMode,
|
|
99
106
|
routePattern: route.pattern,
|
|
100
107
|
routeSegments: route.routeSegments
|
|
101
108
|
}, renderFn);
|
|
@@ -3,6 +3,7 @@ import { RouteHandlerHttpMethod, RouteHandlerModule } from "./app-route-handler-
|
|
|
3
3
|
//#region src/server/app-route-handler-policy.d.ts
|
|
4
4
|
type AppRouteHandlerModule = {
|
|
5
5
|
dynamic?: string;
|
|
6
|
+
fetchCache?: unknown;
|
|
6
7
|
revalidate?: unknown;
|
|
7
8
|
} & RouteHandlerModule;
|
|
8
9
|
type AppRouteHandlerFunction = (...args: unknown[]) => unknown;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import "./server-globals.js";
|
|
2
2
|
import { runWithExecutionContext } from "../shims/request-context.js";
|
|
3
|
+
import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER } from "./headers.js";
|
|
3
4
|
import { badRequestResponse, notFoundResponse, notFoundStaticAssetResponse } from "./http-error-responses.js";
|
|
4
5
|
import { cloneRequestWithHeaders, filterInternalHeaders, isOpenRedirectShaped } from "./request-pipeline.js";
|
|
5
6
|
import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js";
|
|
6
7
|
import { resolveStaticAssetSignal } from "./worker-utils.js";
|
|
8
|
+
import { readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
|
|
7
9
|
import rscHandler, { __assetPrefix, __basePath } from "virtual:vinext-rsc-entry";
|
|
8
10
|
import { registerConfiguredCacheAdapters } from "virtual:vinext-cache-adapters";
|
|
9
11
|
//#region src/server/app-router-entry.ts
|
|
@@ -23,7 +25,10 @@ async function handleRequest(request, env, ctx) {
|
|
|
23
25
|
}
|
|
24
26
|
if (isNextStaticPath(url.pathname, __workerBasePath, __workerAssetPathPrefix)) return notFoundStaticAssetResponse();
|
|
25
27
|
{
|
|
28
|
+
const prerenderRouteParamsPayload = readTrustedPrerenderRouteParams(request);
|
|
26
29
|
const filteredHeaders = filterInternalHeaders(request.headers);
|
|
30
|
+
const prerenderRouteParamsHeader = serializePrerenderRouteParamsHeader(prerenderRouteParamsPayload);
|
|
31
|
+
if (prerenderRouteParamsHeader !== null) filteredHeaders.set(VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, prerenderRouteParamsHeader);
|
|
27
32
|
request = cloneRequestWithHeaders(request, filteredHeaders);
|
|
28
33
|
}
|
|
29
34
|
const handleFn = () => rscHandler(request, ctx);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_RSC_RENDER_MODE_HEADER } from "./headers.js";
|
|
2
2
|
import { fnv1a64 } from "../utils/hash.js";
|
|
3
3
|
import { parseAppRscRenderMode } from "./app-rsc-render-mode.js";
|
|
4
|
+
import { applyDeploymentIdHeader } from "../utils/deployment-id.js";
|
|
4
5
|
//#region src/server/app-rsc-cache-busting.ts
|
|
5
6
|
/**
|
|
6
7
|
* RSC cache-busting hashes cover the headers that make an RSC payload vary.
|
|
@@ -148,6 +149,7 @@ function createRscRequestHeaders(options = {}) {
|
|
|
148
149
|
Accept: VINEXT_RSC_CONTENT_TYPE,
|
|
149
150
|
["RSC"]: "1"
|
|
150
151
|
});
|
|
152
|
+
applyDeploymentIdHeader(headers);
|
|
151
153
|
if (options.interceptionContext !== void 0 && options.interceptionContext !== null) headers.set(VINEXT_INTERCEPTION_CONTEXT_HEADER, options.interceptionContext);
|
|
152
154
|
if (options.mountedSlotsHeader !== void 0 && options.mountedSlotsHeader !== null) headers.set(VINEXT_MOUNTED_SLOTS_HEADER, options.mountedSlotsHeader);
|
|
153
155
|
if (options.clientReuseManifestHeader !== void 0 && options.clientReuseManifestHeader !== null) headers.set(VINEXT_CLIENT_REUSE_MANIFEST_HEADER, options.clientReuseManifestHeader);
|