vinext 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -10
- package/dist/build/app-page-static-eligibility.d.ts +15 -0
- package/dist/build/app-page-static-eligibility.js +82 -0
- package/dist/build/client-build-config.d.ts +10 -0
- package/dist/build/client-build-config.js +18 -2
- package/dist/build/pages-client-assets-module.d.ts +8 -0
- package/dist/build/pages-client-assets-module.js +21 -1
- package/dist/build/prerender-paths.js +8 -81
- package/dist/build/prerender.js +33 -8
- package/dist/build/run-prerender.js +1 -1
- package/dist/build/server-manifest.d.ts +7 -0
- package/dist/build/server-manifest.js +11 -1
- package/dist/build/ssr-manifest.d.ts +2 -0
- package/dist/build/ssr-manifest.js +6 -2
- package/dist/cache/cache-adapters-virtual.d.ts +7 -1
- package/dist/cache/cache-adapters-virtual.js +3 -3
- package/dist/check.js +7 -6
- package/dist/cli.js +2 -1
- package/dist/client/client-redirect-matcher.d.ts +14 -0
- package/dist/client/client-redirect-matcher.js +37 -0
- package/dist/client/client-redirects.d.ts +27 -0
- package/dist/client/client-redirects.js +28 -0
- package/dist/client/client-rewrites.d.ts +2 -1
- package/dist/client/client-rewrites.js +1 -1
- package/dist/client/navigation-runtime.d.ts +11 -0
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/config-matchers.d.ts +26 -11
- package/dist/config/config-matchers.js +81 -82
- package/dist/config/destination-params.d.ts +47 -0
- package/dist/config/destination-params.js +116 -0
- package/dist/config/next-config.d.ts +14 -0
- package/dist/config/next-config.js +21 -3
- package/dist/entries/app-rsc-entry.d.ts +6 -0
- package/dist/entries/app-rsc-entry.js +84 -49
- package/dist/entries/pages-client-entry.js +3 -1
- package/dist/entries/pages-server-entry.js +13 -37
- package/dist/index.d.ts +7 -2
- package/dist/index.js +193 -73
- package/dist/init-cloudflare.d.ts +9 -0
- package/dist/init-cloudflare.js +107 -31
- package/dist/init-platform.d.ts +4 -0
- package/dist/init-platform.js +27 -2
- package/dist/init.d.ts +1 -0
- package/dist/init.js +67 -3
- package/dist/plugins/ast-scope.d.ts +7 -0
- package/dist/plugins/ast-scope.js +59 -3
- package/dist/plugins/cache-flight-codec.d.ts +19 -0
- package/dist/plugins/cache-flight-codec.js +68 -0
- package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
- package/dist/plugins/commonjs-esm-facade.js +80 -0
- package/dist/plugins/dynamic-preload-metadata.d.ts +1 -1
- package/dist/plugins/dynamic-preload-metadata.js +9 -8
- package/dist/plugins/fonts.d.ts +8 -11
- package/dist/plugins/fonts.js +71 -34
- package/dist/plugins/ignore-dynamic-requests.d.ts +1 -1
- package/dist/plugins/ignore-dynamic-requests.js +3 -4
- package/dist/plugins/middleware-server-only.d.ts +5 -4
- package/dist/plugins/middleware-server-only.js +8 -5
- package/dist/plugins/pages-node-externals.js +1 -1
- package/dist/plugins/rsc-scan-glob-imports.d.ts +19 -0
- package/dist/plugins/rsc-scan-glob-imports.js +50 -0
- package/dist/plugins/strip-server-exports.js +262 -98
- package/dist/plugins/transform-result.d.ts +9 -5
- package/dist/plugins/transitive-externals.js +1 -1
- package/dist/plugins/typeof-window.d.ts +2 -2
- package/dist/plugins/use-cache-callable.js +8 -2
- package/dist/plugins/worker-server-only-imports.d.ts +20 -0
- package/dist/plugins/worker-server-only-imports.js +31 -0
- package/dist/plugins/worker-use-server.d.ts +25 -0
- package/dist/plugins/worker-use-server.js +129 -0
- package/dist/routing/file-matcher.d.ts +1 -0
- package/dist/routing/file-matcher.js +1 -1
- package/dist/server/api-handler.d.ts +1 -0
- package/dist/server/api-handler.js +19 -8
- package/dist/server/app-browser-action-result.d.ts +1 -1
- package/dist/server/app-browser-action-result.js +9 -2
- package/dist/server/app-browser-entry.js +11 -7
- package/dist/server/app-browser-history-controller.d.ts +2 -0
- package/dist/server/app-browser-history-controller.js +8 -0
- package/dist/server/app-browser-interception-context.js +26 -2
- package/dist/server/app-browser-navigation-controller.d.ts +7 -1
- package/dist/server/app-browser-navigation-controller.js +94 -11
- package/dist/server/app-browser-server-action-client.js +1 -1
- package/dist/server/app-fallback-renderer.d.ts +2 -0
- package/dist/server/app-fallback-renderer.js +1 -0
- package/dist/server/app-history-state.d.ts +3 -0
- package/dist/server/app-history-state.js +7 -0
- package/dist/server/app-middleware.d.ts +11 -0
- package/dist/server/app-middleware.js +19 -3
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-boundary-render.d.ts +5 -0
- package/dist/server/app-page-boundary-render.js +6 -4
- package/dist/server/app-page-cache-finalizer.d.ts +11 -0
- package/dist/server/app-page-cache-finalizer.js +41 -7
- package/dist/server/app-page-cache-render.d.ts +18 -0
- package/dist/server/app-page-cache-render.js +63 -43
- package/dist/server/app-page-cache.d.ts +6 -1
- package/dist/server/app-page-cache.js +28 -8
- package/dist/server/app-page-dispatch.d.ts +12 -2
- package/dist/server/app-page-dispatch.js +51 -33
- package/dist/server/app-page-element-builder.d.ts +7 -0
- package/dist/server/app-page-element-builder.js +27 -42
- package/dist/server/app-page-execution.d.ts +15 -12
- package/dist/server/app-page-execution.js +30 -40
- package/dist/server/app-page-head.d.ts +5 -0
- package/dist/server/app-page-head.js +9 -3
- package/dist/server/app-page-ppr-runtime.js +1 -1
- package/dist/server/app-page-probe.d.ts +0 -109
- package/dist/server/app-page-probe.js +3 -136
- package/dist/server/app-page-render-identity.d.ts +0 -1
- package/dist/server/app-page-render-identity.js +1 -1
- package/dist/server/app-page-render-observation.js +3 -3
- package/dist/server/app-page-render.d.ts +13 -5
- package/dist/server/app-page-render.js +219 -119
- package/dist/server/app-page-request.d.ts +0 -1
- package/dist/server/app-page-request.js +54 -17
- package/dist/server/app-page-response.d.ts +4 -3
- package/dist/server/app-page-response.js +4 -3
- package/dist/server/app-page-route-wiring.d.ts +17 -5
- package/dist/server/app-page-route-wiring.js +57 -35
- package/dist/server/app-page-rsc-render-status.d.ts +48 -0
- package/dist/server/app-page-rsc-render-status.js +54 -0
- package/dist/server/app-page-stream.d.ts +15 -8
- package/dist/server/app-page-stream.js +6 -0
- package/dist/server/app-pages-bridge.d.ts +1 -1
- package/dist/server/app-pages-bridge.js +2 -3
- package/dist/server/app-prerender-endpoints.js +9 -6
- package/dist/server/app-request-stage-dispatch.js +7 -3
- package/dist/server/app-request-stage-independent-entry.js +29 -9
- package/dist/server/app-response-header-provenance.d.ts +2 -0
- package/dist/server/app-response-header-provenance.js +10 -4
- package/dist/server/app-response-stage-entry.js +10 -2
- package/dist/server/app-route-handler-cache.d.ts +1 -0
- package/dist/server/app-route-handler-cache.js +1 -0
- package/dist/server/app-route-handler-dispatch.d.ts +1 -0
- package/dist/server/app-route-handler-dispatch.js +6 -3
- package/dist/server/app-route-handler-execution.d.ts +1 -0
- package/dist/server/app-route-handler-execution.js +1 -0
- package/dist/server/app-route-handler-runtime.d.ts +4 -1
- package/dist/server/app-route-handler-runtime.js +45 -24
- package/dist/server/app-router-entry.js +27 -8
- package/dist/server/app-rsc-cache-busting.js +1 -1
- package/dist/server/app-rsc-errors.js +20 -16
- package/dist/server/app-rsc-handler.d.ts +11 -0
- package/dist/server/app-rsc-handler.js +291 -125
- package/dist/server/app-rsc-request-normalization.d.ts +3 -1
- package/dist/server/app-rsc-request-normalization.js +4 -2
- package/dist/server/app-rsc-response-stage.d.ts +1 -1
- package/dist/server/app-rsc-response-stage.js +10 -6
- package/dist/server/app-rsc-route-matching.d.ts +9 -1
- package/dist/server/app-rsc-route-matching.js +36 -19
- package/dist/server/app-segment-config.d.ts +2 -1
- package/dist/server/app-server-action-execution.d.ts +2 -1
- package/dist/server/app-server-action-execution.js +62 -23
- package/dist/server/app-ssr-entry.d.ts +3 -2
- package/dist/server/app-ssr-entry.js +8 -5
- package/dist/server/app-ssr-stream.d.ts +6 -1
- package/dist/server/app-ssr-stream.js +34 -15
- package/dist/server/app-worker-stages.d.ts +7 -2
- package/dist/server/app-worker-stages.js +4 -4
- package/dist/server/cacheability-request.js +11 -7
- package/dist/server/client-build-files.d.ts +16 -0
- package/dist/server/client-build-files.js +36 -0
- package/dist/server/client-reuse-manifest.js +1 -1
- package/dist/server/config-headers.js +2 -0
- package/dist/server/dev-server.js +50 -29
- package/dist/server/dev-stack-sourcemap.js +18 -23
- package/dist/server/document-initial-head.d.ts +0 -11
- package/dist/server/document-initial-head.js +1 -1
- package/dist/server/forwarded-middleware-context.d.ts +5 -0
- package/dist/server/forwarded-middleware-context.js +22 -0
- package/dist/server/headers.d.ts +18 -1
- package/dist/server/headers.js +19 -2
- package/dist/server/http-conditional.d.ts +11 -0
- package/dist/server/http-conditional.js +10 -1
- package/dist/server/http-error-responses.d.ts +1 -1
- package/dist/server/image-optimization.d.ts +54 -0
- package/dist/server/image-optimization.js +118 -9
- package/dist/server/isr-cache.d.ts +10 -0
- package/dist/server/isr-cache.js +43 -8
- package/dist/server/metadata-route-response.js +9 -8
- package/dist/server/middleware-matcher-pattern.js +8 -4
- package/dist/server/middleware-matcher.d.ts +2 -0
- package/dist/server/middleware-matcher.js +23 -2
- package/dist/server/middleware-response-headers.js +2 -0
- package/dist/server/middleware-runtime.d.ts +13 -0
- package/dist/server/middleware-runtime.js +33 -20
- package/dist/server/middleware.d.ts +1 -1
- package/dist/server/middleware.js +3 -1
- package/dist/server/multi-stage.d.ts +19 -0
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/node-response-signal.d.ts +16 -0
- package/dist/server/node-response-signal.js +26 -0
- package/dist/server/normalize-path.d.ts +0 -13
- package/dist/server/normalize-path.js +1 -34
- package/dist/server/open-redirect.d.ts +47 -0
- package/dist/server/open-redirect.js +74 -1
- package/dist/server/pages-api-route.d.ts +3 -2
- package/dist/server/pages-api-route.js +4 -3
- package/dist/server/pages-cache-tag.d.ts +12 -0
- package/dist/server/pages-cache-tag.js +19 -0
- package/dist/server/pages-client-assets.d.ts +2 -0
- package/dist/server/pages-data-route.d.ts +10 -0
- package/dist/server/pages-data-route.js +19 -2
- package/dist/server/pages-document-asset-props.d.ts +5 -1
- package/dist/server/pages-document-asset-props.js +13 -5
- package/dist/server/pages-document-splice.d.ts +19 -0
- package/dist/server/pages-document-splice.js +55 -0
- package/dist/server/pages-i18n.d.ts +12 -1
- package/dist/server/pages-i18n.js +18 -4
- package/dist/server/pages-node-compat.d.ts +16 -5
- package/dist/server/pages-node-compat.js +20 -12
- package/dist/server/pages-page-data.d.ts +32 -24
- package/dist/server/pages-page-data.js +50 -120
- package/dist/server/pages-page-handler.d.ts +0 -6
- package/dist/server/pages-page-handler.js +209 -130
- package/dist/server/pages-page-response.d.ts +12 -6
- package/dist/server/pages-page-response.js +41 -34
- package/dist/server/pages-request-pipeline.d.ts +10 -2
- package/dist/server/pages-request-pipeline.js +37 -18
- package/dist/server/pages-request-stage-entry.d.ts +6 -0
- package/dist/server/pages-request-stage-entry.js +79 -16
- package/dist/server/pages-response-stage-entry.js +4 -0
- package/dist/server/pages-revalidate.js +1 -1
- package/dist/server/pages-router-entry.js +4 -3
- package/dist/server/prerender-manifest.d.ts +3 -3
- package/dist/server/prerender-manifest.js +4 -3
- package/dist/server/prerender-work-unit-setup.js +4 -0
- package/dist/server/prod-server.d.ts +20 -7
- package/dist/server/prod-server.js +343 -129
- package/dist/server/proper-error.d.ts +4 -0
- package/dist/server/proper-error.js +31 -0
- package/dist/server/request-pipeline.d.ts +24 -9
- package/dist/server/request-pipeline.js +24 -9
- package/dist/server/response-compression.d.ts +43 -0
- package/dist/server/response-compression.js +111 -0
- package/dist/server/revalidation-request.d.ts +1 -0
- package/dist/server/revalidation-request.js +1 -1
- package/dist/server/rsc-stream-hints.js +31 -2
- package/dist/server/seed-cache.d.ts +1 -0
- package/dist/server/seed-cache.js +15 -11
- package/dist/server/server-reference-loader.d.ts +4 -0
- package/dist/server/server-reference-loader.js +29 -0
- package/dist/server/socket-error-backstop.d.ts +23 -1
- package/dist/server/socket-error-backstop.js +69 -17
- package/dist/server/static-file-signal.d.ts +15 -4
- package/dist/server/static-file-signal.js +46 -12
- package/dist/server/worker-image-optimization.d.ts +34 -0
- package/dist/server/worker-image-optimization.js +86 -0
- package/dist/server/worker-stages.d.ts +1 -1
- package/dist/server/worker-stages.js +2 -2
- package/dist/server/worker-utils.d.ts +8 -3
- package/dist/server/worker-utils.js +12 -7
- package/dist/shims/app-router-scroll.js +4 -1
- package/dist/shims/app-router-tree-context.d.ts +5 -0
- package/dist/shims/app-router-tree-context.js +27 -0
- package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
- package/dist/shims/cache-adapter-instantiate.js +118 -0
- package/dist/shims/cache-callable-runtime.d.ts +6 -42
- package/dist/shims/cache-callable-runtime.js +65 -174
- package/dist/shims/cache-flight-arguments.d.ts +22 -0
- package/dist/shims/cache-flight-arguments.js +56 -0
- package/dist/shims/cache-handler.js +1 -9
- package/dist/shims/cache-request-state.d.ts +15 -0
- package/dist/shims/cache-request-state.js +31 -8
- package/dist/shims/cache-runtime.d.ts +12 -20
- package/dist/shims/cache-runtime.js +166 -225
- package/dist/shims/cache.d.ts +4 -4
- package/dist/shims/cache.js +44 -16
- package/dist/shims/cacheability-classification.d.ts +7 -0
- package/dist/shims/cdn-cache.d.ts +8 -0
- package/dist/shims/cdn-cache.js +17 -1
- package/dist/shims/disable-smooth-scroll.d.ts +3 -0
- package/dist/shims/disable-smooth-scroll.js +36 -0
- package/dist/shims/document-placeholders.d.ts +19 -0
- package/dist/shims/document-placeholders.js +45 -0
- package/dist/shims/document.js +21 -5
- package/dist/shims/dynamic-preload-chunks.d.ts +1 -0
- package/dist/shims/dynamic-preload-chunks.js +13 -9
- package/dist/shims/dynamic.d.ts +1 -1
- package/dist/shims/dynamic.js +60 -8
- package/dist/shims/error-boundary-navigation.d.ts +7 -0
- package/dist/shims/error-boundary-navigation.js +19 -1
- package/dist/shims/error-boundary.d.ts +10 -10
- package/dist/shims/error-boundary.js +26 -7
- package/dist/shims/fetch-cache-state.d.ts +66 -0
- package/dist/shims/fetch-cache-state.js +92 -0
- package/dist/shims/fetch-cache.d.ts +3 -61
- package/dist/shims/fetch-cache.js +161 -108
- package/dist/shims/form.js +1 -1
- package/dist/shims/head.d.ts +10 -6
- package/dist/shims/head.js +15 -13
- package/dist/shims/headers.d.ts +13 -0
- package/dist/shims/headers.js +47 -4
- package/dist/shims/image.js +2 -1
- package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
- package/dist/shims/internal/app-page-props-cache-key.js +24 -15
- package/dist/shims/internal/headers-state.d.ts +0 -1
- package/dist/shims/internal/work-store-scope.d.ts +5 -0
- package/dist/shims/internal/work-store-scope.js +24 -0
- package/dist/shims/metadata.js +3 -3
- package/dist/shims/navigation-errors.d.ts +6 -0
- package/dist/shims/navigation-errors.js +11 -1
- package/dist/shims/navigation.d.ts +7 -0
- package/dist/shims/navigation.js +45 -9
- package/dist/shims/request-context.d.ts +11 -0
- package/dist/shims/request-state-types.d.ts +2 -1
- package/dist/shims/router.js +12 -20
- package/dist/shims/server.d.ts +16 -0
- package/dist/shims/server.js +24 -4
- package/dist/shims/thenable-params.d.ts +4 -0
- package/dist/shims/thenable-params.js +25 -3
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/shims/url-utils.d.ts +2 -0
- package/dist/shims/url-utils.js +3 -1
- package/dist/utils/client-runtime-metadata.js +1 -1
- package/dist/utils/hash.d.ts +7 -0
- package/dist/utils/hash.js +11 -1
- package/dist/utils/mdx-scan.d.ts +5 -0
- package/dist/utils/mdx-scan.js +8 -1
- package/dist/utils/package-name.d.ts +6 -0
- package/dist/utils/package-name.js +12 -1
- package/dist/utils/plugin-rsc-version.d.ts +4 -0
- package/dist/utils/plugin-rsc-version.js +15 -0
- package/dist/utils/prerender-output-paths.js +15 -4
- package/dist/utils/public-file-path.d.ts +10 -2
- package/dist/utils/public-file-path.js +13 -9
- package/dist/utils/public-routes.js +2 -2
- package/dist/utils/react-version.d.ts +3 -0
- package/dist/utils/react-version.js +1 -1
- package/dist/utils/regex-safety.d.ts +10 -0
- package/dist/utils/regex-safety.js +70 -18
- package/package.json +9 -5
|
@@ -18,9 +18,10 @@ function applyDynamicStaleTimeHeader(headers, dynamicStaleTimeSeconds) {
|
|
|
18
18
|
if (dynamicStaleTimeSeconds !== void 0 && Number.isInteger(dynamicStaleTimeSeconds) && dynamicStaleTimeSeconds >= 0) headers.set(VINEXT_DYNAMIC_STALE_TIME_HEADER, String(dynamicStaleTimeSeconds));
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
* Only ever set from a *completed* render's cacheLife (cache replay
|
|
22
|
-
* prerender seed) — `use cache` scopes
|
|
23
|
-
* so a streaming response can never
|
|
21
|
+
* Only ever set from a *completed* render's cacheLife (cache replay,
|
|
22
|
+
* prerender seed, or a layout probe's early redirect) — `use cache` scopes
|
|
23
|
+
* keep resolving after headers commit, so a streaming response can never
|
|
24
|
+
* carry it.
|
|
24
25
|
*/
|
|
25
26
|
function applyClientStaleTimeHeader(headers, staleTimeSeconds) {
|
|
26
27
|
if (staleTimeSeconds === void 0) return;
|
|
@@ -140,14 +140,15 @@ type BuildAppPageRouteElementOptions<TModule extends AppPageModule = AppPageModu
|
|
|
140
140
|
makeThenableParams: MakeThenableParams;
|
|
141
141
|
matchedParams: AppPageParams;
|
|
142
142
|
metadataPlacement?: "body" | "head";
|
|
143
|
-
|
|
143
|
+
/**
|
|
144
|
+
* Starts resolving the page's head. The head, its streamed body tags and its
|
|
145
|
+
* error outlet each call this while Flight renders them, so callers memoise
|
|
146
|
+
* it per render with React's `cache()`. Without it the head has no metadata.
|
|
147
|
+
*/
|
|
148
|
+
resolveHead?: (() => AppPageRouteHead) | null;
|
|
144
149
|
resolvedMetadataPathname?: string;
|
|
145
|
-
resolvedViewport: Viewport;
|
|
146
150
|
scriptNonce?: string;
|
|
147
|
-
streamingMetadata?: Promise<Metadata | null> | null;
|
|
148
|
-
streamingMetadataOutlet?: Promise<unknown> | null;
|
|
149
151
|
streamingMetadataOutletSuspended?: boolean;
|
|
150
|
-
streamingMetadataTags?: Promise<Metadata | null> | null;
|
|
151
152
|
trailingSlash?: boolean;
|
|
152
153
|
rootForbiddenModule?: TModule | null;
|
|
153
154
|
rootNotFoundModule?: TModule | null;
|
|
@@ -158,6 +159,17 @@ type BuildAppPageRouteElementOptions<TModule extends AppPageModule = AppPageModu
|
|
|
158
159
|
searchParams?: unknown;
|
|
159
160
|
slotOverrides?: Readonly<Record<string, AppPageSlotOverride<TModule>>> | null;
|
|
160
161
|
};
|
|
162
|
+
/**
|
|
163
|
+
* A page's head as Flight renders it. `metadata` and `viewport` hold the tags
|
|
164
|
+
* to render, including the HTTP access fallback's when resolution failed, so
|
|
165
|
+
* they never reject. `outlet` rejects with the resolution error so the route's
|
|
166
|
+
* boundaries can handle it.
|
|
167
|
+
*/
|
|
168
|
+
export type AppPageRouteHead = {
|
|
169
|
+
metadata: Promise<Metadata | null>;
|
|
170
|
+
outlet: Promise<null>;
|
|
171
|
+
viewport: Promise<Viewport>;
|
|
172
|
+
};
|
|
161
173
|
type MakeThenableParams = (params: AppPageParams, observer?: ThenableParamsObserver) => unknown;
|
|
162
174
|
type BuildAppPageElementsOptions<TModule extends AppPageModule = AppPageModule, TErrorModule extends AppPageErrorModule = AppPageErrorModule> = BuildAppPageRouteElementOptions<TModule, TErrorModule> & {
|
|
163
175
|
interception?: AppElementsInterception | null;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { fnv1a64 } from "../utils/hash.js";
|
|
2
1
|
import { APP_RSC_RENDER_MODE_PREFETCH_EMPTY, APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL } from "./app-rsc-render-mode.js";
|
|
2
|
+
import { fnv1a64 } from "../utils/hash.js";
|
|
3
|
+
import { createInlineScriptTag, escapeHtmlAttr } from "./html.js";
|
|
3
4
|
import { createAppRenderDependency, registerAppElementRenderDependencies, renderAfterAppDependencies, renderAppComponentWithDependencyBarrier } from "./app-render-dependency.js";
|
|
4
5
|
import { APP_LAYOUT_IDS_KEY, APP_ROOT_LAYOUT_KEY, APP_STATIC_SIBLINGS_KEY, AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
|
|
5
6
|
import { APP_PREFETCH_LOADING_SHELL_MARKER_KEY } from "./app-elements.js";
|
|
6
|
-
import { createInlineScriptTag, escapeHtmlAttr } from "./html.js";
|
|
7
7
|
import DefaultGlobalError from "../shims/default-global-error.js";
|
|
8
8
|
import { ErrorBoundary, ForbiddenBoundary, GlobalErrorBoundary, NotFoundBoundary, RedirectBoundary, UnauthorizedBoundary } from "../shims/error-boundary.js";
|
|
9
9
|
import { AppRouterScrollTarget } from "../shims/app-router-scroll.js";
|
|
10
10
|
import DefaultNotFound from "../shims/default-not-found.js";
|
|
11
11
|
import { LayoutSegmentProvider } from "../shims/layout-segment-context.js";
|
|
12
|
+
import { withUseCacheLayoutMarker } from "../shims/internal/app-page-props-cache-key.js";
|
|
12
13
|
import { MetadataHead, ViewportHead, renderMetadataToHtml } from "../shims/metadata.js";
|
|
13
14
|
import { BfcacheSegmentBoundary, Children as Children$1, ParallelSlot, Slot } from "../shims/slot.js";
|
|
14
15
|
import { StreamedIconsInsertion } from "../shims/streamed-icons.js";
|
|
@@ -64,7 +65,7 @@ function probeAppPageLayoutWithTracking(options) {
|
|
|
64
65
|
});
|
|
65
66
|
const layoutParams = resolveAppPageSegmentParams(options.route.routeSegments, treePosition, options.matchedParams);
|
|
66
67
|
return probeReactServerSubtree(/* @__PURE__ */ jsx(LayoutComponent, {
|
|
67
|
-
params: options.makeThenableParams(layoutParams, options.layoutParamAccess?.createThenableParamsObserver(layoutId)),
|
|
68
|
+
...withUseCacheLayoutMarker(LayoutComponent, { params: options.makeThenableParams(layoutParams, options.layoutParamAccess?.createThenableParamsObserver(layoutId)) }),
|
|
68
69
|
children: APP_PAGE_LAYOUT_PROBE_CHILD
|
|
69
70
|
}));
|
|
70
71
|
};
|
|
@@ -179,6 +180,14 @@ function createAppPageSlotLoadingEntries(slot, override) {
|
|
|
179
180
|
}
|
|
180
181
|
return entries;
|
|
181
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* Only an override that replaces the slot's page or layouts changes its tree.
|
|
185
|
+
* A params-only override, as built for an inherited slot with its own param
|
|
186
|
+
* names, keeps the slot's nested loading boundaries.
|
|
187
|
+
*/
|
|
188
|
+
function getAppPageSlotTreeOverride(override) {
|
|
189
|
+
return override?.pageModule != null || override?.layoutModules !== void 0 ? override ?? null : null;
|
|
190
|
+
}
|
|
182
191
|
function getFirstLoadingEntry(entries) {
|
|
183
192
|
return entries.reduce((first, entry) => first === null || entry.treePosition < first.treePosition ? entry : first, null);
|
|
184
193
|
}
|
|
@@ -242,17 +251,24 @@ function createAppPageSlotBindings(route, layoutEntries, resolveSlotOverride, op
|
|
|
242
251
|
}
|
|
243
252
|
return normalizeAppElementsSlotBindings(bindings, { layoutIds: layoutEntries.map((entry) => entry.id) });
|
|
244
253
|
}
|
|
245
|
-
function createAppPageRouteHead(
|
|
246
|
-
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
254
|
+
function createAppPageRouteHead(resolveHead, pathname, metadataPlacement, trailingSlash) {
|
|
255
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("meta", { charSet: "utf-8" }), resolveHead ? /* @__PURE__ */ jsx(AppPageHead, {
|
|
256
|
+
metadataPlacement,
|
|
257
|
+
pathname,
|
|
258
|
+
resolveHead,
|
|
259
|
+
trailingSlash
|
|
260
|
+
}) : /* @__PURE__ */ jsx(ViewportHead, { viewport: {} })] });
|
|
261
|
+
}
|
|
262
|
+
async function AppPageHead(props) {
|
|
263
|
+
const head = props.resolveHead();
|
|
264
|
+
const [metadata, viewport] = await Promise.all([props.metadataPlacement === "head" ? head.metadata : null, head.viewport]);
|
|
265
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [metadata ? /* @__PURE__ */ jsx(MetadataHead, {
|
|
266
|
+
metadata,
|
|
267
|
+
pathname: props.pathname,
|
|
268
|
+
trailingSlash: props.trailingSlash
|
|
269
|
+
}) : null, /* @__PURE__ */ jsx(ViewportHead, { viewport })] });
|
|
255
270
|
}
|
|
271
|
+
AppPageHead.displayName = "Vinext.Head";
|
|
256
272
|
function hasStreamedIcons(metadata) {
|
|
257
273
|
const icons = metadata.icons;
|
|
258
274
|
if (!icons) return false;
|
|
@@ -273,7 +289,7 @@ function createAppPageRouteBodyMetadata(metadata, pathname, metadataPlacement, t
|
|
|
273
289
|
streamedIconKey
|
|
274
290
|
});
|
|
275
291
|
const metadataKey = streamedIconKey ? createStreamedIconKey(pathname, renderedMetadataHtml) : "";
|
|
276
|
-
const parserInsertedMetadataHtml = (streamedIconKey ? renderedMetadataHtml.replaceAll(`<link data-vinext-streamed-icon="${STREAMED_ICON_KEY_PLACEHOLDER}:`, `<link data-vinext-streamed-icon="${escapeHtmlAttr(metadataKey)}:`) : renderedMetadataHtml) + createInlineScriptTag(REINSERT_STREAMED_ICONS_SCRIPT, scriptNonce);
|
|
292
|
+
const parserInsertedMetadataHtml = (streamedIconKey ? renderedMetadataHtml.replaceAll(`<link data-vinext-streamed-icon="${STREAMED_ICON_KEY_PLACEHOLDER}:`, () => `<link data-vinext-streamed-icon="${escapeHtmlAttr(metadataKey)}:`) : renderedMetadataHtml) + createInlineScriptTag(REINSERT_STREAMED_ICONS_SCRIPT, scriptNonce);
|
|
277
293
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
|
|
278
294
|
hidden: true,
|
|
279
295
|
suppressHydrationWarning: true,
|
|
@@ -282,15 +298,14 @@ function createAppPageRouteBodyMetadata(metadata, pathname, metadataPlacement, t
|
|
|
282
298
|
}
|
|
283
299
|
async function AppPageStreamingMetadata(props) {
|
|
284
300
|
try {
|
|
285
|
-
return createAppPageRouteBodyMetadata(await props.metadata, props.pathname, "body", props.trailingSlash, props.scriptNonce);
|
|
301
|
+
return createAppPageRouteBodyMetadata(await props.resolveHead().metadata, props.pathname, "body", props.trailingSlash, props.scriptNonce);
|
|
286
302
|
} catch {
|
|
287
303
|
return null;
|
|
288
304
|
}
|
|
289
305
|
}
|
|
290
306
|
AppPageStreamingMetadata.displayName = "Vinext.StreamingMetadata";
|
|
291
307
|
async function AppPageMetadataOutlet(props) {
|
|
292
|
-
|
|
293
|
-
return null;
|
|
308
|
+
return props.resolveHead().outlet;
|
|
294
309
|
}
|
|
295
310
|
AppPageMetadataOutlet.displayName = "Vinext.MetadataOutlet";
|
|
296
311
|
function createAppPageStreamingMetadataOutlet(elementId, suspended = true) {
|
|
@@ -319,8 +334,8 @@ function buildAppPageElements(options) {
|
|
|
319
334
|
const routeId = renderIdentity?.routeId ?? AppElementsWire.encodeRouteId(options.routePath, interceptionContext);
|
|
320
335
|
const pageId = renderIdentity?.pageId ?? AppElementsWire.encodePageId(options.routePath, interceptionContext);
|
|
321
336
|
const pageElementId = options.route.childrenSlot ? resolveAppPageChildrenSlotId(options.route.childrenSlot) : pageId;
|
|
322
|
-
const
|
|
323
|
-
const streamingMetadataOutletId = options.
|
|
337
|
+
const metadataPlacement = options.metadataPlacement ?? "head";
|
|
338
|
+
const streamingMetadataOutletId = options.resolveHead ? `__vinext_streaming_metadata_outlet:${routeId}` : null;
|
|
324
339
|
const layoutEntries = createAppPageLayoutEntries(options.route);
|
|
325
340
|
const templateEntries = createAppPageTemplateEntries(options.route);
|
|
326
341
|
const loadingEntries = createAppPageLoadingEntries(options.route);
|
|
@@ -337,7 +352,6 @@ function buildAppPageElements(options) {
|
|
|
337
352
|
const isPrefetchLoadingShell = renderMode === APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL;
|
|
338
353
|
const pageRenderDependency = isPrefetchLoadingShell ? null : options.pageRenderDependency;
|
|
339
354
|
const prefetchLoadingEntry = isPrefetchLoadingShell ? getPrefetchLoadingEntry(options.route) : null;
|
|
340
|
-
const metadataPlacement = options.metadataPlacement ?? "head";
|
|
341
355
|
const layoutEntriesByTreePosition = /* @__PURE__ */ new Map();
|
|
342
356
|
const templateEntriesByTreePosition = /* @__PURE__ */ new Map();
|
|
343
357
|
const loadingEntriesByTreePosition = /* @__PURE__ */ new Map();
|
|
@@ -380,8 +394,11 @@ function buildAppPageElements(options) {
|
|
|
380
394
|
routePath: options.routePath
|
|
381
395
|
});
|
|
382
396
|
const prefetchSlotLoadingEntries = isPrefetchLoadingShell ? Object.entries(options.route.slots ?? {}).flatMap(([slotKey, slot]) => {
|
|
383
|
-
return getFirstLoadingEntry(createAppPageSlotLoadingEntries(slot, resolveSlotOverride(slotKey, slot.name)
|
|
397
|
+
return getFirstLoadingEntry(createAppPageSlotLoadingEntries(slot, getAppPageSlotTreeOverride(resolveSlotOverride(slotKey, slot.name)))) ? [{ ownerTreePosition: slot.ownerTreePosition ?? 0 }] : [];
|
|
384
398
|
}) : [];
|
|
399
|
+
const prefetchLoadingComponent = getDefaultExport(prefetchLoadingEntry?.loadingModule);
|
|
400
|
+
const shouldRenderPrefetchLoadingShell = isPrefetchLoadingShell && (prefetchLoadingComponent !== null || prefetchSlotLoadingEntries.length > 0);
|
|
401
|
+
const streamingMetadataBodyId = options.resolveHead && metadataPlacement === "body" && (!isPrefetchLoadingShell || shouldRenderPrefetchLoadingShell) ? `__vinext_streaming_metadata_body:${routeId}` : null;
|
|
385
402
|
const prefetchCutoffTreePosition = isPrefetchLoadingShell ? prefetchLoadingEntry?.treePosition ?? prefetchSlotLoadingEntries.reduce((deepest, entry) => Math.max(deepest, entry.ownerTreePosition), 0) : null;
|
|
386
403
|
const includesPrefetchTreePosition = (treePosition) => prefetchCutoffTreePosition === null || treePosition <= prefetchCutoffTreePosition;
|
|
387
404
|
const segmentPlan = createAppPageSegmentPlan({
|
|
@@ -426,13 +443,13 @@ function buildAppPageElements(options) {
|
|
|
426
443
|
const elements = {};
|
|
427
444
|
for (const slotPlan of segmentPlan.slots) for (const segment of slotPlan.nestedBfcacheSegments) elements[segment.id] = null;
|
|
428
445
|
if (options.route.staticSiblings && options.route.staticSiblings.length > 0) elements[APP_STATIC_SIBLINGS_KEY] = options.route.staticSiblings;
|
|
429
|
-
if (options.
|
|
430
|
-
metadata: options.streamingMetadataTags ?? options.streamingMetadata,
|
|
446
|
+
if (options.resolveHead && streamingMetadataBodyId) elements[streamingMetadataBodyId] = /* @__PURE__ */ jsx(AppPageStreamingMetadata, {
|
|
431
447
|
pathname: options.resolvedMetadataPathname ?? options.routePath,
|
|
448
|
+
resolveHead: options.resolveHead,
|
|
432
449
|
scriptNonce: options.scriptNonce,
|
|
433
450
|
trailingSlash: options.trailingSlash
|
|
434
451
|
});
|
|
435
|
-
if (options.
|
|
452
|
+
if (options.resolveHead && streamingMetadataOutletId) elements[streamingMetadataOutletId] = /* @__PURE__ */ jsx(AppPageMetadataOutlet, { resolveHead: options.resolveHead });
|
|
436
453
|
const getEffectiveSlotParams = (slotKey, _slotName) => slotPlansByKey.get(slotKey)?.params ?? options.matchedParams;
|
|
437
454
|
for (const treePosition of orderedTreePositions) {
|
|
438
455
|
if (isPrefetchLoadingShell && !includesPrefetchTreePosition(treePosition)) continue;
|
|
@@ -457,8 +474,6 @@ function buildAppPageElements(options) {
|
|
|
457
474
|
}
|
|
458
475
|
pageRenderDependency?.setResultDependencies(pageDependencies);
|
|
459
476
|
const routeLoadingComponent = getDefaultExport(options.route.loading);
|
|
460
|
-
const prefetchLoadingComponent = getDefaultExport(prefetchLoadingEntry?.loadingModule);
|
|
461
|
-
const shouldRenderPrefetchLoadingShell = isPrefetchLoadingShell && (prefetchLoadingComponent !== null || prefetchSlotLoadingEntries.length > 0);
|
|
462
477
|
if (shouldRenderPrefetchLoadingShell) elements[APP_PREFETCH_LOADING_SHELL_MARKER_KEY] = "LoadingBoundary";
|
|
463
478
|
const pageLoadingModule = resolveAppPageLoadingModuleAtOrAbove(options.route, routeSegments.length);
|
|
464
479
|
const PageLoadingComponent = pageRenderDependency ? getDefaultExport(pageLoadingModule) : null;
|
|
@@ -508,11 +523,11 @@ function buildAppPageElements(options) {
|
|
|
508
523
|
}
|
|
509
524
|
const LayoutComponent = layoutComponent;
|
|
510
525
|
const layoutDependency = layoutDependenciesByIndex.get(index);
|
|
511
|
-
let layoutElement = layoutDependency ? renderAppComponentWithDependencyBarrier(LayoutComponent, {
|
|
526
|
+
let layoutElement = layoutDependency ? renderAppComponentWithDependencyBarrier(LayoutComponent, withUseCacheLayoutMarker(LayoutComponent, {
|
|
512
527
|
...layoutProps,
|
|
513
528
|
children: /* @__PURE__ */ jsx(Children$1, {})
|
|
514
|
-
}, layoutDependency) : /* @__PURE__ */ jsx(LayoutComponent, {
|
|
515
|
-
...layoutProps,
|
|
529
|
+
}), layoutDependency) : /* @__PURE__ */ jsx(LayoutComponent, {
|
|
530
|
+
...withUseCacheLayoutMarker(LayoutComponent, layoutProps),
|
|
516
531
|
children: /* @__PURE__ */ jsx(Children$1, {})
|
|
517
532
|
});
|
|
518
533
|
const ancestorLoadingEntry = findNearestAncestorLoadingEntry(layoutEntry.treePosition);
|
|
@@ -532,8 +547,9 @@ function buildAppPageElements(options) {
|
|
|
532
547
|
const isOwnedAtRoutePrefetchCutoff = isPrefetchLoadingShell && prefetchLoadingEntry !== null && ownerTreePosition === prefetchLoadingEntry.treePosition;
|
|
533
548
|
if (!includedInPayload) continue;
|
|
534
549
|
const slotOwnerParams = resolveAppPageSegmentParams(options.route.routeSegments, layoutEntries[targetIndex]?.treePosition ?? 0, options.matchedParams);
|
|
535
|
-
const
|
|
536
|
-
const
|
|
550
|
+
const slotTreeOverride = getAppPageSlotTreeOverride(slotOverride);
|
|
551
|
+
const hasSlotTreeOverride = slotTreeOverride !== null;
|
|
552
|
+
const slotLoadingEntries = createAppPageSlotLoadingEntries(slot, slotTreeOverride);
|
|
537
553
|
const prefetchSlotLoadingEntry = isOwnedAtRoutePrefetchCutoff ? prefetchLoadingEntry : isPrefetchLoadingShell ? getFirstLoadingEntry(slotLoadingEntries) : null;
|
|
538
554
|
if (isPrefetchLoadingShell && prefetchSlotLoadingEntry === null) continue;
|
|
539
555
|
const resolvedOverrideOrPageComponent = slotOverride?.pageModule || slot.page ? traceGetLayoutOrPageModule(APP_PAGE_SEGMENT_KEY, () => getDefaultExport(slotOverride?.pageModule) ?? getDefaultExport(slot.page)) : null;
|
|
@@ -557,6 +573,10 @@ function buildAppPageElements(options) {
|
|
|
557
573
|
return /* @__PURE__ */ jsx(slotComponent, { ...slotProps });
|
|
558
574
|
})();
|
|
559
575
|
if (overrideOrPageComponent) slotElement = /* @__PURE__ */ jsx(Fragment, { children: slotElement }, slotResetKey);
|
|
576
|
+
slotElement = /* @__PURE__ */ jsx(RedirectBoundary, {
|
|
577
|
+
resetKey: slotResetKey,
|
|
578
|
+
children: slotElement
|
|
579
|
+
});
|
|
560
580
|
}
|
|
561
581
|
const branchLayouts = /* @__PURE__ */ new Map();
|
|
562
582
|
const addBranchLayout = (treePosition, entry) => {
|
|
@@ -637,7 +657,7 @@ function buildAppPageElements(options) {
|
|
|
637
657
|
const layoutEntry = layoutEntriesAtPosition[layoutIndex];
|
|
638
658
|
const LayoutComponent = layoutEntry.component;
|
|
639
659
|
slotElement = /* @__PURE__ */ jsx(LayoutComponent, {
|
|
640
|
-
params: options.makeThenableParams(layoutEntry.params),
|
|
660
|
+
...withUseCacheLayoutMarker(LayoutComponent, { params: options.makeThenableParams(layoutEntry.params) }),
|
|
641
661
|
children: slotElement
|
|
642
662
|
});
|
|
643
663
|
}
|
|
@@ -669,7 +689,10 @@ function buildAppPageElements(options) {
|
|
|
669
689
|
if (prefetchLoadingComponent === null) routeChildren = null;
|
|
670
690
|
else routeChildren = /* @__PURE__ */ jsx(prefetchLoadingComponent, {});
|
|
671
691
|
} else {
|
|
672
|
-
routeChildren = /* @__PURE__ */ jsx(RedirectBoundary, {
|
|
692
|
+
routeChildren = /* @__PURE__ */ jsx(RedirectBoundary, {
|
|
693
|
+
resetKey: routeResetKey,
|
|
694
|
+
children: routeChildren
|
|
695
|
+
});
|
|
673
696
|
if (routeLoadingComponent) routeChildren = /* @__PURE__ */ jsx(Suspense, {
|
|
674
697
|
fallback: /* @__PURE__ */ jsx(routeLoadingComponent, {}),
|
|
675
698
|
children: routeChildren
|
|
@@ -787,9 +810,8 @@ function buildAppPageElements(options) {
|
|
|
787
810
|
}) : routeChildren
|
|
788
811
|
});
|
|
789
812
|
const routeElement = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
790
|
-
createAppPageRouteHead(options.
|
|
813
|
+
createAppPageRouteHead(options.resolveHead, options.resolvedMetadataPathname ?? options.routePath, metadataPlacement, options.trailingSlash),
|
|
791
814
|
routeChildren,
|
|
792
|
-
createAppPageRouteBodyMetadata(options.resolvedMetadata, options.resolvedMetadataPathname ?? options.routePath, metadataPlacement, options.trailingSlash, options.scriptNonce),
|
|
793
815
|
createAppPageStreamingMetadataBody(streamingMetadataBodyId)
|
|
794
816
|
] });
|
|
795
817
|
elements[routeId] = pageRenderDependency ? renderAfterAppDependencies(routeElement, [pageRenderDependency]) : routeElement;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { NavigationContext } from "../shims/navigation-context-state.js";
|
|
2
|
+
import "../shims/navigation.js";
|
|
3
|
+
import { RootParams } from "../shims/root-params.js";
|
|
4
|
+
import { AppPageSsrHandler } from "./app-page-stream.js";
|
|
5
|
+
//#region src/server/app-page-rsc-render-status.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* The status of a finished RSC render, as Next.js's static generation decides
|
|
8
|
+
* it from the document's shell. A special error that rejects the shell sets
|
|
9
|
+
* it. One inside a Suspense boundary leaves the render a 200.
|
|
10
|
+
*/
|
|
11
|
+
export type AppPageRscRenderStatus = {
|
|
12
|
+
kind: "page";
|
|
13
|
+
} | {
|
|
14
|
+
kind: "special-error";
|
|
15
|
+
status: number;
|
|
16
|
+
headers?: Record<string, string>;
|
|
17
|
+
} |
|
|
18
|
+
/**
|
|
19
|
+
* A render not stored: another error rejected the shell, or
|
|
20
|
+
* generateMetadata()'s special error, whose document an RSC miss can't write.
|
|
21
|
+
*/
|
|
22
|
+
{
|
|
23
|
+
kind: "unstorable";
|
|
24
|
+
};
|
|
25
|
+
type CreateAppPageRscRenderStatusResolverOptions = {
|
|
26
|
+
basePath?: string;
|
|
27
|
+
capturedRscData: Promise<ArrayBuffer>;
|
|
28
|
+
getCapturedSpecialError: () => unknown;
|
|
29
|
+
getCapturedSpecialErrors: (error: unknown) => readonly unknown[];
|
|
30
|
+
isForceStatic: boolean;
|
|
31
|
+
loadSsrHandler: () => Promise<AppPageSsrHandler>;
|
|
32
|
+
navigationContext: NavigationContext | null;
|
|
33
|
+
rootParams?: RootParams;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Resolve an RSC-only render's status once its Flight payload is complete.
|
|
37
|
+
* Flight can't tell whether a special error sits inside a Suspense boundary, so
|
|
38
|
+
* a render that threw one renders the document's shell from the same payload,
|
|
39
|
+
* as Next.js's static generation renders HTML beside RSC. Its server
|
|
40
|
+
* components don't run again. A render without a special error is a 200.
|
|
41
|
+
*/
|
|
42
|
+
export declare function createAppPageRscRenderStatusResolver(options: CreateAppPageRscRenderStatusResolverOptions): () => Promise<AppPageRscRenderStatus>;
|
|
43
|
+
/**
|
|
44
|
+
* The status Next.js sends an RSC request for a render with this status. Its
|
|
45
|
+
* payload carries a redirect, so a redirect is a 200 with its `location`.
|
|
46
|
+
*/
|
|
47
|
+
export declare function resolveAppPageRscResponseStatus(status: number): number;
|
|
48
|
+
//#endregion
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { resolveAppPageShellSpecialError, resolveAppPageSpecialErrorStoredHeaders } from "./app-page-execution.js";
|
|
2
|
+
import { isAppSsrRenderResult } from "./app-page-stream.js";
|
|
3
|
+
//#region src/server/app-page-rsc-render-status.ts
|
|
4
|
+
const PAGE_STATUS = { kind: "page" };
|
|
5
|
+
/**
|
|
6
|
+
* Resolve an RSC-only render's status once its Flight payload is complete.
|
|
7
|
+
* Flight can't tell whether a special error sits inside a Suspense boundary, so
|
|
8
|
+
* a render that threw one renders the document's shell from the same payload,
|
|
9
|
+
* as Next.js's static generation renders HTML beside RSC. Its server
|
|
10
|
+
* components don't run again. A render without a special error is a 200.
|
|
11
|
+
*/
|
|
12
|
+
function createAppPageRscRenderStatusResolver(options) {
|
|
13
|
+
let status;
|
|
14
|
+
return () => status ??= resolveAppPageRscRenderStatus(options);
|
|
15
|
+
}
|
|
16
|
+
async function resolveAppPageRscRenderStatus(options) {
|
|
17
|
+
const rscData = await options.capturedRscData;
|
|
18
|
+
if (options.getCapturedSpecialError() === null) return PAGE_STATUS;
|
|
19
|
+
const ssrHandler = await options.loadSsrHandler();
|
|
20
|
+
let rendered;
|
|
21
|
+
try {
|
|
22
|
+
rendered = await ssrHandler.handleSsr(new Response(rscData).body, options.navigationContext, {
|
|
23
|
+
links: [],
|
|
24
|
+
preloads: [],
|
|
25
|
+
styles: []
|
|
26
|
+
}, {
|
|
27
|
+
basePath: options.basePath,
|
|
28
|
+
isForceStatic: options.isForceStatic,
|
|
29
|
+
isStaticGeneration: true,
|
|
30
|
+
onSsrError: () => void 0,
|
|
31
|
+
rootParams: options.rootParams
|
|
32
|
+
});
|
|
33
|
+
} catch (error) {
|
|
34
|
+
const specialError = resolveAppPageShellSpecialError(error, options.getCapturedSpecialErrors(error));
|
|
35
|
+
if (!specialError || specialError.fromMetadata === true) return { kind: "unstorable" };
|
|
36
|
+
const headers = resolveAppPageSpecialErrorStoredHeaders(specialError, options.basePath);
|
|
37
|
+
return {
|
|
38
|
+
kind: "special-error",
|
|
39
|
+
status: specialError.statusCode,
|
|
40
|
+
...headers ? { headers } : {}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
(isAppSsrRenderResult(rendered) ? rendered.htmlStream : rendered).cancel().catch(() => {});
|
|
44
|
+
return PAGE_STATUS;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The status Next.js sends an RSC request for a render with this status. Its
|
|
48
|
+
* payload carries a redirect, so a redirect is a 200 with its `location`.
|
|
49
|
+
*/
|
|
50
|
+
function resolveAppPageRscResponseStatus(status) {
|
|
51
|
+
return status >= 300 && status < 400 ? 200 : status;
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
export { createAppPageRscRenderStatusResolver, resolveAppPageRscResponseStatus };
|
|
@@ -83,8 +83,9 @@ export type AppPageSsrHandler = {
|
|
|
83
83
|
initialDevServerError?: unknown;
|
|
84
84
|
/** Report an SSR/Fizz render failure through instrumentation. */
|
|
85
85
|
onSsrError?: (error: unknown) => unknown;
|
|
86
|
-
/** Mirror inline Flight chunks into Next.js's `self.__next_f` transport
|
|
87
|
-
|
|
86
|
+
/** Mirror inline Flight chunks into Next.js's `self.__next_f` transport, or start
|
|
87
|
+
* mirroring once a function returns true. */
|
|
88
|
+
mirrorNextFlight?: boolean | (() => boolean);
|
|
88
89
|
/** When true, an SSR-phase-only shell render error resolves to the
|
|
89
90
|
* default `__next_error__` error-document shell (with the original
|
|
90
91
|
* flight payload and bootstrap) instead of rejecting. See handleSsr. */
|
|
@@ -141,8 +142,9 @@ type RenderAppPageHtmlStreamOptions = {
|
|
|
141
142
|
initialDevServerError?: unknown;
|
|
142
143
|
/** Report an SSR/Fizz render failure through instrumentation. */
|
|
143
144
|
onSsrError?: (error: unknown) => unknown;
|
|
144
|
-
/** Mirror inline Flight chunks into Next.js's `self.__next_f` transport
|
|
145
|
-
|
|
145
|
+
/** Mirror inline Flight chunks into Next.js's `self.__next_f` transport, or start
|
|
146
|
+
* mirroring once a function returns true. */
|
|
147
|
+
mirrorNextFlight?: boolean | (() => boolean);
|
|
146
148
|
/** True when the app supplies a custom global-error.tsx. Disables the
|
|
147
149
|
* default error-document shell fallback so SSR shell errors keep driving
|
|
148
150
|
* the server-rendered global-error boundary re-render. */
|
|
@@ -175,12 +177,17 @@ type RenderAppPageHtmlStreamWithRecoveryOptions<TSpecialError> = {
|
|
|
175
177
|
type AppPageRscErrorTracker = {
|
|
176
178
|
getCapturedError: () => unknown;
|
|
177
179
|
/**
|
|
178
|
-
* Returns
|
|
179
|
-
* the RSC render
|
|
180
|
-
*
|
|
181
|
-
* synchronously inside a route-level Suspense boundary (loading.tsx).
|
|
180
|
+
* Returns the first NEXT_REDIRECT or NEXT_HTTP_ERROR_FALLBACK error captured
|
|
181
|
+
* during the RSC render, if any. Whether it set the render's status depends
|
|
182
|
+
* on whether it rejected the document's shell.
|
|
182
183
|
*/
|
|
183
184
|
getCapturedSpecialError: () => unknown;
|
|
185
|
+
/**
|
|
186
|
+
* The special errors the RSC render threw with the digest of `error`. The
|
|
187
|
+
* SSR shell rejects with its own copy, decoded from the Flight digest, which
|
|
188
|
+
* loses server-side markers such as generateMetadata()'s.
|
|
189
|
+
*/
|
|
190
|
+
getCapturedSpecialErrors: (error: unknown) => readonly unknown[];
|
|
184
191
|
isCapturedError: (error: unknown) => boolean;
|
|
185
192
|
onRenderError: (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown;
|
|
186
193
|
};
|
|
@@ -151,6 +151,7 @@ function createAppPageRscErrorTracker(baseOnError) {
|
|
|
151
151
|
let capturedSpecialError = null;
|
|
152
152
|
const capturedErrors = /* @__PURE__ */ new Set();
|
|
153
153
|
const capturedDigests = /* @__PURE__ */ new Set();
|
|
154
|
+
const specialErrorsByDigest = /* @__PURE__ */ new Map();
|
|
154
155
|
return {
|
|
155
156
|
getCapturedError() {
|
|
156
157
|
return capturedError;
|
|
@@ -158,6 +159,10 @@ function createAppPageRscErrorTracker(baseOnError) {
|
|
|
158
159
|
getCapturedSpecialError() {
|
|
159
160
|
return capturedSpecialError;
|
|
160
161
|
},
|
|
162
|
+
getCapturedSpecialErrors(error) {
|
|
163
|
+
const digest = getNextErrorDigest(error);
|
|
164
|
+
return digest !== null && specialErrorsByDigest.get(digest) || [];
|
|
165
|
+
},
|
|
161
166
|
isCapturedError(error) {
|
|
162
167
|
if (capturedErrors.has(error)) return true;
|
|
163
168
|
const digest = getNextErrorDigest(error);
|
|
@@ -173,6 +178,7 @@ function createAppPageRscErrorTracker(baseOnError) {
|
|
|
173
178
|
const result = baseOnError(error, requestInfo, errorContext);
|
|
174
179
|
const digest = typeof result === "string" ? result : getNextErrorDigest(error);
|
|
175
180
|
if (digest !== null && !isNavigationSignalError(error)) capturedDigests.add(digest);
|
|
181
|
+
else if (digest !== null) specialErrorsByDigest.set(digest, [...specialErrorsByDigest.get(digest) ?? [], error]);
|
|
176
182
|
return result;
|
|
177
183
|
}
|
|
178
184
|
};
|
|
@@ -24,7 +24,6 @@ type AppRouteMatch = {
|
|
|
24
24
|
type RenderPagesFallbackDependencies = {
|
|
25
25
|
loadPagesEntry: () => Promise<PagesEntry> | PagesEntry;
|
|
26
26
|
buildRequestHeaders: (requestHeaders: Headers, middlewareRequestHeaders: Headers) => Headers | null;
|
|
27
|
-
decodePathParams: (pathname: string) => string;
|
|
28
27
|
applyRouteHandlerMiddlewareContext: (response: Response, middlewareContext: AppMiddlewareContext) => Response;
|
|
29
28
|
/**
|
|
30
29
|
* Returns the `__prerender_bypass` Set-Cookie header emitted by a
|
|
@@ -51,6 +50,7 @@ type RenderPagesFallbackOptions = {
|
|
|
51
50
|
initialResponseHeaders?: Headers;
|
|
52
51
|
matchKind?: "dynamic" | "static";
|
|
53
52
|
middlewareContext: AppMiddlewareContext;
|
|
53
|
+
/** Raw (still percent-encoded) Pages route URL; defaults to `url.pathname`. */
|
|
54
54
|
pathname?: string;
|
|
55
55
|
pagesDataRequest?: Request | null;
|
|
56
56
|
request: Request;
|
|
@@ -19,7 +19,7 @@ function applyPagesMiddlewareContext(response, middlewareContext) {
|
|
|
19
19
|
*/
|
|
20
20
|
async function renderPagesFallback(options, dependencies) {
|
|
21
21
|
const { allowRscDocumentFallback = false, appRouteMatch = null, isDataRequest = false, isRscRequest, initialResponseHeaders, matchKind, middlewareContext, pathname = options.url.pathname, pagesDataRequest = null, request, url } = options;
|
|
22
|
-
const { loadPagesEntry, buildRequestHeaders,
|
|
22
|
+
const { loadPagesEntry, buildRequestHeaders, applyRouteHandlerMiddlewareContext, getDraftModeCookieHeader } = dependencies;
|
|
23
23
|
if (isRscRequest && !allowRscDocumentFallback) return null;
|
|
24
24
|
const pagesEntry = await loadPagesEntry();
|
|
25
25
|
const pagesRequestHeaders = middlewareContext.requestHeaders ? buildRequestHeaders(request.headers, middlewareContext.requestHeaders) : null;
|
|
@@ -27,8 +27,7 @@ async function renderPagesFallback(options, dependencies) {
|
|
|
27
27
|
if (pagesRequestHeaders) pagesRequest = cloneRequestWithHeaders(request, pagesRequestHeaders);
|
|
28
28
|
const queryIndex = pathname.indexOf("?");
|
|
29
29
|
const pagesPathname = queryIndex === -1 ? pathname : pathname.slice(0, queryIndex);
|
|
30
|
-
const
|
|
31
|
-
const pagesUrl = decodePathParams(pagesPathname) + pagesSearch;
|
|
30
|
+
const pagesUrl = pagesPathname + (queryIndex === -1 ? url.search || "" : pathname.slice(queryIndex));
|
|
32
31
|
if (pagesPathname.startsWith("/api/") || pagesPathname === "/api") {
|
|
33
32
|
if (typeof pagesEntry.handleApiRoute !== "function") return null;
|
|
34
33
|
const hasApiMatcher = typeof pagesEntry.matchApiRoute === "function";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import "./headers.js";
|
|
2
|
+
import { runInWorkStoreScope, runOutsideWorkStoreScope } from "../shims/internal/work-store-scope.js";
|
|
2
3
|
import { notFoundResponse } from "./http-error-responses.js";
|
|
3
4
|
import { callAppPrerenderStaticParams } from "./app-prerender-static-params.js";
|
|
4
5
|
//#region src/server/app-prerender-endpoints.ts
|
|
@@ -39,13 +40,13 @@ async function handleStaticParamsEndpoint(request, options) {
|
|
|
39
40
|
if (typeof generateStaticParams !== "function") return jsonNullResponse();
|
|
40
41
|
try {
|
|
41
42
|
const params = parseParentParams(url.searchParams.get("parentParams"));
|
|
42
|
-
const result = await callAppPrerenderStaticParams({
|
|
43
|
+
const result = await runInWorkStoreScope(() => callAppPrerenderStaticParams({
|
|
43
44
|
fn: generateStaticParams,
|
|
44
45
|
params,
|
|
45
46
|
pattern,
|
|
46
47
|
rejectEmptyResults: url.searchParams.get("rejectEmptyResults") === "1",
|
|
47
48
|
rootParamNamesByPattern: options.rootParamNamesByPattern ?? {}
|
|
48
|
-
});
|
|
49
|
+
}));
|
|
49
50
|
if (result === null) return jsonNullResponse();
|
|
50
51
|
return jsonResponse(result);
|
|
51
52
|
} catch (error) {
|
|
@@ -63,10 +64,12 @@ async function handlePagesStaticPathsEndpoint(request, options) {
|
|
|
63
64
|
try {
|
|
64
65
|
const getStaticPaths = findPageRoute(await options.loadPagesRoutes?.(), pattern)?.module?.getStaticPaths;
|
|
65
66
|
if (typeof getStaticPaths !== "function") return jsonNullResponse();
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
const locales = parseLocales(url.searchParams.get("locales"));
|
|
68
|
+
const defaultLocale = url.searchParams.get("defaultLocale") ?? "";
|
|
69
|
+
return jsonResponse(await runOutsideWorkStoreScope(() => getStaticPaths({
|
|
70
|
+
locales,
|
|
71
|
+
defaultLocale
|
|
72
|
+
})));
|
|
70
73
|
} catch (error) {
|
|
71
74
|
return jsonResponse({ error: String(error) }, 500);
|
|
72
75
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import "../utils/protocol-headers.js";
|
|
2
2
|
import "./headers.js";
|
|
3
3
|
import { restoreStaticFileSignalFromTransport } from "./static-file-signal.js";
|
|
4
|
+
import { attachRequestCfMetadata } from "./request-pipeline.js";
|
|
4
5
|
import { isDraftModeRequest } from "../shims/headers.js";
|
|
5
6
|
import { getScriptNonceFromHeaderSources } from "./csp.js";
|
|
7
|
+
import { restoreImageOptimizationSignalFromTransport } from "./image-optimization.js";
|
|
6
8
|
import { isRouteTreePrefetchRequest } from "./app-route-tree-prefetch.js";
|
|
7
9
|
import "./app-worker-stages.js";
|
|
8
10
|
//#region src/server/app-request-stage-dispatch.ts
|
|
@@ -29,7 +31,8 @@ async function dispatchAppRequestStage(request, ctx, dispatchResponseStage, opti
|
|
|
29
31
|
if (!dispatchResponseStage) throw new Error("App request stage requires a response-stage dispatcher");
|
|
30
32
|
if (appRequestUsesFullResponseGraph(request, options)) {
|
|
31
33
|
const staticFileSignalToken = crypto.randomUUID();
|
|
32
|
-
const
|
|
34
|
+
const headRequest = request.method === "HEAD";
|
|
35
|
+
const response = await dispatchResponseStage(headRequest ? attachRequestCfMetadata(new Request(request, { method: "GET" }), request) : request, {
|
|
33
36
|
kind: "app-full-request",
|
|
34
37
|
buildId: options.buildId,
|
|
35
38
|
cacheability: {
|
|
@@ -38,15 +41,16 @@ async function dispatchAppRequestStage(request, ctx, dispatchResponseStage, opti
|
|
|
38
41
|
resolvedRoutePathname: new URL(request.url).pathname
|
|
39
42
|
},
|
|
40
43
|
draftModeCookie: null,
|
|
44
|
+
headRequest,
|
|
41
45
|
middlewareCookieOverlay: null,
|
|
42
46
|
prerenderDiscovery: options.prerenderDiscovery,
|
|
43
|
-
protocolVersion:
|
|
47
|
+
protocolVersion: 11,
|
|
44
48
|
requestOrigin: new URL(request.url).origin,
|
|
45
49
|
scriptNonce: null,
|
|
46
50
|
staticFileSignalToken,
|
|
47
51
|
trustedPrerenderState: options.trustedPrerenderState ?? null
|
|
48
52
|
}, { cache: "bypass" });
|
|
49
|
-
return restoreStaticFileSignalFromTransport(response, staticFileSignalToken);
|
|
53
|
+
return await restoreImageOptimizationSignalFromTransport(await restoreStaticFileSignalFromTransport(response, staticFileSignalToken), staticFileSignalToken);
|
|
50
54
|
}
|
|
51
55
|
return options.handleRequest(request, ctx, false, dispatchResponseStage, options.probeMode);
|
|
52
56
|
}
|