vinext 1.0.0-beta.0 → 1.0.0-beta.1
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 +17 -1
- package/dist/build/assets-ignore.js +1 -1
- package/dist/build/clean-output.js +1 -1
- package/dist/build/client-build-config.js +6 -4
- package/dist/build/css-url-assets.js +3 -3
- package/dist/build/google-fonts/fallback-metrics.js +1 -1
- package/dist/build/google-fonts/font-metadata.js +1 -1
- package/dist/build/inject-pregenerated-paths.js +1 -1
- package/dist/build/inline-css.js +2 -5
- package/dist/build/module-dependency-cache.d.ts +4 -0
- package/dist/build/module-dependency-cache.js +13 -0
- package/dist/build/next-client-runtime-manifests.js +1 -1
- package/dist/build/pages-client-assets-module.js +1 -1
- package/dist/build/precompress.js +7 -7
- package/dist/build/prerender-paths.d.ts +2 -2
- package/dist/build/prerender-paths.js +10 -15
- package/dist/build/prerender-server-pool.js +2 -2
- package/dist/build/prerender.js +1 -1
- package/dist/build/preview-credentials.d.ts +11 -0
- package/dist/build/preview-credentials.js +19 -0
- package/dist/build/report.d.ts +0 -3
- package/dist/build/report.js +2 -4
- package/dist/build/run-prerender.d.ts +2 -11
- package/dist/build/run-prerender.js +2 -10
- package/dist/build/server-manifest.js +1 -1
- package/dist/build/ssr-manifest.d.ts +4 -0
- package/dist/build/ssr-manifest.js +10 -6
- package/dist/build/standalone.js +37 -37
- package/dist/cache/cache-adapters-virtual.d.ts +1 -17
- package/dist/cache/cache-adapters-virtual.js +20 -11
- package/dist/check.d.ts +0 -16
- package/dist/check.js +12 -34
- package/dist/cli.js +58 -53
- package/dist/client/instrumentation-client-inject.js +1 -1
- package/dist/client/pages-router-link-navigation.js +1 -1
- package/dist/config/config-matchers.js +2 -2
- package/dist/config/dotenv.js +1 -1
- package/dist/config/next-config.d.ts +4 -1
- package/dist/config/next-config.js +81 -14
- package/dist/config/prerender.d.ts +2 -2
- package/dist/config/prerender.js +7 -15
- package/dist/config/server-external-packages.js +1 -1
- package/dist/config/tsconfig-paths.js +2 -2
- package/dist/{node_modules/.pnpm/am-i-vibing@0.5.0/node_modules → deps/.pnpm/am-i-vibing@0.5.0/deps}/am-i-vibing/dist/detector-1yx2Hoe0.js +2 -2
- package/dist/deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js +50 -0
- package/dist/entries/app-rsc-entry.js +12 -5
- package/dist/entries/app-rsc-manifest.js +4 -4
- package/dist/entries/pages-client-entry.js +6 -5
- package/dist/entries/pages-server-entry.js +15 -26
- package/dist/entries/runtime-entry-module.js +2 -2
- package/dist/index.js +255 -195
- package/dist/init-cloudflare.js +1 -1
- package/dist/init-platform.js +1 -1
- package/dist/init.js +5 -5
- package/dist/plugins/ast-utils.js +1 -1
- package/dist/plugins/dynamic-preload-metadata.js +7 -7
- package/dist/plugins/extensionless-dynamic-import.js +1 -1
- package/dist/plugins/fonts.js +3 -3
- package/dist/plugins/ignore-dynamic-requests.js +13 -8
- package/dist/plugins/import-meta-url.js +16 -17
- package/dist/plugins/middleware-export-validation.js +1 -1
- package/dist/plugins/middleware-server-only.js +2 -2
- package/dist/plugins/og-asset-ownership.js +7 -6
- package/dist/plugins/og-assets.js +4 -5
- package/dist/plugins/optimize-imports.js +12 -13
- package/dist/plugins/postcss.js +1 -1
- package/dist/plugins/remove-console.js +1 -1
- package/dist/plugins/require-context.js +1 -1
- package/dist/plugins/sass.js +2 -2
- package/dist/plugins/server-externals-manifest.js +1 -1
- package/dist/plugins/strip-server-exports.js +1 -1
- package/dist/plugins/styled-jsx.js +3 -2
- package/dist/plugins/typeof-window.js +1 -1
- package/dist/routing/app-route-graph.d.ts +3 -10
- package/dist/routing/app-route-graph.js +28 -76
- package/dist/routing/app-router.d.ts +0 -5
- package/dist/routing/app-router.js +0 -5
- package/dist/routing/file-matcher.d.ts +2 -6
- package/dist/routing/file-matcher.js +10 -11
- package/dist/routing/pages-router.js +3 -3
- package/dist/server/api-handler.js +41 -33
- package/dist/server/app-browser-entry.js +17 -11
- package/dist/server/app-browser-navigation-controller.js +5 -3
- package/dist/server/app-browser-server-action-client.js +1 -1
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-visible-commit.js +1 -1
- package/dist/server/app-elements-wire.d.ts +2 -1
- package/dist/server/app-fallback-renderer.d.ts +8 -0
- package/dist/server/app-fallback-renderer.js +13 -1
- package/dist/server/app-page-boundary-render.d.ts +14 -1
- package/dist/server/app-page-boundary-render.js +107 -54
- package/dist/server/app-page-dispatch.d.ts +1 -0
- package/dist/server/app-page-dispatch.js +26 -37
- package/dist/server/app-page-element-builder.d.ts +2 -1
- package/dist/server/app-page-element-builder.js +3 -3
- package/dist/server/app-page-execution.d.ts +3 -1
- package/dist/server/app-page-execution.js +31 -39
- package/dist/server/app-page-request.js +1 -1
- package/dist/server/app-page-route-wiring.js +1 -1
- package/dist/server/app-route-handler-execution.js +1 -1
- package/dist/server/app-route-tree-prefetch.js +1 -1
- package/dist/server/app-rsc-cache-busting.js +1 -1
- package/dist/server/app-rsc-handler.js +3 -3
- package/dist/server/app-rsc-redirect-flight.d.ts +66 -0
- package/dist/server/app-rsc-redirect-flight.js +71 -0
- package/dist/server/app-segment-config.js +2 -2
- package/dist/server/app-server-action-execution.js +1 -1
- package/dist/server/app-ssr-entry.js +6 -3
- package/dist/server/app-ssr-stream.d.ts +2 -1
- package/dist/server/app-ssr-stream.js +4 -1
- package/dist/server/cache-proof.js +1 -1
- package/dist/server/default-global-error-module.d.ts +3 -1
- package/dist/server/default-not-found-module.d.ts +3 -1
- package/dist/server/dev-lockfile.js +2 -3
- package/dist/server/dev-route-files.js +1 -1
- package/dist/server/dev-server.js +253 -161
- package/dist/server/dev-stack-sourcemap.js +4 -3
- package/dist/server/headers.d.ts +3 -1
- package/dist/server/headers.js +3 -1
- package/dist/server/image-optimization.js +2 -2
- package/dist/server/implicit-tags.js +2 -1
- package/dist/server/instrumentation.js +2 -2
- package/dist/server/isr-cache.js +1 -1
- package/dist/server/metadata-routes.js +4 -4
- package/dist/server/middleware-response-headers.js +1 -1
- package/dist/server/middleware-runtime.js +1 -1
- package/dist/server/middleware.d.ts +1 -0
- package/dist/server/middleware.js +1 -1
- package/dist/server/navigation-planner.d.ts +2 -0
- package/dist/server/navigation-planner.js +8 -2
- package/dist/server/next-error-digest.d.ts +9 -24
- package/dist/server/next-error-digest.js +23 -15
- package/dist/server/operation-token.js +1 -1
- package/dist/server/pages-body-parser-config.js +2 -1
- package/dist/server/pages-dev-hydration.d.ts +14 -0
- package/dist/server/pages-dev-hydration.js +83 -0
- package/dist/server/pages-dev-module-url.js +2 -2
- package/dist/server/pages-node-compat.d.ts +13 -6
- package/dist/server/pages-node-compat.js +44 -45
- package/dist/server/pages-page-data.d.ts +1 -1
- package/dist/server/pages-page-data.js +4 -3
- package/dist/server/pages-page-handler.js +61 -29
- package/dist/server/pages-page-response.d.ts +2 -2
- package/dist/server/pages-preview.d.ts +26 -0
- package/dist/server/pages-preview.js +165 -0
- package/dist/server/pages-readiness.d.ts +2 -1
- package/dist/server/pages-readiness.js +4 -2
- package/dist/server/prod-server.js +9 -8
- package/dist/server/request-pipeline.js +1 -1
- package/dist/server/seed-cache.js +1 -1
- package/dist/server/socket-error-backstop.js +1 -1
- package/dist/server/static-file-cache.js +7 -8
- package/dist/server/worker-utils.js +1 -1
- package/dist/shims/cache.js +2 -1
- package/dist/shims/constants.js +1 -1
- package/dist/shims/error-boundary.d.ts +4 -4
- package/dist/shims/error.d.ts +21 -5
- package/dist/shims/error.js +52 -14
- package/dist/shims/fetch-cache.js +1 -1
- package/dist/shims/font-utils.js +1 -1
- package/dist/shims/form.d.ts +1 -1
- package/dist/shims/head.js +3 -3
- package/dist/shims/headers.js +6 -4
- package/dist/shims/internal/pages-data-fetch-dedup.js +5 -3
- package/dist/shims/layout-segment-context.d.ts +1 -1
- package/dist/shims/link.d.ts +3 -1
- package/dist/shims/link.js +6 -3
- package/dist/shims/navigation-errors.d.ts +2 -1
- package/dist/shims/navigation-errors.js +9 -13
- package/dist/shims/navigation.d.ts +1 -1
- package/dist/shims/navigation.js +5 -5
- package/dist/shims/navigation.react-server.js +1 -1
- package/dist/shims/router-state.d.ts +1 -0
- package/dist/shims/router.d.ts +2 -1
- package/dist/shims/router.js +18 -11
- package/dist/shims/script.js +1 -1
- package/dist/shims/server.js +2 -2
- package/dist/shims/slot.d.ts +1 -1
- package/dist/shims/thenable-params.js +1 -1
- package/dist/typegen.js +9 -11
- package/dist/utils/client-build-manifest.js +2 -2
- package/dist/utils/client-entry-manifest.js +1 -1
- package/dist/utils/client-runtime-metadata.js +1 -1
- package/dist/utils/commonjs-loader.js +3 -3
- package/dist/utils/mdx-scan.js +1 -1
- package/dist/utils/path.d.ts +1 -13
- package/dist/utils/path.js +1 -15
- package/dist/utils/plugin-options.d.ts +4 -0
- package/dist/utils/plugin-options.js +8 -0
- package/dist/utils/project.d.ts +0 -6
- package/dist/utils/project.js +2 -8
- package/dist/utils/public-routes.js +2 -2
- package/dist/utils/react-version.js +1 -1
- package/dist/utils/redirect-digest.d.ts +9 -0
- package/dist/utils/redirect-digest.js +25 -0
- package/dist/utils/vinext-root.js +1 -1
- package/dist/utils/vite-version.d.ts +5 -2
- package/dist/utils/vite-version.js +43 -17
- package/package.json +4 -3
- /package/dist/build/google-fonts/{fallback-metrics-data.js → fallback-metrics-data.json.js} +0 -0
- /package/dist/build/google-fonts/{font-data.js → font-data.json.js} +0 -0
- /package/dist/{node_modules/.pnpm/process-ancestry@0.1.0/node_modules → deps/.pnpm/process-ancestry@0.1.0/deps}/process-ancestry/dist/index.js +0 -0
|
@@ -49,7 +49,7 @@ var ServerActionRedirectError = class extends Error {
|
|
|
49
49
|
const redirectUrl = new URL(target.href, window.location.href);
|
|
50
50
|
const redirectHref = redirectUrl.pathname + redirectUrl.search + redirectUrl.hash;
|
|
51
51
|
const redirectType = target.type === "push" ? "push" : "replace";
|
|
52
|
-
this.digest = `NEXT_REDIRECT;${redirectType};${
|
|
52
|
+
this.digest = `NEXT_REDIRECT;${redirectType};${redirectHref};${target.status};`;
|
|
53
53
|
}
|
|
54
54
|
};
|
|
55
55
|
async function invokeClientServerAction(id, args, actionInitiation, deps) {
|
|
@@ -6,12 +6,12 @@ import { AppElementsWire } from "./app-elements-wire.js";
|
|
|
6
6
|
import { getMountedSlotIds, getMountedSlotIdsHeader } from "./app-elements.js";
|
|
7
7
|
import { createRscRequestHeaders } from "./app-rsc-cache-busting.js";
|
|
8
8
|
import { createCacheEntryReuseProof } from "./cache-proof.js";
|
|
9
|
-
import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
|
|
10
9
|
import { createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, isHistoryStateBfcacheVersionCurrent, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent } from "./app-history-state.js";
|
|
11
10
|
import { NavigationTraceReasonCodes, createNavigationLifecycleTraceFields, createNavigationTrace } from "./navigation-trace.js";
|
|
12
11
|
import { verifyOperationTokenForCommit } from "./operation-token.js";
|
|
13
12
|
import { navigationPlanner, resolveDefaultOrUnmatchedSlotPersistenceForLayouts } from "./navigation-planner.js";
|
|
14
13
|
import { createSnapshotPathAndSearch } from "../shims/navigation.js";
|
|
14
|
+
import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
|
|
15
15
|
//#region src/server/app-browser-state.ts
|
|
16
16
|
const COMMITTED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN = { origin: "committed-cache" };
|
|
17
17
|
const FRESH_APP_NAVIGATION_PAYLOAD_ORIGIN = { origin: "fresh" };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
|
|
2
2
|
import "./app-elements.js";
|
|
3
3
|
import { mergeElements } from "../shims/slot.js";
|
|
4
|
-
import { preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
|
|
5
4
|
import { NavigationTraceReasonCodes, NavigationTraceTransactionCodes, createNavigationTrace, prependNavigationTraceEntry } from "./navigation-trace.js";
|
|
5
|
+
import { preserveBfcacheIdsForMergedElements } from "./app-bfcache-identity.js";
|
|
6
6
|
import { createPendingNavigationCommit, resolvePendingNavigationCommitDispositionDecision } from "./app-browser-state.js";
|
|
7
7
|
//#region src/server/app-browser-visible-commit.ts
|
|
8
8
|
const approvedVisibleCommitBrand = Symbol("ApprovedVisibleCommit");
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ArtifactCompatibilityEnvelope } from "./artifact-compatibility.js";
|
|
2
2
|
import { CacheEntryReuseProof, RenderObservation } from "./cache-proof.js";
|
|
3
3
|
import { ClientReuseManifestSkipDisposition } from "./client-reuse-manifest.js";
|
|
4
|
+
import { compareStrings } from "../utils/compare.js";
|
|
4
5
|
import { ReactNode } from "react";
|
|
5
6
|
|
|
6
7
|
//#region src/server/app-elements-wire.d.ts
|
|
@@ -42,7 +43,7 @@ type AppElementsInterception = Readonly<{
|
|
|
42
43
|
targetMatchedUrl: string;
|
|
43
44
|
targetRouteId: string;
|
|
44
45
|
}>;
|
|
45
|
-
declare const compareAppElementsSlotIds:
|
|
46
|
+
declare const compareAppElementsSlotIds: typeof compareStrings;
|
|
46
47
|
declare function normalizeAppElementsSlotBindings(slotBindings: readonly AppElementsSlotBinding[], options?: {
|
|
47
48
|
layoutIds?: readonly string[];
|
|
48
49
|
}): readonly AppElementsSlotBinding[];
|
|
@@ -32,6 +32,7 @@ type AppFallbackRendererOptions<TModule extends AppPageModule = AppPageModule> =
|
|
|
32
32
|
clearRequestContext: () => void;
|
|
33
33
|
createRscOnErrorHandler: (request: Request, pathname: string, routePath: string) => AppPageBoundaryOnError;
|
|
34
34
|
fontProviders: AppFallbackRendererFontProviders;
|
|
35
|
+
getAndClearPendingCookies?: () => string[];
|
|
35
36
|
getNavigationContext: () => NavigationContext | null;
|
|
36
37
|
globalErrorModule?: TModule | null; /** Whether experimental.globalNotFound is enabled for route-miss 404s. */
|
|
37
38
|
globalNotFoundEnabled?: boolean;
|
|
@@ -57,6 +58,13 @@ type AppFallbackRendererOptions<TModule extends AppPageModule = AppPageModule> =
|
|
|
57
58
|
metadataRoutes: MetadataFileRoute[]; /** Configured next.config `basePath`, threaded into file-based metadata href emission. */
|
|
58
59
|
basePath?: string; /** Configured next.config `trailingSlash`, threaded into canonical URL rendering. */
|
|
59
60
|
trailingSlash?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Serialized next.config `htmlLimitedBots` regexp source. Used to decide, per
|
|
63
|
+
* request user-agent, whether a `generateMetadata()` redirect thrown from a
|
|
64
|
+
* fallback boundary should stream (200) or block (307) — matching the
|
|
65
|
+
* matched-page dispatch path via `shouldServeStreamingMetadata`.
|
|
66
|
+
*/
|
|
67
|
+
htmlLimitedBots?: string;
|
|
60
68
|
resolveChildSegments: (routeSegments: readonly string[], treePosition: number, params: AppPageParams) => string[];
|
|
61
69
|
rootBoundaries: AppFallbackRendererRootBoundaries<TModule>;
|
|
62
70
|
rscRenderer: (element: ReactNode | AppElements, options: {
|
|
@@ -2,13 +2,14 @@ import { renderAppPageErrorBoundary, renderAppPageHttpAccessFallback } from "./a
|
|
|
2
2
|
import { DEFAULT_GLOBAL_ERROR_MODULE } from "./default-global-error-module.js";
|
|
3
3
|
import { DEFAULT_GLOBAL_NOT_FOUND_MODULE } from "./default-global-not-found-module.js";
|
|
4
4
|
import { DEFAULT_NOT_FOUND_MODULE } from "./default-not-found-module.js";
|
|
5
|
+
import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
|
|
5
6
|
//#region src/server/app-fallback-renderer.ts
|
|
6
7
|
const EMPTY_MW_CTX = {
|
|
7
8
|
headers: null,
|
|
8
9
|
status: null
|
|
9
10
|
};
|
|
10
11
|
function createAppFallbackRenderer(options) {
|
|
11
|
-
const { applyFileBasedMetadata, basePath = "", clearRequestContext, createRscOnErrorHandler: buildRscOnErrorHandler, fontProviders, getNavigationContext, globalErrorModule, globalNotFoundEnabled = false, loadGlobalNotFoundModule, makeThenableParams, metadataRoutes, resolveChildSegments, rootBoundaries, rscRenderer, sanitizer, ssrLoader, trailingSlash } = options;
|
|
12
|
+
const { applyFileBasedMetadata, basePath = "", htmlLimitedBots, clearRequestContext, createRscOnErrorHandler: buildRscOnErrorHandler, fontProviders, getAndClearPendingCookies, getNavigationContext, globalErrorModule, globalNotFoundEnabled = false, loadGlobalNotFoundModule, makeThenableParams, metadataRoutes, resolveChildSegments, rootBoundaries, rscRenderer, sanitizer, ssrLoader, trailingSlash } = options;
|
|
12
13
|
const { rootForbiddenModule, rootLayouts, rootNotFoundModule, rootUnauthorizedModule } = rootBoundaries;
|
|
13
14
|
const effectiveGlobalErrorModule = globalErrorModule ?? DEFAULT_GLOBAL_ERROR_MODULE;
|
|
14
15
|
const effectiveRootNotFoundModule = rootNotFoundModule ?? DEFAULT_NOT_FOUND_MODULE;
|
|
@@ -20,12 +21,15 @@ function createAppFallbackRenderer(options) {
|
|
|
20
21
|
}
|
|
21
22
|
return {
|
|
22
23
|
async renderHttpAccessFallback(route, statusCode, isRscRequest, request, opts, scriptNonce, middlewareContext, callContext) {
|
|
24
|
+
const serveStreamingMetadata = shouldServeStreamingMetadata(request.headers.get("user-agent") ?? "", htmlLimitedBots);
|
|
23
25
|
const useGlobalNotFound = statusCode === 404 && globalNotFoundEnabled && !route && !opts?.boundaryComponent;
|
|
24
26
|
if (useGlobalNotFound && loadGlobalNotFoundModule) {
|
|
25
27
|
const globalNotFoundModule = await resolveGlobalNotFoundModule();
|
|
26
28
|
const globalNotFoundComponent = globalNotFoundModule?.default ?? null;
|
|
27
29
|
if (globalNotFoundComponent) return renderAppPageHttpAccessFallback({
|
|
28
30
|
applyFileBasedMetadata,
|
|
31
|
+
basePath,
|
|
32
|
+
trailingSlash,
|
|
29
33
|
boundaryComponent: globalNotFoundComponent,
|
|
30
34
|
boundaryModule: globalNotFoundModule ?? null,
|
|
31
35
|
buildFontLinkHeader: fontProviders.buildFontLinkHeader,
|
|
@@ -36,6 +40,7 @@ function createAppFallbackRenderer(options) {
|
|
|
36
40
|
getFontLinks: fontProviders.getFontLinks,
|
|
37
41
|
getFontPreloads: fontProviders.getFontPreloads,
|
|
38
42
|
getFontStyles: fontProviders.getFontStyles,
|
|
43
|
+
getAndClearPendingCookies,
|
|
39
44
|
getNavigationContext,
|
|
40
45
|
globalErrorModule: effectiveGlobalErrorModule,
|
|
41
46
|
isEdgeRuntime: callContext?.isEdgeRuntime,
|
|
@@ -46,6 +51,7 @@ function createAppFallbackRenderer(options) {
|
|
|
46
51
|
matchedParams: opts?.matchedParams ?? {},
|
|
47
52
|
middlewareContext: middlewareContext ?? EMPTY_MW_CTX,
|
|
48
53
|
metadataRoutes,
|
|
54
|
+
request,
|
|
49
55
|
requestUrl: request.url,
|
|
50
56
|
resolveChildSegments,
|
|
51
57
|
rootForbiddenModule: null,
|
|
@@ -55,6 +61,7 @@ function createAppFallbackRenderer(options) {
|
|
|
55
61
|
route: null,
|
|
56
62
|
renderToReadableStream: rscRenderer,
|
|
57
63
|
scriptNonce,
|
|
64
|
+
serveStreamingMetadata,
|
|
58
65
|
skipLayoutWrapping: true,
|
|
59
66
|
statusCode
|
|
60
67
|
});
|
|
@@ -74,6 +81,7 @@ function createAppFallbackRenderer(options) {
|
|
|
74
81
|
getFontLinks: fontProviders.getFontLinks,
|
|
75
82
|
getFontPreloads: fontProviders.getFontPreloads,
|
|
76
83
|
getFontStyles: fontProviders.getFontStyles,
|
|
84
|
+
getAndClearPendingCookies,
|
|
77
85
|
getNavigationContext,
|
|
78
86
|
globalErrorModule: effectiveGlobalErrorModule,
|
|
79
87
|
isEdgeRuntime: callContext?.isEdgeRuntime,
|
|
@@ -84,6 +92,7 @@ function createAppFallbackRenderer(options) {
|
|
|
84
92
|
matchedParams: opts?.matchedParams ?? route?.params ?? {},
|
|
85
93
|
middlewareContext: middlewareContext ?? EMPTY_MW_CTX,
|
|
86
94
|
metadataRoutes,
|
|
95
|
+
request,
|
|
87
96
|
requestUrl: request.url,
|
|
88
97
|
resolveChildSegments,
|
|
89
98
|
rootForbiddenModule,
|
|
@@ -93,6 +102,7 @@ function createAppFallbackRenderer(options) {
|
|
|
93
102
|
route: useGlobalNotFound ? null : route,
|
|
94
103
|
renderToReadableStream: rscRenderer,
|
|
95
104
|
scriptNonce,
|
|
105
|
+
serveStreamingMetadata,
|
|
96
106
|
skipLayoutWrapping: useGlobalNotFound,
|
|
97
107
|
sourcePageSegments: callContext?.sourcePageSegments,
|
|
98
108
|
statusCode
|
|
@@ -116,6 +126,7 @@ function createAppFallbackRenderer(options) {
|
|
|
116
126
|
getFontLinks: fontProviders.getFontLinks,
|
|
117
127
|
getFontPreloads: fontProviders.getFontPreloads,
|
|
118
128
|
getFontStyles: fontProviders.getFontStyles,
|
|
129
|
+
getAndClearPendingCookies,
|
|
119
130
|
getNavigationContext,
|
|
120
131
|
globalErrorModule: effectiveGlobalErrorModule,
|
|
121
132
|
isEdgeRuntime: callContext?.isEdgeRuntime,
|
|
@@ -125,6 +136,7 @@ function createAppFallbackRenderer(options) {
|
|
|
125
136
|
matchedParams: matchedParams ?? route?.params ?? {},
|
|
126
137
|
middlewareContext: middlewareContext ?? EMPTY_MW_CTX,
|
|
127
138
|
metadataRoutes,
|
|
139
|
+
request,
|
|
128
140
|
requestUrl: request.url,
|
|
129
141
|
resolveChildSegments,
|
|
130
142
|
rootLayouts,
|
|
@@ -32,6 +32,7 @@ type AppPageBoundaryRenderCommonOptions<TModule extends AppPageModule = AppPageM
|
|
|
32
32
|
buildFontLinkHeader: (preloads: readonly AppPageFontPreload[] | null | undefined) => string;
|
|
33
33
|
clearRequestContext: () => void;
|
|
34
34
|
createRscOnErrorHandler: (pathname: string, routePath: string) => AppPageBoundaryOnError;
|
|
35
|
+
getAndClearPendingCookies?: () => string[];
|
|
35
36
|
getFontLinks: () => string[];
|
|
36
37
|
getFontPreloads: () => AppPageFontPreload[];
|
|
37
38
|
getFontStyles: () => string[];
|
|
@@ -42,12 +43,24 @@ type AppPageBoundaryRenderCommonOptions<TModule extends AppPageModule = AppPageM
|
|
|
42
43
|
loadSsrHandler: () => Promise<AppPageSsrHandler>;
|
|
43
44
|
makeThenableParams: (params: AppPageParams) => unknown;
|
|
44
45
|
middlewareContext: AppPageMiddlewareContext;
|
|
45
|
-
metadataRoutes: MetadataFileRoute[];
|
|
46
|
+
metadataRoutes: MetadataFileRoute[];
|
|
47
|
+
/**
|
|
48
|
+
* Whether metadata-origin redirects should ride as a 200 streaming response
|
|
49
|
+
* (HTML meta-refresh / RSC flight) rather than a blocking 307. Mirrors the
|
|
50
|
+
* matched-page dispatch decision `shouldServeStreamingMetadata(userAgent,
|
|
51
|
+
* htmlLimitedBots)`: html-limited bots get the blocking 307, so a
|
|
52
|
+
* `generateMetadata()` redirect thrown from a fallback boundary matches the
|
|
53
|
+
* matched-page path instead of always defaulting to streaming. Undefined
|
|
54
|
+
* means "not computed" and is treated as streaming, preserving prior behavior
|
|
55
|
+
* for callers that never hit metadata redirects.
|
|
56
|
+
*/
|
|
57
|
+
serveStreamingMetadata?: boolean; /** Configured next.config `basePath`, threaded into file-based metadata href emission. */
|
|
46
58
|
basePath?: string; /** Configured next.config `trailingSlash`, threaded into canonical URL rendering. */
|
|
47
59
|
trailingSlash?: boolean;
|
|
48
60
|
renderToReadableStream: (element: ReactNode | AppElements, options: {
|
|
49
61
|
onError: AppPageBoundaryOnError;
|
|
50
62
|
}) => ReadableStream<Uint8Array>;
|
|
63
|
+
request: Request;
|
|
51
64
|
requestUrl: string;
|
|
52
65
|
resolveChildSegments: (routeSegments: readonly string[], treePosition: number, params: AppPageParams) => string[];
|
|
53
66
|
rootLayouts: readonly (TModule | null | undefined)[];
|
|
@@ -6,12 +6,13 @@ import { isNavigationSignalError } from "../utils/navigation-signal.js";
|
|
|
6
6
|
import { ErrorBoundary, GlobalErrorBoundary, SerializedErrorBoundary } from "../shims/error-boundary.js";
|
|
7
7
|
import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
|
|
8
8
|
import { MetadataHead, ViewportHead } from "../shims/metadata.js";
|
|
9
|
-
import {
|
|
9
|
+
import { buildRscRedirectFlightStream } from "./app-rsc-redirect-flight.js";
|
|
10
|
+
import { bufferAppPageBinaryStream, buildAppPageSpecialErrorResponse, resolveAppPageSpecialError } from "./app-page-execution.js";
|
|
10
11
|
import { resolveAppPageHead } from "./app-page-head.js";
|
|
11
12
|
import { createAppPageLayoutEntries, createAppPageSourcePage } from "./app-page-route-wiring.js";
|
|
12
13
|
import { buildClientHookErrorMessage } from "../shims/client-hook-error.js";
|
|
13
14
|
import { renderAppPageBoundaryResponse, resolveAppPageErrorBoundary, resolveAppPageHttpAccessBoundaryModule, wrapAppPageBoundaryElement } from "./app-page-boundary.js";
|
|
14
|
-
import { createAppPageFontData, renderAppPageHtmlResponse } from "./app-page-stream.js";
|
|
15
|
+
import { createAppPageFontData, createAppPageRscErrorTracker, renderAppPageHtmlResponse } from "./app-page-stream.js";
|
|
15
16
|
import { Fragment, createElement } from "react";
|
|
16
17
|
//#region src/server/app-page-boundary-render.ts
|
|
17
18
|
const DEFAULT_GLOBAL_ERROR_COMPONENT = DefaultGlobalError;
|
|
@@ -89,52 +90,95 @@ function createAppPageBoundaryRscPayload(options) {
|
|
|
89
90
|
[routeId]: options.element
|
|
90
91
|
};
|
|
91
92
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
getLinks: options.getFontLinks,
|
|
99
|
-
getPreloads: options.getFontPreloads,
|
|
100
|
-
getStyles: options.getFontStyles
|
|
101
|
-
});
|
|
102
|
-
const ssrHandler = await options.loadSsrHandler();
|
|
103
|
-
return renderAppPageHtmlResponse({
|
|
104
|
-
clearRequestContext: options.clearRequestContext,
|
|
105
|
-
fontData,
|
|
106
|
-
fontLinkHeader: options.buildFontLinkHeader(fontData.preloads),
|
|
107
|
-
isEdgeRuntime: options.isEdgeRuntime,
|
|
108
|
-
middlewareHeaders: options.middlewareContext.headers,
|
|
109
|
-
navigationContext: options.getNavigationContext() ?? {
|
|
110
|
-
pathname,
|
|
111
|
-
searchParams: requestUrl.searchParams,
|
|
112
|
-
params: options.navigationParams ?? options.route?.params ?? {}
|
|
113
|
-
},
|
|
114
|
-
rscStream,
|
|
115
|
-
scriptNonce: options.scriptNonce,
|
|
116
|
-
ssrHandler,
|
|
117
|
-
status: responseStatus,
|
|
118
|
-
initialDevServerError: options.initialDevServerError
|
|
119
|
-
});
|
|
120
|
-
},
|
|
121
|
-
createRscOnErrorHandler() {
|
|
122
|
-
return options.createRscOnErrorHandler(pathname, options.routePattern ?? pathname);
|
|
123
|
-
},
|
|
124
|
-
element: createAppPageBoundaryRscPayload({
|
|
125
|
-
element: options.element,
|
|
126
|
-
layoutModules: options.layoutModules,
|
|
127
|
-
pathname,
|
|
128
|
-
route: options.route,
|
|
129
|
-
sourcePageSegments: options.sourcePageSegments
|
|
93
|
+
function renderBoundarySpecialErrorResponse(options, specialError) {
|
|
94
|
+
return buildAppPageSpecialErrorResponse({
|
|
95
|
+
basePath: options.basePath,
|
|
96
|
+
buildRscRedirectFlightStream: (rscOptions) => buildRscRedirectFlightStream({
|
|
97
|
+
renderToReadableStream: options.renderToReadableStream,
|
|
98
|
+
digest: rscOptions.digest
|
|
130
99
|
}),
|
|
100
|
+
clearRequestContext: options.clearRequestContext,
|
|
101
|
+
getAndClearPendingCookies: options.getAndClearPendingCookies,
|
|
131
102
|
isEdgeRuntime: options.isEdgeRuntime,
|
|
132
103
|
isRscRequest: options.isRscRequest,
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
104
|
+
middlewareContext: options.middlewareContext,
|
|
105
|
+
serveStreamingMetadata: options.serveStreamingMetadata,
|
|
106
|
+
request: options.request,
|
|
107
|
+
specialError
|
|
136
108
|
});
|
|
137
109
|
}
|
|
110
|
+
async function renderAppPageBoundaryElementResponse(options) {
|
|
111
|
+
const requestUrl = new URL(options.requestUrl);
|
|
112
|
+
const pathname = requestUrl.pathname;
|
|
113
|
+
const payload = createAppPageBoundaryRscPayload({
|
|
114
|
+
element: options.element,
|
|
115
|
+
layoutModules: options.layoutModules,
|
|
116
|
+
pathname,
|
|
117
|
+
route: options.route,
|
|
118
|
+
sourcePageSegments: options.sourcePageSegments
|
|
119
|
+
});
|
|
120
|
+
const rscErrorTracker = createAppPageRscErrorTracker(options.createRscOnErrorHandler(pathname, options.routePattern ?? pathname));
|
|
121
|
+
const resolveCapturedSpecialError = (error) => resolveAppPageSpecialError(error) ?? resolveAppPageSpecialError(rscErrorTracker.getCapturedSpecialError());
|
|
122
|
+
const renderSpecialErrorResponse = (specialError) => renderBoundarySpecialErrorResponse(options, specialError);
|
|
123
|
+
const handleSpecialErrors = options.handleSpecialErrors === true;
|
|
124
|
+
let response;
|
|
125
|
+
try {
|
|
126
|
+
response = await renderAppPageBoundaryResponse({
|
|
127
|
+
async createHtmlResponse(rscStream, responseStatus) {
|
|
128
|
+
const fontData = createAppPageFontData({
|
|
129
|
+
getLinks: options.getFontLinks,
|
|
130
|
+
getPreloads: options.getFontPreloads,
|
|
131
|
+
getStyles: options.getFontStyles
|
|
132
|
+
});
|
|
133
|
+
const ssrHandler = await options.loadSsrHandler();
|
|
134
|
+
return renderAppPageHtmlResponse({
|
|
135
|
+
clearRequestContext: options.clearRequestContext,
|
|
136
|
+
fontData,
|
|
137
|
+
fontLinkHeader: options.buildFontLinkHeader(fontData.preloads),
|
|
138
|
+
isEdgeRuntime: options.isEdgeRuntime,
|
|
139
|
+
middlewareHeaders: options.middlewareContext.headers,
|
|
140
|
+
navigationContext: options.getNavigationContext() ?? {
|
|
141
|
+
pathname,
|
|
142
|
+
searchParams: requestUrl.searchParams,
|
|
143
|
+
params: options.navigationParams ?? options.route?.params ?? {}
|
|
144
|
+
},
|
|
145
|
+
rscStream,
|
|
146
|
+
scriptNonce: options.scriptNonce,
|
|
147
|
+
ssrHandler,
|
|
148
|
+
status: responseStatus,
|
|
149
|
+
initialDevServerError: options.initialDevServerError
|
|
150
|
+
});
|
|
151
|
+
},
|
|
152
|
+
createRscOnErrorHandler() {
|
|
153
|
+
return rscErrorTracker.onRenderError;
|
|
154
|
+
},
|
|
155
|
+
element: payload,
|
|
156
|
+
isEdgeRuntime: options.isEdgeRuntime,
|
|
157
|
+
isRscRequest: options.isRscRequest,
|
|
158
|
+
middlewareHeaders: options.middlewareContext.headers,
|
|
159
|
+
renderToReadableStream: options.renderToReadableStream,
|
|
160
|
+
status: options.status
|
|
161
|
+
});
|
|
162
|
+
} catch (error) {
|
|
163
|
+
const specialError = handleSpecialErrors ? resolveCapturedSpecialError(error) : null;
|
|
164
|
+
if (specialError !== null) return renderSpecialErrorResponse(specialError);
|
|
165
|
+
throw error;
|
|
166
|
+
}
|
|
167
|
+
if (!handleSpecialErrors) return response;
|
|
168
|
+
if (options.isRscRequest && response.body) {
|
|
169
|
+
const bufferedStream = await bufferAppPageBinaryStream(response.body);
|
|
170
|
+
response = new Response(bufferedStream, {
|
|
171
|
+
status: response.status,
|
|
172
|
+
headers: response.headers
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
const specialError = resolveCapturedSpecialError();
|
|
176
|
+
if (!specialError) return response;
|
|
177
|
+
if (response.body) try {
|
|
178
|
+
await response.body.cancel();
|
|
179
|
+
} catch {}
|
|
180
|
+
return renderSpecialErrorResponse(specialError);
|
|
181
|
+
}
|
|
138
182
|
async function renderAppPageHttpAccessFallback(options) {
|
|
139
183
|
const resolvedBoundaryModule = resolveAppPageHttpAccessBoundaryModule({
|
|
140
184
|
rootForbiddenModule: options.rootForbiddenModule,
|
|
@@ -151,17 +195,25 @@ async function renderAppPageHttpAccessFallback(options) {
|
|
|
151
195
|
const layoutModules = options.layoutModules ?? options.route?.layouts ?? options.rootLayouts;
|
|
152
196
|
const pathname = new URL(options.requestUrl).pathname;
|
|
153
197
|
const routeSegments = resolveHttpAccessFallbackHeadRouteSegments(options.route, layoutModules);
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
198
|
+
let head;
|
|
199
|
+
try {
|
|
200
|
+
head = await resolveAppPageHead({
|
|
201
|
+
applyFileBasedMetadata: options.applyFileBasedMetadata,
|
|
202
|
+
basePath: options.basePath ?? "",
|
|
203
|
+
layoutModules,
|
|
204
|
+
layoutTreePositions: resolveHttpAccessFallbackHeadLayoutTreePositions(options.route, layoutModules),
|
|
205
|
+
metadataRoutes: options.metadataRoutes,
|
|
206
|
+
pageModule: boundaryModule,
|
|
207
|
+
params: options.matchedParams,
|
|
208
|
+
routePath: options.route?.pattern ?? pathname,
|
|
209
|
+
routeSegments
|
|
210
|
+
});
|
|
211
|
+
} catch (error) {
|
|
212
|
+
const specialError = resolveAppPageSpecialError(error);
|
|
213
|
+
if (specialError) return renderBoundarySpecialErrorResponse(options, specialError);
|
|
214
|
+
throw error;
|
|
215
|
+
}
|
|
216
|
+
const { metadata, viewport } = head;
|
|
165
217
|
const headElements = [createElement("meta", {
|
|
166
218
|
charSet: "utf-8",
|
|
167
219
|
key: "charset"
|
|
@@ -197,6 +249,7 @@ async function renderAppPageHttpAccessFallback(options) {
|
|
|
197
249
|
return renderAppPageBoundaryElementResponse({
|
|
198
250
|
...options,
|
|
199
251
|
element,
|
|
252
|
+
handleSpecialErrors: true,
|
|
200
253
|
layoutModules: skipLayoutWrapping ? [] : layoutModules,
|
|
201
254
|
navigationParams: options.matchedParams,
|
|
202
255
|
route: skipLayoutWrapping ? null : options.route,
|
|
@@ -112,6 +112,7 @@ type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
|
|
|
112
112
|
buildPageElement: (route: TRoute, params: AppPageParams, opts: AppPageDispatchInterceptOptions | undefined, searchParams: URLSearchParams, layoutParamAccess?: AppLayoutParamAccessTracker, options?: {
|
|
113
113
|
observeMetadataSearchParamsAccess?: boolean;
|
|
114
114
|
observePageSearchParamsAccess?: boolean;
|
|
115
|
+
serveStreamingMetadata?: boolean;
|
|
115
116
|
}) => Promise<AppPageElement>;
|
|
116
117
|
clientReuseManifest?: ClientReuseManifestParseResult;
|
|
117
118
|
cleanPathname: string;
|
|
@@ -10,18 +10,18 @@ import { ensureFetchPatch, getCollectedFetchTags, peekDynamicFetchObservations,
|
|
|
10
10
|
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader } from "./app-rsc-cache-busting.js";
|
|
11
11
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
12
12
|
import "./app-page-response.js";
|
|
13
|
+
import { buildRscRedirectFlightStream } from "./app-rsc-redirect-flight.js";
|
|
13
14
|
import { buildAppPageSpecialErrorResponse, probeAppPageThrownError, resolveAppPageSpecialError } from "./app-page-execution.js";
|
|
14
15
|
import { createAppPageTreePath } from "./app-page-route-wiring.js";
|
|
15
16
|
import { consumeAppPageRenderObservationState, discardAppPageRenderState } from "./app-page-render-observation.js";
|
|
16
17
|
import { resolveAppPageParentHttpAccessBoundary, resolveAppPageParentHttpAccessBoundaryModule } from "./app-page-boundary.js";
|
|
18
|
+
import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
|
|
17
19
|
import { createAppLayoutParamAccessTracker, isAppLayoutObservationUnsafeForStaticReuse } from "./app-layout-param-observation.js";
|
|
18
20
|
import { buildAppPageTags } from "./implicit-tags.js";
|
|
19
21
|
import { resolveAppPageMethodResponse } from "./app-page-method.js";
|
|
20
|
-
import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
|
|
21
22
|
import { resolveAppPageNavigationParams } from "./app-page-element-builder.js";
|
|
22
23
|
import { buildAppPageElement, resolveAppPageIntercept, resolveAppPageInterceptionRerenderTarget, validateAppPageDynamicParams } from "./app-page-request.js";
|
|
23
24
|
import { renderAppPageLifecycle } from "./app-page-render.js";
|
|
24
|
-
import React from "react";
|
|
25
25
|
//#region src/server/app-page-dispatch.ts
|
|
26
26
|
function resolveAppPageRouteBoundaryModule(route, statusCode) {
|
|
27
27
|
if (statusCode === 403) return route.forbidden ?? null;
|
|
@@ -160,6 +160,9 @@ async function dispatchAppPageInner(options) {
|
|
|
160
160
|
const isForceStatic = dynamicConfig === "force-static";
|
|
161
161
|
const isDynamicError = dynamicConfig === "error";
|
|
162
162
|
const isForceDynamic = dynamicConfig === "force-dynamic";
|
|
163
|
+
const isPrerender = process.env.VINEXT_PRERENDER === "1";
|
|
164
|
+
const serveStreamingMetadata = shouldServeStreamingMetadata(options.request.headers.get("user-agent") ?? "", options.htmlLimitedBots);
|
|
165
|
+
const placeGeneratedMetadataInBody = (!isPrerender || options.pprFallbackShell !== void 0) && serveStreamingMetadata;
|
|
163
166
|
const isPrefetchDynamicShell = options.renderMode === APP_RSC_RENDER_MODE_PREFETCH_DYNAMIC_SHELL;
|
|
164
167
|
const isDraftMode = isDraftModeRequest(options.request, options.draftModeSecret);
|
|
165
168
|
const requestHeadersContext = getHeadersContext();
|
|
@@ -269,7 +272,8 @@ async function dispatchAppPageInner(options) {
|
|
|
269
272
|
const { renderAppPageCacheArtifacts } = await import("./app-page-cache-render.js");
|
|
270
273
|
const revalidatedElement = await options.buildPageElement(revalidationTarget.route, revalidationTarget.params, revalidationTarget.interceptOpts, new URLSearchParams(), void 0, {
|
|
271
274
|
observeMetadataSearchParamsAccess: revalidationDynamicConfig !== "force-static",
|
|
272
|
-
observePageSearchParamsAccess: revalidationDynamicConfig !== "force-static"
|
|
275
|
+
observePageSearchParamsAccess: revalidationDynamicConfig !== "force-static",
|
|
276
|
+
serveStreamingMetadata: false
|
|
273
277
|
});
|
|
274
278
|
const revalidatedOnError = options.createRscOnErrorHandler(options.cleanPathname, revalidationTarget.route.pattern);
|
|
275
279
|
const rendered = await renderAppPageCacheArtifacts({
|
|
@@ -345,7 +349,8 @@ async function dispatchAppPageInner(options) {
|
|
|
345
349
|
setCurrentForceDynamicFetchDefault(sourceDynamicConfig === "force-dynamic");
|
|
346
350
|
return options.buildPageElement(interceptRoute, interceptParams, interceptOpts, interceptSearchParams, interceptLayoutParamAccess, {
|
|
347
351
|
observeMetadataSearchParamsAccess: sourceDynamicConfig !== "force-static",
|
|
348
|
-
observePageSearchParamsAccess: sourceDynamicConfig !== "force-static"
|
|
352
|
+
observePageSearchParamsAccess: sourceDynamicConfig !== "force-static",
|
|
353
|
+
serveStreamingMetadata: placeGeneratedMetadataInBody
|
|
349
354
|
});
|
|
350
355
|
},
|
|
351
356
|
cleanPathname: options.cleanPathname,
|
|
@@ -397,7 +402,8 @@ async function dispatchAppPageInner(options) {
|
|
|
397
402
|
if (options.actionFailed) throw options.actionError;
|
|
398
403
|
return options.buildPageElement(route, options.params, interceptResult.interceptOpts, pageSearchParams, layoutParamAccess, {
|
|
399
404
|
observeMetadataSearchParamsAccess: !isForceStatic,
|
|
400
|
-
observePageSearchParamsAccess: !isForceStatic
|
|
405
|
+
observePageSearchParamsAccess: !isForceStatic,
|
|
406
|
+
serveStreamingMetadata: placeGeneratedMetadataInBody
|
|
401
407
|
});
|
|
402
408
|
},
|
|
403
409
|
async probePageSpecialError() {
|
|
@@ -413,7 +419,7 @@ async function dispatchAppPageInner(options) {
|
|
|
413
419
|
return options.renderErrorBoundaryPage(buildError);
|
|
414
420
|
},
|
|
415
421
|
renderSpecialError(specialError) {
|
|
416
|
-
return renderPageSpecialError(options, specialError);
|
|
422
|
+
return renderPageSpecialError(options, specialError, serveStreamingMetadata);
|
|
417
423
|
},
|
|
418
424
|
resolveSpecialError: resolveAppPageSpecialError
|
|
419
425
|
});
|
|
@@ -441,7 +447,6 @@ async function dispatchAppPageInner(options) {
|
|
|
441
447
|
const activeFallbackShellState = options.pprRuntime?.getState() ?? null;
|
|
442
448
|
const pprFallbackShellSignal = activeFallbackShellState?.abortController.signal;
|
|
443
449
|
const pprFallbackShellReactSignal = activeFallbackShellState?.reactAbortController.signal;
|
|
444
|
-
const isPrerender = process.env.VINEXT_PRERENDER === "1";
|
|
445
450
|
const isSpeculativePrerender = isPrerender && options.request.headers.get("x-vinext-prerender-speculative") === "1";
|
|
446
451
|
return renderAppPageLifecycle({
|
|
447
452
|
basePath: options.basePath,
|
|
@@ -550,10 +555,10 @@ async function dispatchAppPageInner(options) {
|
|
|
550
555
|
return options.renderErrorBoundaryPage(renderError, errorOrigin);
|
|
551
556
|
},
|
|
552
557
|
renderLayoutSpecialError(specialError, layoutIndex) {
|
|
553
|
-
return renderLayoutSpecialError(options, specialError, layoutIndex);
|
|
558
|
+
return renderLayoutSpecialError(options, specialError, layoutIndex, serveStreamingMetadata);
|
|
554
559
|
},
|
|
555
560
|
renderPageSpecialError(specialError) {
|
|
556
|
-
return renderPageSpecialError(options, specialError);
|
|
561
|
+
return renderPageSpecialError(options, specialError, serveStreamingMetadata);
|
|
557
562
|
},
|
|
558
563
|
renderToReadableStream: options.renderToReadableStream,
|
|
559
564
|
hasCustomGlobalError: options.hasCustomGlobalError,
|
|
@@ -568,35 +573,16 @@ async function dispatchAppPageInner(options) {
|
|
|
568
573
|
}
|
|
569
574
|
});
|
|
570
575
|
}
|
|
571
|
-
|
|
572
|
-
* Builds an RSC flight payload that encodes a redirect as a React error chunk.
|
|
573
|
-
* We render a tiny element that immediately throws an `Error` whose `digest`
|
|
574
|
-
* is the canonical `NEXT_REDIRECT;...` string. `renderToReadableStream`'s
|
|
575
|
-
* `onError` returns that digest, react-server-dom-webpack serializes the
|
|
576
|
-
* error into the stream, and the client's `RedirectErrorBoundary` decodes it
|
|
577
|
-
* via `getURLFromRedirectError` / `getRedirectTypeFromError`.
|
|
578
|
-
*
|
|
579
|
-
* The thrown error's digest matches Next.js's well-known router error format,
|
|
580
|
-
* so neither vinext's RSC error handler nor Next.js's reporter logs it as a
|
|
581
|
-
* "real" server error. Mirrors `app-render.tsx generateDynamicFlightRenderResult`
|
|
582
|
-
* where a redirect thrown during RSC rendering propagates through
|
|
583
|
-
* `renderToFlightStream`'s `onError` callback into the flight payload.
|
|
584
|
-
*/
|
|
585
|
-
function buildRscRedirectFlightStream(options, digest) {
|
|
586
|
-
const throwingElement = React.createElement(function NextRedirectFlightThrower() {
|
|
587
|
-
const err = /* @__PURE__ */ new Error("NEXT_REDIRECT");
|
|
588
|
-
err.digest = digest;
|
|
589
|
-
throw err;
|
|
590
|
-
});
|
|
591
|
-
return options.renderToReadableStream(throwingElement, { onError: () => digest });
|
|
592
|
-
}
|
|
593
|
-
async function renderLayoutSpecialError(options, specialError, layoutIndex) {
|
|
576
|
+
async function renderLayoutSpecialError(options, specialError, layoutIndex, serveStreamingMetadata) {
|
|
594
577
|
return buildAppPageSpecialErrorResponse({
|
|
595
578
|
basePath: options.basePath,
|
|
596
|
-
buildRscRedirectFlightStream: (rscOptions) => buildRscRedirectFlightStream(
|
|
579
|
+
buildRscRedirectFlightStream: (rscOptions) => buildRscRedirectFlightStream({
|
|
580
|
+
renderToReadableStream: options.renderToReadableStream,
|
|
581
|
+
digest: rscOptions.digest
|
|
582
|
+
}),
|
|
597
583
|
clearRequestContext: options.clearRequestContext,
|
|
598
584
|
getAndClearPendingCookies,
|
|
599
|
-
serveStreamingMetadata
|
|
585
|
+
serveStreamingMetadata,
|
|
600
586
|
isEdgeRuntime: options.isEdgeRuntime,
|
|
601
587
|
isRscRequest: options.isRscRequest,
|
|
602
588
|
middlewareContext: options.middlewareContext,
|
|
@@ -625,13 +611,16 @@ async function renderLayoutSpecialError(options, specialError, layoutIndex) {
|
|
|
625
611
|
specialError
|
|
626
612
|
});
|
|
627
613
|
}
|
|
628
|
-
async function renderPageSpecialError(options, specialError) {
|
|
614
|
+
async function renderPageSpecialError(options, specialError, serveStreamingMetadata) {
|
|
629
615
|
return buildAppPageSpecialErrorResponse({
|
|
630
616
|
basePath: options.basePath,
|
|
631
|
-
buildRscRedirectFlightStream: (rscOptions) => buildRscRedirectFlightStream(
|
|
617
|
+
buildRscRedirectFlightStream: (rscOptions) => buildRscRedirectFlightStream({
|
|
618
|
+
renderToReadableStream: options.renderToReadableStream,
|
|
619
|
+
digest: rscOptions.digest
|
|
620
|
+
}),
|
|
632
621
|
clearRequestContext: options.clearRequestContext,
|
|
633
622
|
getAndClearPendingCookies,
|
|
634
|
-
serveStreamingMetadata
|
|
623
|
+
serveStreamingMetadata,
|
|
635
624
|
isEdgeRuntime: options.isEdgeRuntime,
|
|
636
625
|
isRscRequest: options.isRscRequest,
|
|
637
626
|
middlewareContext: options.middlewareContext,
|
|
@@ -37,7 +37,8 @@ type AppPagePageRequest<TModule extends AppPageModule = AppPageModule> = {
|
|
|
37
37
|
mountedSlotsHeader: string | null; /** Semantic RSC payload mode for this page render. */
|
|
38
38
|
renderMode?: AppRscRenderMode; /** Observe page `searchParams` access for cache-safety classification. */
|
|
39
39
|
observePageSearchParamsAccess?: boolean; /** Observe page metadata `searchParams` access for cache-safety classification. */
|
|
40
|
-
observeMetadataSearchParamsAccess?: boolean;
|
|
40
|
+
observeMetadataSearchParamsAccess?: boolean; /** Whether generated metadata may stream into the response body. */
|
|
41
|
+
serveStreamingMetadata?: boolean;
|
|
41
42
|
};
|
|
42
43
|
type BuildPageElementsOptions<TModule extends AppPageModule = AppPageModule, TErrorModule extends AppPageErrorModule = AppPageErrorModule> = {
|
|
43
44
|
applyFileBasedMetadata?: ApplyAppPageFileBasedMetadata;
|
|
@@ -9,8 +9,8 @@ import { resolveActiveParallelRouteHeadInputs, resolveAppPageHead } from "./app-
|
|
|
9
9
|
import { createAppPageSearchParamsObserver, makeObservedAppPageSearchParamsThenable } from "./app-page-search-params-observation.js";
|
|
10
10
|
import { buildAppPageElements, createAppPageSourcePage, createAppPageTreePath } from "./app-page-route-wiring.js";
|
|
11
11
|
import { DEFAULT_GLOBAL_ERROR_MODULE } from "./default-global-error-module.js";
|
|
12
|
-
import "./app-rsc-route-matching.js";
|
|
13
12
|
import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
|
|
13
|
+
import "./app-rsc-route-matching.js";
|
|
14
14
|
import { createElement } from "react";
|
|
15
15
|
//#region src/server/app-page-element-builder.ts
|
|
16
16
|
function resolveInterceptLayoutParams(branchSegments, layoutSegments, params) {
|
|
@@ -41,7 +41,7 @@ function isReactOwnedPageComponent(component) {
|
|
|
41
41
|
async function buildPageElements(options) {
|
|
42
42
|
const { route, params, routePath, displayPathname = routePath, pageRequest, globalErrorModule, rootNotFoundModule, rootForbiddenModule, rootUnauthorizedModule, metadataRoutes } = options;
|
|
43
43
|
const slotParamOverrides = resolveSlotParamOverrides(route, routePath);
|
|
44
|
-
const { opts, searchParams, isRscRequest, mountedSlotsHeader, renderMode = APP_RSC_RENDER_MODE_NAVIGATION, observeMetadataSearchParamsAccess = false, observePageSearchParamsAccess = false } = pageRequest;
|
|
44
|
+
const { opts, searchParams, isRscRequest, mountedSlotsHeader, renderMode = APP_RSC_RENDER_MODE_NAVIGATION, observeMetadataSearchParamsAccess = false, observePageSearchParamsAccess = false, serveStreamingMetadata } = pageRequest;
|
|
45
45
|
const pageModule = route.page;
|
|
46
46
|
const isSiblingIntercept = opts?.interceptSlotKey === "__vinext_page_intercept" && !!opts?.interceptPage;
|
|
47
47
|
const effectivePageModule = isSiblingIntercept ? opts.interceptPage : pageModule;
|
|
@@ -127,7 +127,7 @@ async function buildPageElements(options) {
|
|
|
127
127
|
const pageSearchParamsThenable = searchParams ? makeThenableParams(pageSearchParams) : void 0;
|
|
128
128
|
const mountedSlotIds = mountedSlotsHeader ? new Set(mountedSlotsHeader.split(" ")) : null;
|
|
129
129
|
const slotOverrides = buildSlotOverrides(route, params, routePath, opts);
|
|
130
|
-
const metadataPlacement = hasDynamicMetadata && shouldServeStreamingMetadata(pageRequest.request.headers.get("user-agent") ?? "", options.htmlLimitedBots) ? "body" : "head";
|
|
130
|
+
const metadataPlacement = hasDynamicMetadata && (serveStreamingMetadata ?? shouldServeStreamingMetadata(pageRequest.request.headers.get("user-agent") ?? "", options.htmlLimitedBots)) ? "body" : "head";
|
|
131
131
|
let siblingInterceptElement = isSiblingIntercept && EffectivePageComponent ? createPageElement(EffectivePageComponent, pageProps) : null;
|
|
132
132
|
if (isSiblingIntercept && siblingInterceptElement !== null && opts?.interceptLayouts?.length) for (let i = opts.interceptLayouts.length - 1; i >= 0; i--) {
|
|
133
133
|
const LayoutComponent = opts.interceptLayouts[i]?.default;
|
|
@@ -6,6 +6,7 @@ type AppPageSpecialError = {
|
|
|
6
6
|
kind: "redirect";
|
|
7
7
|
location: string;
|
|
8
8
|
statusCode: number;
|
|
9
|
+
type?: "push" | "replace";
|
|
9
10
|
fromMetadata?: boolean;
|
|
10
11
|
} | {
|
|
11
12
|
kind: "http-access-fallback";
|
|
@@ -132,7 +133,8 @@ declare function probeAppPageLayouts(options: ProbeAppPageLayoutsOptions): Promi
|
|
|
132
133
|
declare function probeAppPageComponent(options: ProbeAppPageComponentOptions): Promise<Response | null>;
|
|
133
134
|
declare function probeAppPageThrownError(options: ProbeAppPageThrownErrorOptions): Promise<unknown>;
|
|
134
135
|
declare function readAppPageBinaryStream(stream: ReadableStream<Uint8Array>): Promise<ArrayBuffer>;
|
|
136
|
+
declare function bufferAppPageBinaryStream(stream: ReadableStream<Uint8Array>): Promise<ReadableStream<Uint8Array>>;
|
|
135
137
|
declare function teeAppPageRscStreamForCapture(stream: ReadableStream<Uint8Array>, shouldCapture: boolean): AppPageRscStreamCapture;
|
|
136
138
|
declare function buildAppPageFontLinkHeader(preloads: readonly AppPageFontPreload[] | null | undefined): string;
|
|
137
139
|
//#endregion
|
|
138
|
-
export { AppPageFontPreload, AppPageSpecialError, LayoutClassificationOptions, type LayoutFlags, buildAppPageFontLinkHeader, buildAppPageSpecialErrorResponse, probeAppPageComponent, probeAppPageLayouts, probeAppPageThrownError, readAppPageBinaryStream, resolveAppPageSpecialError, tagAppPageMetadataError, teeAppPageRscStreamForCapture };
|
|
140
|
+
export { AppPageFontPreload, AppPageSpecialError, LayoutClassificationOptions, type LayoutFlags, bufferAppPageBinaryStream, buildAppPageFontLinkHeader, buildAppPageSpecialErrorResponse, probeAppPageComponent, probeAppPageLayouts, probeAppPageThrownError, readAppPageBinaryStream, resolveAppPageSpecialError, tagAppPageMetadataError, teeAppPageRscStreamForCapture };
|