vinext 0.1.8 → 0.2.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 +51 -30
- package/dist/build/css-url-assets.d.ts +3 -1
- package/dist/build/css-url-assets.js +18 -1
- package/dist/build/inject-pregenerated-paths.d.ts +7 -0
- package/dist/build/inject-pregenerated-paths.js +21 -0
- package/dist/build/layout-classification.js +1 -1
- package/dist/build/nitro-route-rules.js +1 -1
- package/dist/build/pages-client-assets-module.d.ts +11 -0
- package/dist/build/pages-client-assets-module.js +27 -0
- package/dist/build/prerender-server-entry.d.ts +1 -0
- package/dist/build/prerender-server-entry.js +49 -0
- package/dist/build/prerender-server-pool.d.ts +44 -0
- package/dist/build/prerender-server-pool.js +194 -0
- package/dist/build/prerender.d.ts +2 -1
- package/dist/build/prerender.js +98 -27
- package/dist/build/report.d.ts +13 -2
- package/dist/build/report.js +99 -2
- package/dist/build/run-prerender.d.ts +7 -0
- package/dist/build/run-prerender.js +12 -2
- package/dist/build/standalone.js +2 -0
- package/dist/cache/cache-adapters-virtual.js +3 -3
- package/dist/check.d.ts +4 -6
- package/dist/check.js +48 -11
- package/dist/cli-args.d.ts +1 -2
- package/dist/cli-args.js +1 -1
- package/dist/cli-dev-config.d.ts +12 -0
- package/dist/cli-dev-config.js +23 -0
- package/dist/cli.js +112 -96
- package/dist/{server → client}/dev-error-overlay-store.d.ts +1 -1
- package/dist/{server → client}/dev-error-overlay-store.js +1 -1
- package/dist/{server → client}/dev-error-overlay.d.ts +1 -1
- package/dist/{server → client}/dev-error-overlay.js +2 -2
- package/dist/client/navigation-runtime.d.ts +2 -0
- package/dist/client/navigation-runtime.js +3 -1
- package/dist/client/vinext-next-data.d.ts +4 -1
- package/dist/client/window-next.d.ts +2 -1
- package/dist/cloudflare/index.d.ts +2 -2
- package/dist/cloudflare/index.js +2 -2
- package/dist/config/config-matchers.js +45 -19
- package/dist/config/next-config.d.ts +41 -9
- package/dist/config/next-config.js +60 -3
- package/dist/config/prerender.d.ts +34 -0
- package/dist/config/prerender.js +55 -0
- package/dist/entries/app-browser-entry.js +5 -1
- package/dist/entries/app-rsc-entry.d.ts +5 -3
- package/dist/entries/app-rsc-entry.js +44 -10
- package/dist/entries/app-rsc-manifest.js +2 -0
- package/dist/entries/pages-client-entry.d.ts +3 -0
- package/dist/entries/pages-client-entry.js +28 -3
- package/dist/entries/pages-server-entry.js +23 -6
- package/dist/image/image-adapters-virtual.d.ts +59 -0
- package/dist/image/image-adapters-virtual.js +59 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +482 -120
- package/dist/init-cloudflare.d.ts +43 -0
- package/dist/init-cloudflare.js +839 -0
- package/dist/init-platform.d.ts +40 -0
- package/dist/init-platform.js +195 -0
- package/dist/init.d.ts +16 -38
- package/dist/init.js +209 -99
- package/dist/node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/detector-1yx2Hoe0.js +294 -0
- package/dist/node_modules/.pnpm/process-ancestry@0.1.0/node_modules/process-ancestry/dist/index.js +94 -0
- package/dist/{cloudflare → packages/cloudflare}/src/cache/cdn-adapter.runtime.js +1 -1
- package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.d.ts +2 -2
- package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.js +9 -2
- package/dist/packages/cloudflare/src/deploy-config.js +150 -0
- package/dist/packages/cloudflare/src/deploy-help.js +55 -0
- package/dist/packages/cloudflare/src/deploy.js +272 -0
- package/dist/{cloudflare → packages/cloudflare/src}/tpr.d.ts +4 -41
- package/dist/{cloudflare → packages/cloudflare/src}/tpr.js +44 -20
- package/dist/plugins/ast-scope.d.ts +16 -0
- package/dist/plugins/ast-scope.js +62 -0
- package/dist/plugins/ast-utils.d.ts +27 -1
- package/dist/plugins/ast-utils.js +32 -1
- package/dist/plugins/css-module-imports.d.ts +14 -0
- package/dist/plugins/css-module-imports.js +59 -0
- package/dist/plugins/extensionless-dynamic-import.js +2 -2
- package/dist/plugins/fonts.js +1 -1
- package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
- package/dist/plugins/ignore-dynamic-requests.js +530 -0
- package/dist/plugins/og-assets.js +2 -1
- package/dist/plugins/optimize-imports.js +1 -1
- package/dist/plugins/rsc-reference-validation-normalizer.d.ts +12 -0
- package/dist/plugins/rsc-reference-validation-normalizer.js +48 -0
- package/dist/plugins/sass.d.ts +17 -1
- package/dist/plugins/sass.js +74 -1
- package/dist/plugins/styled-jsx.d.ts +16 -0
- package/dist/plugins/styled-jsx.js +149 -0
- package/dist/plugins/typeof-window.d.ts +1 -1
- package/dist/plugins/typeof-window.js +28 -56
- package/dist/routing/app-route-graph.d.ts +23 -2
- package/dist/routing/app-route-graph.js +138 -38
- package/dist/routing/file-matcher.d.ts +11 -1
- package/dist/routing/file-matcher.js +18 -3
- package/dist/routing/pages-router.js +2 -2
- package/dist/server/api-handler.js +9 -14
- package/dist/server/app-browser-action-result.d.ts +4 -1
- package/dist/server/app-browser-action-result.js +8 -1
- package/dist/server/app-browser-entry.js +198 -57
- package/dist/server/app-browser-interception-context.d.ts +1 -0
- package/dist/server/app-browser-interception-context.js +4 -2
- package/dist/server/app-browser-navigation-controller.d.ts +2 -0
- package/dist/server/app-browser-navigation-controller.js +60 -31
- package/dist/server/app-browser-server-action-client.d.ts +1 -1
- package/dist/server/app-browser-server-action-client.js +8 -7
- package/dist/server/app-browser-state.d.ts +12 -1
- package/dist/server/app-browser-state.js +25 -8
- package/dist/server/app-browser-visible-commit.d.ts +6 -1
- package/dist/server/app-browser-visible-commit.js +42 -24
- package/dist/server/app-elements-wire.d.ts +9 -2
- package/dist/server/app-elements-wire.js +8 -1
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +4 -3
- package/dist/server/app-fallback-renderer.d.ts +2 -1
- package/dist/server/app-fallback-renderer.js +10 -6
- package/dist/server/app-hydration-cache-publication.d.ts +11 -0
- package/dist/server/app-hydration-cache-publication.js +43 -0
- package/dist/server/app-middleware.d.ts +4 -3
- package/dist/server/app-middleware.js +8 -3
- package/dist/server/app-optimistic-routing.js +11 -4
- package/dist/server/app-page-boundary.js +2 -1
- package/dist/server/app-page-cache-finalizer.d.ts +1 -0
- package/dist/server/app-page-cache-finalizer.js +5 -4
- package/dist/server/app-page-cache-render.d.ts +1 -0
- package/dist/server/app-page-cache-render.js +8 -4
- package/dist/server/app-page-cache.d.ts +1 -0
- package/dist/server/app-page-cache.js +27 -7
- package/dist/server/app-page-dispatch.d.ts +1 -0
- package/dist/server/app-page-dispatch.js +26 -8
- package/dist/server/app-page-element-builder.d.ts +2 -1
- package/dist/server/app-page-element-builder.js +59 -4
- package/dist/server/app-page-execution.js +2 -1
- package/dist/server/app-page-probe.js +5 -0
- package/dist/server/app-page-render-identity.d.ts +2 -0
- package/dist/server/app-page-render-identity.js +3 -2
- package/dist/server/app-page-render.d.ts +2 -0
- package/dist/server/app-page-render.js +85 -16
- package/dist/server/app-page-request.d.ts +14 -0
- package/dist/server/app-page-request.js +69 -4
- package/dist/server/app-page-response.d.ts +7 -0
- package/dist/server/app-page-response.js +16 -4
- package/dist/server/app-page-route-wiring.d.ts +8 -1
- package/dist/server/app-page-route-wiring.js +32 -18
- package/dist/server/app-page-segment-state.d.ts +2 -1
- package/dist/server/app-page-segment-state.js +3 -1
- package/dist/server/app-page-stream.d.ts +7 -1
- package/dist/server/app-page-stream.js +3 -1
- package/dist/server/app-route-handler-execution.js +5 -1
- package/dist/server/app-route-handler-response.js +1 -0
- package/dist/server/app-route-handler-runtime.js +1 -1
- package/dist/server/app-route-tree-prefetch.d.ts +43 -0
- package/dist/server/app-route-tree-prefetch.js +187 -0
- package/dist/server/app-router-entry.js +9 -2
- package/dist/server/app-rsc-cache-busting.d.ts +2 -1
- package/dist/server/app-rsc-cache-busting.js +9 -4
- package/dist/server/app-rsc-handler.d.ts +7 -0
- package/dist/server/app-rsc-handler.js +148 -39
- package/dist/server/app-rsc-render-mode.d.ts +3 -2
- package/dist/server/app-rsc-render-mode.js +4 -1
- package/dist/server/app-rsc-request-normalization.d.ts +6 -6
- package/dist/server/app-rsc-request-normalization.js +10 -8
- package/dist/server/app-segment-config.d.ts +11 -0
- package/dist/server/app-segment-config.js +62 -6
- package/dist/server/app-server-action-execution.d.ts +1 -0
- package/dist/server/app-server-action-execution.js +61 -30
- package/dist/server/app-ssr-entry.d.ts +3 -0
- package/dist/server/app-ssr-entry.js +13 -5
- package/dist/server/app-ssr-stream.d.ts +7 -3
- package/dist/server/app-ssr-stream.js +10 -6
- package/dist/server/app-visited-response-cache.d.ts +6 -0
- package/dist/server/app-visited-response-cache.js +3 -1
- package/dist/server/cache-control.d.ts +3 -1
- package/dist/server/cache-control.js +13 -1
- package/dist/server/client-trace-metadata.js +26 -0
- package/dist/server/default-global-not-found-module.d.ts +14 -0
- package/dist/server/default-global-not-found-module.js +14 -0
- package/dist/server/dev-route-files.js +4 -0
- package/dist/server/dev-server.d.ts +11 -1
- package/dist/server/dev-server.js +94 -35
- package/dist/server/dev-stack-sourcemap.d.ts +1 -1
- package/dist/server/dev-stack-sourcemap.js +1 -1
- package/dist/server/fetch-handler.d.ts +2 -0
- package/dist/server/fetch-handler.js +18 -0
- package/dist/server/headers.d.ts +7 -15
- package/dist/server/headers.js +11 -18
- package/dist/server/image-optimization.d.ts +51 -1
- package/dist/server/image-optimization.js +52 -2
- package/dist/server/implicit-tags.js +1 -1
- package/dist/server/isr-cache.d.ts +3 -2
- package/dist/server/isr-cache.js +9 -5
- package/dist/server/metadata-routes.d.ts +3 -1
- package/dist/server/metadata-routes.js +12 -2
- package/dist/server/middleware-runtime.js +6 -1
- package/dist/server/navigation-planner.d.ts +1 -0
- package/dist/server/navigation-planner.js +14 -3
- package/dist/server/pages-api-route.js +2 -2
- package/dist/server/pages-asset-tags.d.ts +4 -6
- package/dist/server/pages-asset-tags.js +12 -12
- package/dist/server/pages-client-assets.d.ts +12 -0
- package/dist/server/pages-client-assets.js +10 -0
- package/dist/server/pages-data-route.d.ts +4 -2
- package/dist/server/pages-data-route.js +18 -4
- package/dist/server/pages-dev-module-url.d.ts +2 -1
- package/dist/server/pages-dev-module-url.js +6 -3
- package/dist/server/pages-node-compat.d.ts +19 -1
- package/dist/server/pages-node-compat.js +81 -4
- package/dist/server/pages-page-data.d.ts +33 -1
- package/dist/server/pages-page-data.js +62 -33
- package/dist/server/pages-page-handler.d.ts +2 -1
- package/dist/server/pages-page-handler.js +38 -19
- package/dist/server/pages-page-response.d.ts +8 -0
- package/dist/server/pages-page-response.js +7 -3
- package/dist/server/pages-request-pipeline.d.ts +9 -5
- package/dist/server/pages-request-pipeline.js +55 -7
- package/dist/server/pages-router-entry.d.ts +30 -0
- package/dist/server/pages-router-entry.js +108 -0
- package/dist/server/prerender-manifest.d.ts +3 -1
- package/dist/server/prerender-route-params.js +1 -1
- package/dist/server/prod-server.d.ts +5 -3
- package/dist/server/prod-server.js +68 -39
- package/dist/server/request-pipeline.js +2 -1
- package/dist/server/seed-cache.js +4 -4
- package/dist/shims/app-router-scroll-state.d.ts +1 -0
- package/dist/shims/app-router-scroll-state.js +1 -0
- package/dist/shims/app-router-scroll.js +2 -1
- package/dist/shims/cache-handler.js +8 -1
- package/dist/shims/cache.js +22 -15
- package/dist/shims/cdn-cache.js +1 -1
- package/dist/shims/dynamic-preload-chunks.js +2 -1
- package/dist/shims/fetch-cache.d.ts +3 -1
- package/dist/shims/fetch-cache.js +77 -52
- package/dist/shims/form.d.ts +4 -2
- package/dist/shims/form.js +37 -43
- package/dist/shims/headers.d.ts +7 -1
- package/dist/shims/headers.js +17 -3
- package/dist/shims/image.js +75 -14
- package/dist/shims/internal/app-prefetch-fetch-queue.d.ts +10 -0
- package/dist/shims/internal/app-prefetch-fetch-queue.js +61 -0
- package/dist/shims/internal/app-route-detection.d.ts +2 -17
- package/dist/shims/internal/app-route-detection.js +4 -17
- package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +23 -0
- package/dist/shims/internal/hybrid-client-route-owner-direct.js +51 -0
- package/dist/shims/internal/hybrid-client-route-owner.d.ts +3 -15
- package/dist/shims/internal/hybrid-client-route-owner.js +40 -58
- package/dist/shims/internal/pages-data-fetch-dedup.d.ts +10 -5
- package/dist/shims/internal/pages-data-fetch-dedup.js +84 -14
- package/dist/shims/internal/pages-data-target.d.ts +18 -12
- package/dist/shims/internal/pages-data-target.js +97 -13
- package/dist/shims/internal/pages-router-components.d.ts +7 -0
- package/dist/shims/internal/pages-router-components.js +13 -0
- package/dist/shims/layout-segment-context.d.ts +4 -1
- package/dist/shims/layout-segment-context.js +18 -4
- package/dist/shims/link.d.ts +1 -1
- package/dist/shims/link.js +224 -58
- package/dist/shims/navigation.d.ts +19 -3
- package/dist/shims/navigation.js +245 -47
- package/dist/shims/request-context.js +18 -0
- package/dist/shims/root-params.d.ts +15 -1
- package/dist/shims/root-params.js +21 -1
- package/dist/shims/router.d.ts +5 -7
- package/dist/shims/router.js +387 -102
- package/dist/shims/server.js +3 -2
- package/dist/shims/slot.js +3 -6
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/typegen.js +1 -1
- package/dist/utils/client-runtime-metadata.d.ts +2 -18
- package/dist/utils/client-runtime-metadata.js +31 -22
- package/dist/utils/dev-stack-sourcemap-endpoint.d.ts +4 -0
- package/dist/{server → utils}/dev-stack-sourcemap-endpoint.js +1 -1
- package/dist/utils/domain-locale.d.ts +6 -3
- package/dist/{server → utils}/middleware-request-headers.d.ts +1 -1
- package/dist/{server → utils}/middleware-request-headers.js +3 -3
- package/dist/utils/project.d.ts +48 -2
- package/dist/utils/project.js +225 -4
- package/dist/utils/protocol-headers.d.ts +23 -0
- package/dist/utils/protocol-headers.js +23 -0
- package/dist/utils/react-version.d.ts +4 -0
- package/dist/utils/react-version.js +44 -0
- package/dist/utils/vite-version.d.ts +2 -0
- package/dist/utils/vite-version.js +11 -1
- package/package.json +47 -2
- package/dist/deploy.d.ts +0 -197
- package/dist/deploy.js +0 -1040
- package/dist/server/dev-stack-sourcemap-endpoint.d.ts +0 -4
- /package/dist/{cloudflare → packages/cloudflare}/src/utils/cache-control-metadata.js +0 -0
|
@@ -8,6 +8,7 @@ import { isValidElement } from "react";
|
|
|
8
8
|
const APP_INTERCEPTION_SEPARATOR = "\0";
|
|
9
9
|
const APP_ARTIFACT_COMPATIBILITY_KEY = "__artifactCompatibility";
|
|
10
10
|
const APP_CACHE_ENTRY_REUSE_PROOF_KEY = "__cacheEntryReuseProof";
|
|
11
|
+
const APP_DYNAMIC_STALE_TIME_KEY = "__dynamicStaleTime";
|
|
11
12
|
const APP_INTERCEPTION_KEY = "__interception";
|
|
12
13
|
const APP_INTERCEPTION_CONTEXT_KEY = "__interceptionContext";
|
|
13
14
|
const APP_LAYOUT_IDS_KEY = "__layoutIds";
|
|
@@ -177,6 +178,7 @@ function createAppElementsWireMetadataEntries(input) {
|
|
|
177
178
|
[APP_INTERCEPTION_CONTEXT_KEY]: input.interceptionContext,
|
|
178
179
|
[APP_LAYOUT_IDS_KEY]: layoutIds,
|
|
179
180
|
[APP_ROOT_LAYOUT_KEY]: input.rootLayoutTreePath,
|
|
181
|
+
...input.dynamicStaleTimeSeconds === void 0 ? {} : { [APP_DYNAMIC_STALE_TIME_KEY]: input.dynamicStaleTimeSeconds },
|
|
180
182
|
...input.sourcePage === null || input.sourcePage === void 0 ? {} : { [APP_SOURCE_PAGE_KEY]: input.sourcePage }
|
|
181
183
|
};
|
|
182
184
|
const entriesWithInterception = input.interception ? {
|
|
@@ -319,6 +321,7 @@ function buildOutgoingAppPayload(input) {
|
|
|
319
321
|
if (skippedLayoutIds.size > 0) payload[APP_SKIPPED_LAYOUT_IDS_KEY] = [...skippedLayoutIds];
|
|
320
322
|
payload[APP_ARTIFACT_COMPATIBILITY_KEY] = input.artifactCompatibility ?? createArtifactCompatibilityEnvelope();
|
|
321
323
|
if (input.cacheEntryReuseProof) payload[APP_CACHE_ENTRY_REUSE_PROOF_KEY] = input.cacheEntryReuseProof;
|
|
324
|
+
if (input.dynamicStaleTimeSeconds !== void 0) payload[APP_DYNAMIC_STALE_TIME_KEY] = input.dynamicStaleTimeSeconds;
|
|
322
325
|
if (input.renderObservation) payload[APP_RENDER_OBSERVATION_KEY] = input.renderObservation;
|
|
323
326
|
return payload;
|
|
324
327
|
}
|
|
@@ -394,10 +397,13 @@ function readAppElementsMetadata(elements) {
|
|
|
394
397
|
const interception = parseInterceptionMetadata(elements[APP_INTERCEPTION_KEY]);
|
|
395
398
|
const artifactCompatibility = readArtifactCompatibilityMetadata(elements[APP_ARTIFACT_COMPATIBILITY_KEY]);
|
|
396
399
|
const cacheEntryReuseProof = parseCacheEntryReuseProofMetadata(elements[APP_CACHE_ENTRY_REUSE_PROOF_KEY]);
|
|
400
|
+
const dynamicStaleTime = elements[APP_DYNAMIC_STALE_TIME_KEY];
|
|
401
|
+
const dynamicStaleTimeSeconds = typeof dynamicStaleTime === "number" && Number.isFinite(dynamicStaleTime) && dynamicStaleTime >= 0 ? dynamicStaleTime : void 0;
|
|
397
402
|
const sourcePage = readSourcePageMetadata(elements[APP_SOURCE_PAGE_KEY]);
|
|
398
403
|
return {
|
|
399
404
|
artifactCompatibility,
|
|
400
405
|
...cacheEntryReuseProof ? { cacheEntryReuseProof } : {},
|
|
406
|
+
...dynamicStaleTimeSeconds === void 0 ? {} : { dynamicStaleTimeSeconds },
|
|
401
407
|
interception,
|
|
402
408
|
interceptionContext: interceptionContext ?? null,
|
|
403
409
|
layoutIds,
|
|
@@ -413,6 +419,7 @@ const AppElementsWire = {
|
|
|
413
419
|
keys: {
|
|
414
420
|
artifactCompatibility: APP_ARTIFACT_COMPATIBILITY_KEY,
|
|
415
421
|
cacheEntryReuseProof: APP_CACHE_ENTRY_REUSE_PROOF_KEY,
|
|
422
|
+
dynamicStaleTime: APP_DYNAMIC_STALE_TIME_KEY,
|
|
416
423
|
interception: APP_INTERCEPTION_KEY,
|
|
417
424
|
interceptionContext: APP_INTERCEPTION_CONTEXT_KEY,
|
|
418
425
|
layoutIds: APP_LAYOUT_IDS_KEY,
|
|
@@ -440,4 +447,4 @@ const AppElementsWire = {
|
|
|
440
447
|
withLayoutFlags
|
|
441
448
|
};
|
|
442
449
|
//#endregion
|
|
443
|
-
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags };
|
|
450
|
+
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsInterception, AppElementsSlotBinding, AppElementsWire, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
|
|
1
|
+
import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementValue, AppElements, AppElementsInterception, AppElementsSlotBinding, AppElementsWire, AppOutgoingElements, AppWireElements, LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
|
|
2
2
|
|
|
3
3
|
//#region src/server/app-elements.d.ts
|
|
4
4
|
declare const APP_PREFETCH_LOADING_SHELL_MARKER_KEY = "__prefetchLoadingShell";
|
|
@@ -6,4 +6,4 @@ declare function getMountedSlotIds(elements: AppElements): string[];
|
|
|
6
6
|
declare function getMountedSlotIdsHeader(elements: AppElements): string | null;
|
|
7
7
|
declare function resolveVisitedResponseInterceptionContext(requestInterceptionContext: string | null, payloadInterceptionContext: string | null): string | null;
|
|
8
8
|
//#endregion
|
|
9
|
-
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, type AppElementValue, type AppElements, type AppElementsInterception, type AppElementsSlotBinding, AppElementsWire, type AppOutgoingElements, type AppWireElements, type LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
|
|
9
|
+
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, type AppElementValue, type AppElements, type AppElementsInterception, type AppElementsSlotBinding, AppElementsWire, type AppOutgoingElements, type AppWireElements, type LayoutFlags, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
|
|
1
|
+
import { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, withLayoutFlags } from "./app-elements-wire.js";
|
|
2
2
|
import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
|
|
3
3
|
//#region src/server/app-elements.ts
|
|
4
4
|
const APP_PREFETCH_LOADING_SHELL_MARKER_KEY = "__prefetchLoadingShell";
|
|
5
5
|
function getMountedSlotIds(elements) {
|
|
6
6
|
return Object.keys(elements).filter((key) => {
|
|
7
7
|
const value = elements[key];
|
|
8
|
-
|
|
8
|
+
const parsed = AppElementsWire.parseElementKey(key);
|
|
9
|
+
return parsed?.kind === "slot" && parsed.name !== "children" && value !== null && value !== void 0 && value !== UNMATCHED_SLOT;
|
|
9
10
|
}).sort();
|
|
10
11
|
}
|
|
11
12
|
function getMountedSlotIdsHeader(elements) {
|
|
@@ -15,4 +16,4 @@ function resolveVisitedResponseInterceptionContext(requestInterceptionContext, p
|
|
|
15
16
|
return payloadInterceptionContext ?? requestInterceptionContext;
|
|
16
17
|
}
|
|
17
18
|
//#endregion
|
|
18
|
-
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
|
|
19
|
+
export { APP_ARTIFACT_COMPATIBILITY_KEY, APP_CACHE_ENTRY_REUSE_PROOF_KEY, APP_DYNAMIC_STALE_TIME_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_LAYOUT_FLAGS_KEY, APP_LAYOUT_IDS_KEY, APP_PREFETCH_LOADING_SHELL_MARKER_KEY, APP_RENDER_OBSERVATION_KEY, APP_ROOT_LAYOUT_KEY, APP_ROUTE_KEY, APP_SKIPPED_LAYOUT_IDS_KEY, APP_SLOT_BINDINGS_KEY, APP_SOURCE_PAGE_KEY, APP_STATIC_SIBLINGS_KEY, APP_UNMATCHED_SLOT_WIRE_VALUE, AppElementsWire, UNMATCHED_SLOT, buildOutgoingAppPayload, compareAppElementsSlotIds, getMountedSlotIds, getMountedSlotIdsHeader, isAppElementsRecord, normalizeAppElements, normalizeAppElementsSlotBindings, readAppElementsMetadata, resolveVisitedResponseInterceptionContext, withLayoutFlags };
|
|
@@ -33,7 +33,8 @@ type AppFallbackRendererOptions<TModule extends AppPageModule = AppPageModule> =
|
|
|
33
33
|
createRscOnErrorHandler: (request: Request, pathname: string, routePath: string) => AppPageBoundaryOnError;
|
|
34
34
|
fontProviders: AppFallbackRendererFontProviders;
|
|
35
35
|
getNavigationContext: () => NavigationContext | null;
|
|
36
|
-
globalErrorModule?: TModule | null;
|
|
36
|
+
globalErrorModule?: TModule | null; /** Whether experimental.globalNotFound is enabled for route-miss 404s. */
|
|
37
|
+
globalNotFoundEnabled?: boolean;
|
|
37
38
|
/**
|
|
38
39
|
* Loader for the user's `app/global-not-found.tsx` module. When provided,
|
|
39
40
|
* route-miss 404s render this module as a standalone document (skipping the
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { renderAppPageErrorBoundary, renderAppPageHttpAccessFallback } from "./app-page-boundary-render.js";
|
|
2
2
|
import { DEFAULT_GLOBAL_ERROR_MODULE } from "./default-global-error-module.js";
|
|
3
|
+
import { DEFAULT_GLOBAL_NOT_FOUND_MODULE } from "./default-global-not-found-module.js";
|
|
3
4
|
import { DEFAULT_NOT_FOUND_MODULE } from "./default-not-found-module.js";
|
|
4
5
|
//#region src/server/app-fallback-renderer.ts
|
|
5
6
|
const EMPTY_MW_CTX = {
|
|
@@ -7,7 +8,7 @@ const EMPTY_MW_CTX = {
|
|
|
7
8
|
status: null
|
|
8
9
|
};
|
|
9
10
|
function createAppFallbackRenderer(options) {
|
|
10
|
-
const { applyFileBasedMetadata, basePath = "", clearRequestContext, createRscOnErrorHandler: buildRscOnErrorHandler, fontProviders, getNavigationContext, globalErrorModule, loadGlobalNotFoundModule, makeThenableParams, metadataRoutes, resolveChildSegments, rootBoundaries, rscRenderer, sanitizer, ssrLoader, trailingSlash } = options;
|
|
11
|
+
const { applyFileBasedMetadata, basePath = "", clearRequestContext, createRscOnErrorHandler: buildRscOnErrorHandler, fontProviders, getNavigationContext, globalErrorModule, globalNotFoundEnabled = false, loadGlobalNotFoundModule, makeThenableParams, metadataRoutes, resolveChildSegments, rootBoundaries, rscRenderer, sanitizer, ssrLoader, trailingSlash } = options;
|
|
11
12
|
const { rootForbiddenModule, rootLayouts, rootNotFoundModule, rootUnauthorizedModule } = rootBoundaries;
|
|
12
13
|
const effectiveGlobalErrorModule = globalErrorModule ?? DEFAULT_GLOBAL_ERROR_MODULE;
|
|
13
14
|
const effectiveRootNotFoundModule = rootNotFoundModule ?? DEFAULT_NOT_FOUND_MODULE;
|
|
@@ -19,7 +20,8 @@ function createAppFallbackRenderer(options) {
|
|
|
19
20
|
}
|
|
20
21
|
return {
|
|
21
22
|
async renderHttpAccessFallback(route, statusCode, isRscRequest, request, opts, scriptNonce, middlewareContext, callContext) {
|
|
22
|
-
|
|
23
|
+
const useGlobalNotFound = statusCode === 404 && globalNotFoundEnabled && !route && !opts?.boundaryComponent;
|
|
24
|
+
if (useGlobalNotFound && loadGlobalNotFoundModule) {
|
|
23
25
|
const globalNotFoundModule = await resolveGlobalNotFoundModule();
|
|
24
26
|
const globalNotFoundComponent = globalNotFoundModule?.default ?? null;
|
|
25
27
|
if (globalNotFoundComponent) return renderAppPageHttpAccessFallback({
|
|
@@ -57,6 +59,7 @@ function createAppFallbackRenderer(options) {
|
|
|
57
59
|
statusCode
|
|
58
60
|
});
|
|
59
61
|
}
|
|
62
|
+
const routeMissRootNotFoundModule = useGlobalNotFound ? DEFAULT_GLOBAL_NOT_FOUND_MODULE : effectiveRootNotFoundModule;
|
|
60
63
|
return renderAppPageHttpAccessFallback({
|
|
61
64
|
applyFileBasedMetadata,
|
|
62
65
|
basePath,
|
|
@@ -75,7 +78,7 @@ function createAppFallbackRenderer(options) {
|
|
|
75
78
|
globalErrorModule: effectiveGlobalErrorModule,
|
|
76
79
|
isEdgeRuntime: callContext?.isEdgeRuntime,
|
|
77
80
|
isRscRequest,
|
|
78
|
-
layoutModules: opts?.layouts ?? null,
|
|
81
|
+
layoutModules: useGlobalNotFound ? [] : opts?.layouts ?? null,
|
|
79
82
|
loadSsrHandler: ssrLoader,
|
|
80
83
|
makeThenableParams,
|
|
81
84
|
matchedParams: opts?.matchedParams ?? route?.params ?? {},
|
|
@@ -84,12 +87,13 @@ function createAppFallbackRenderer(options) {
|
|
|
84
87
|
requestUrl: request.url,
|
|
85
88
|
resolveChildSegments,
|
|
86
89
|
rootForbiddenModule,
|
|
87
|
-
rootLayouts,
|
|
88
|
-
rootNotFoundModule:
|
|
90
|
+
rootLayouts: useGlobalNotFound ? [] : rootLayouts,
|
|
91
|
+
rootNotFoundModule: routeMissRootNotFoundModule,
|
|
89
92
|
rootUnauthorizedModule,
|
|
90
|
-
route,
|
|
93
|
+
route: useGlobalNotFound ? null : route,
|
|
91
94
|
renderToReadableStream: rscRenderer,
|
|
92
95
|
scriptNonce,
|
|
96
|
+
skipLayoutWrapping: useGlobalNotFound,
|
|
93
97
|
sourcePageSegments: callContext?.sourcePageSegments,
|
|
94
98
|
statusCode
|
|
95
99
|
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/server/app-hydration-cache-publication.d.ts
|
|
2
|
+
type HydrationCachePublication = {
|
|
3
|
+
commit(): void;
|
|
4
|
+
complete(): void;
|
|
5
|
+
fail(): void;
|
|
6
|
+
invalidate(): void;
|
|
7
|
+
publish(publishCandidate: () => () => void): void;
|
|
8
|
+
};
|
|
9
|
+
declare function createHydrationCachePublication(): HydrationCachePublication;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { HydrationCachePublication, createHydrationCachePublication };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//#region src/server/app-hydration-cache-publication.ts
|
|
2
|
+
function createHydrationCachePublication() {
|
|
3
|
+
let state = "pending";
|
|
4
|
+
let pendingPublication = null;
|
|
5
|
+
let invalidatePublishedCandidate = null;
|
|
6
|
+
const publishPendingCandidate = () => {
|
|
7
|
+
if (state !== "committed" && state !== "complete" || pendingPublication === null) return;
|
|
8
|
+
const publishCandidate = pendingPublication;
|
|
9
|
+
pendingPublication = null;
|
|
10
|
+
invalidatePublishedCandidate = publishCandidate();
|
|
11
|
+
};
|
|
12
|
+
return {
|
|
13
|
+
commit() {
|
|
14
|
+
if (state !== "pending") return;
|
|
15
|
+
state = "committed";
|
|
16
|
+
publishPendingCandidate();
|
|
17
|
+
},
|
|
18
|
+
complete() {
|
|
19
|
+
if (state === "committed") state = "complete";
|
|
20
|
+
},
|
|
21
|
+
fail() {
|
|
22
|
+
if (state === "complete" || state === "invalidated") return;
|
|
23
|
+
state = "invalidated";
|
|
24
|
+
pendingPublication = null;
|
|
25
|
+
invalidatePublishedCandidate?.();
|
|
26
|
+
invalidatePublishedCandidate = null;
|
|
27
|
+
},
|
|
28
|
+
invalidate() {
|
|
29
|
+
if (state === "invalidated") return;
|
|
30
|
+
state = "invalidated";
|
|
31
|
+
pendingPublication = null;
|
|
32
|
+
invalidatePublishedCandidate?.();
|
|
33
|
+
invalidatePublishedCandidate = null;
|
|
34
|
+
},
|
|
35
|
+
publish(publishCandidate) {
|
|
36
|
+
if (state === "invalidated") return;
|
|
37
|
+
pendingPublication = publishCandidate;
|
|
38
|
+
publishPendingCandidate();
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { createHydrationCachePublication };
|
|
@@ -12,11 +12,11 @@ type ApplyAppMiddlewareOptions = {
|
|
|
12
12
|
basePath?: string;
|
|
13
13
|
cleanPathname: string;
|
|
14
14
|
context: AppMiddlewareContext;
|
|
15
|
+
hadBasePath?: boolean;
|
|
15
16
|
i18nConfig?: NextI18nConfig | null;
|
|
16
17
|
/**
|
|
17
|
-
* Whether the inbound request was a `_next/data` fetch
|
|
18
|
-
*
|
|
19
|
-
* INTERNAL_HEADERS and is stripped before this function runs.
|
|
18
|
+
* Whether the inbound request was recognized as a `_next/data` fetch from
|
|
19
|
+
* trusted URL normalization before internal headers were stripped.
|
|
20
20
|
*/
|
|
21
21
|
isDataRequest?: boolean;
|
|
22
22
|
filePath?: string;
|
|
@@ -34,6 +34,7 @@ type ApplyAppMiddlewareOptions = {
|
|
|
34
34
|
type ApplyAppMiddlewareResult = {
|
|
35
35
|
kind: "continue";
|
|
36
36
|
cleanPathname: string;
|
|
37
|
+
rewritten: boolean;
|
|
37
38
|
search: string | null;
|
|
38
39
|
} | {
|
|
39
40
|
kind: "response";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { VINEXT_MW_CTX_HEADER } from "../utils/protocol-headers.js";
|
|
2
|
+
import { FLIGHT_HEADERS } from "./headers.js";
|
|
3
|
+
import { buildRequestHeadersFromMiddlewareResponse } from "../utils/middleware-request-headers.js";
|
|
3
4
|
import { isExternalUrl, proxyExternalRequest } from "../config/config-matchers.js";
|
|
4
5
|
import { internalServerErrorResponse } from "./http-error-responses.js";
|
|
5
6
|
import { cloneRequestWithHeaders, processMiddlewareHeaders } from "./request-pipeline.js";
|
|
@@ -100,6 +101,7 @@ async function applyAppMiddleware(options) {
|
|
|
100
101
|
const forwarded = applyForwardedMiddlewareContext(options.request, options.context);
|
|
101
102
|
const middlewareRequest = requestWithoutFlightHeaders(options.request);
|
|
102
103
|
let cleanPathname = options.cleanPathname;
|
|
104
|
+
let rewritten = false;
|
|
103
105
|
let search = null;
|
|
104
106
|
if (forwarded.rewriteUrl) try {
|
|
105
107
|
if (isExternalMiddlewareRewrite(forwarded.rewriteUrl, middlewareRequest)) return {
|
|
@@ -108,6 +110,7 @@ async function applyAppMiddleware(options) {
|
|
|
108
110
|
};
|
|
109
111
|
const rewriteParsed = new URL(forwarded.rewriteUrl, middlewareRequest.url);
|
|
110
112
|
cleanPathname = rewriteParsed.pathname;
|
|
113
|
+
rewritten = true;
|
|
111
114
|
search = rewriteParsed.search;
|
|
112
115
|
} catch (e) {
|
|
113
116
|
console.error("[vinext] Failed to apply forwarded middleware rewrite:", e);
|
|
@@ -116,7 +119,7 @@ async function applyAppMiddleware(options) {
|
|
|
116
119
|
if (!forwarded.applied) {
|
|
117
120
|
const result = await executeMiddleware({
|
|
118
121
|
basePath: options.basePath,
|
|
119
|
-
hadBasePath: true,
|
|
122
|
+
hadBasePath: options.hadBasePath ?? true,
|
|
120
123
|
filePath: options.filePath,
|
|
121
124
|
i18nConfig: options.i18nConfig,
|
|
122
125
|
isDataRequest: options.isDataRequest,
|
|
@@ -150,6 +153,7 @@ async function applyAppMiddleware(options) {
|
|
|
150
153
|
};
|
|
151
154
|
const rewriteParsed = new URL(result.rewriteUrl, middlewareRequest.url);
|
|
152
155
|
cleanPathname = rewriteParsed.pathname;
|
|
156
|
+
rewritten = true;
|
|
153
157
|
search = rewriteParsed.search;
|
|
154
158
|
}
|
|
155
159
|
}
|
|
@@ -161,6 +165,7 @@ async function applyAppMiddleware(options) {
|
|
|
161
165
|
return {
|
|
162
166
|
kind: "continue",
|
|
163
167
|
cleanPathname,
|
|
168
|
+
rewritten,
|
|
164
169
|
search
|
|
165
170
|
};
|
|
166
171
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { buildParams, decodeMatchedParams, splitPathnameForRouteMatch } from "../routing/utils.js";
|
|
2
2
|
import { stripBasePath } from "../utils/base-path.js";
|
|
3
|
-
import { matchRoutePattern } from "../routing/route-pattern.js";
|
|
4
3
|
import { isUnknownRecord } from "../utils/record.js";
|
|
5
4
|
import { AppElementsWire } from "./app-elements-wire.js";
|
|
6
5
|
import "./app-elements.js";
|
|
6
|
+
import { matchRoutePattern } from "../routing/route-pattern.js";
|
|
7
7
|
import { stripRscCacheBustingSearchParam, stripRscSuffix } from "./app-rsc-cache-busting.js";
|
|
8
8
|
import { Suspense, createElement, isValidElement } from "react";
|
|
9
9
|
//#region src/server/app-optimistic-routing.ts
|
|
@@ -162,8 +162,15 @@ function elementHasSuspenseFallback(value, depth = 0) {
|
|
|
162
162
|
if (!isUnknownRecord(props)) return false;
|
|
163
163
|
return elementHasSuspenseFallback(Reflect.get(props, "children"), depth + 1);
|
|
164
164
|
}
|
|
165
|
-
function getPageElementIds(elements) {
|
|
166
|
-
|
|
165
|
+
function getPageElementIds(elements, route) {
|
|
166
|
+
const pageElementIds = /* @__PURE__ */ new Set();
|
|
167
|
+
if (route.pageId && Object.hasOwn(elements, route.pageId)) pageElementIds.add(route.pageId);
|
|
168
|
+
for (const slotId of route.slotIds) {
|
|
169
|
+
const parsed = AppElementsWire.parseElementKey(slotId);
|
|
170
|
+
if (parsed?.kind === "slot" && parsed.name === "children" && Object.hasOwn(elements, slotId)) pageElementIds.add(slotId);
|
|
171
|
+
}
|
|
172
|
+
for (const key of Object.keys(elements)) if (AppElementsWire.parseElementKey(key)?.kind === "page") pageElementIds.add(key);
|
|
173
|
+
return Array.from(pageElementIds).sort();
|
|
167
174
|
}
|
|
168
175
|
function OptimisticRouteSegment() {
|
|
169
176
|
throw OPTIMISTIC_ROUTE_SEGMENT_SUSPENSE_TRIGGER;
|
|
@@ -182,7 +189,7 @@ function createOptimisticRouteTemplate(options) {
|
|
|
182
189
|
if (!options.allowLoadingShell && !elementHasSuspenseFallback(routeElement)) return null;
|
|
183
190
|
if (options.allowLoadingShell && options.elements["__prefetchLoadingShell"] !== "LoadingBoundary") return null;
|
|
184
191
|
if (options.allowLoadingShell && (routeElement === void 0 || routeElement === null)) return null;
|
|
185
|
-
const pageElementIds = getPageElementIds(options.elements);
|
|
192
|
+
const pageElementIds = getPageElementIds(options.elements, match.route);
|
|
186
193
|
if (pageElementIds.length === 0) return null;
|
|
187
194
|
return {
|
|
188
195
|
elements: options.elements,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { runWithFetchDedupe } from "../shims/fetch-cache.js";
|
|
2
2
|
import { resolveAppPageSegmentParams } from "./app-page-params.js";
|
|
3
|
-
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
|
|
3
|
+
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader } from "./app-rsc-cache-busting.js";
|
|
4
4
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
5
5
|
import { applyEdgeRuntimeHeader } from "./app-page-response.js";
|
|
6
6
|
//#region src/server/app-page-boundary.ts
|
|
@@ -109,6 +109,7 @@ async function renderAppPageBoundaryResponse(options) {
|
|
|
109
109
|
applyEdgeRuntimeHeader(headers, options.isEdgeRuntime);
|
|
110
110
|
mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders ?? null);
|
|
111
111
|
applyRscCompatibilityIdHeader(headers);
|
|
112
|
+
applyRscDeploymentIdHeader(headers);
|
|
112
113
|
return new Response(rscStream, {
|
|
113
114
|
status: options.status,
|
|
114
115
|
headers
|
|
@@ -50,6 +50,7 @@ type ScheduleAppPageRscCacheWriteOptions = {
|
|
|
50
50
|
isrSet: AppPageCacheSetter;
|
|
51
51
|
interceptionContext?: string | null;
|
|
52
52
|
mountedSlotsHeader?: string | null;
|
|
53
|
+
omitPendingDynamicCacheState?: boolean;
|
|
53
54
|
renderMode?: AppRscRenderMode;
|
|
54
55
|
preserveClientResponseHeaders?: boolean;
|
|
55
56
|
expireSeconds?: number;
|
|
@@ -63,7 +63,8 @@ function finalizeAppPageHtmlCacheResponse(response, options) {
|
|
|
63
63
|
cacheTags: pageTags,
|
|
64
64
|
state: observationState
|
|
65
65
|
});
|
|
66
|
-
const
|
|
66
|
+
const linkHeader = response.headers.get("link");
|
|
67
|
+
const writes = [options.isrSet(htmlKey, buildAppPageCacheValue(cachedHtml, void 0, 200, htmlRenderObservation, linkHeader ? { link: linkHeader } : void 0), cachePolicy.revalidateSeconds, pageTags, cachePolicy.expireSeconds)];
|
|
67
68
|
if (options.capturedRscDataPromise) writes.push(options.capturedRscDataPromise.then((rscData) => options.isrSet(rscKey, buildAppPageCacheValue("", rscData, 200, rscRenderObservation), cachePolicy.revalidateSeconds, pageTags, cachePolicy.expireSeconds)));
|
|
68
69
|
await Promise.all(writes);
|
|
69
70
|
options.isrDebug?.("HTML cache written", htmlKey);
|
|
@@ -82,7 +83,7 @@ function finalizeAppPageRscCacheResponse(response, options) {
|
|
|
82
83
|
if (!scheduleAppPageRscCacheWrite(options)) return response;
|
|
83
84
|
if (options.preserveClientResponseHeaders === true) return response;
|
|
84
85
|
const clientHeaders = new Headers(response.headers);
|
|
85
|
-
applyPendingDynamicCdnHeaders(clientHeaders, options.getPageTags());
|
|
86
|
+
applyPendingDynamicCdnHeaders(clientHeaders, options.getPageTags(), { omitCacheState: options.omitPendingDynamicCacheState === true });
|
|
86
87
|
return new Response(response.body, {
|
|
87
88
|
status: response.status,
|
|
88
89
|
statusText: response.statusText,
|
|
@@ -91,8 +92,8 @@ function finalizeAppPageRscCacheResponse(response, options) {
|
|
|
91
92
|
}
|
|
92
93
|
function scheduleAppPageRscCacheWrite(options) {
|
|
93
94
|
const capturedRscDataPromise = options.capturedRscDataPromise;
|
|
94
|
-
if (!capturedRscDataPromise || options.dynamicUsedDuringBuild) return false;
|
|
95
|
-
const rscKey = options.isrRscKey(options.cleanPathname,
|
|
95
|
+
if (!capturedRscDataPromise || options.dynamicUsedDuringBuild || options.mountedSlotsHeader) return false;
|
|
96
|
+
const rscKey = options.isrRscKey(options.cleanPathname, null, options.renderMode, options.interceptionContext);
|
|
96
97
|
const cachePromise = (async () => {
|
|
97
98
|
try {
|
|
98
99
|
const rscData = await capturedRscDataPromise;
|
|
@@ -38,6 +38,7 @@ type RenderAppPageCacheArtifactsResult = {
|
|
|
38
38
|
cacheControl?: CacheControlMetadata;
|
|
39
39
|
html: string;
|
|
40
40
|
htmlRenderObservation: ReturnType<typeof createAppPageRenderObservation>;
|
|
41
|
+
linkHeader?: string;
|
|
41
42
|
rscData?: ArrayBuffer;
|
|
42
43
|
rscRenderObservation?: ReturnType<typeof createAppPageRenderObservation>;
|
|
43
44
|
tags: string[];
|
|
@@ -2,9 +2,9 @@ import { consumeDynamicUsage, consumeInvalidDynamicUsageError } from "../shims/h
|
|
|
2
2
|
import { _consumeRequestScopedCacheLife } from "../shims/cache-request-state.js";
|
|
3
3
|
import { getCollectedFetchTags } from "../shims/fetch-cache.js";
|
|
4
4
|
import { readStreamAsText } from "../utils/text-stream.js";
|
|
5
|
-
import { teeAppPageRscStreamForCapture } from "./app-page-execution.js";
|
|
5
|
+
import { buildAppPageFontLinkHeader, teeAppPageRscStreamForCapture } from "./app-page-execution.js";
|
|
6
6
|
import { consumeAppPageRenderObservationState, createAppPageHtmlOutputScope, createAppPageRenderObservation, createAppPageRscOutputScope } from "./app-page-render-observation.js";
|
|
7
|
-
import { isAppSsrRenderResult } from "./app-page-stream.js";
|
|
7
|
+
import { buildAppPageLinkHeader, isAppSsrRenderResult } from "./app-page-stream.js";
|
|
8
8
|
import { buildAppPageTags } from "./implicit-tags.js";
|
|
9
9
|
//#region src/server/app-page-cache-render.ts
|
|
10
10
|
/**
|
|
@@ -16,10 +16,11 @@ import { buildAppPageTags } from "./implicit-tags.js";
|
|
|
16
16
|
async function renderAppPageCacheArtifacts(options) {
|
|
17
17
|
const rscCapture = teeAppPageRscStreamForCapture(options.renderToReadableStream(options.element, { onError: options.onError }), options.captureRscData);
|
|
18
18
|
const capturedRscDataRef = { value: null };
|
|
19
|
+
const fontPreloads = options.getFontPreloads();
|
|
19
20
|
const htmlResult = await (await options.loadSsrHandler()).handleSsr(rscCapture.ssrStream, options.getNavigationContext(), {
|
|
20
21
|
links: options.getFontLinks(),
|
|
21
22
|
styles: options.getFontStyles(),
|
|
22
|
-
preloads:
|
|
23
|
+
preloads: fontPreloads
|
|
23
24
|
}, {
|
|
24
25
|
basePath: options.basePath,
|
|
25
26
|
clientTraceMetadata: options.clientTraceMetadata,
|
|
@@ -31,7 +32,9 @@ async function renderAppPageCacheArtifacts(options) {
|
|
|
31
32
|
capturedRscDataRef
|
|
32
33
|
} : {}
|
|
33
34
|
});
|
|
34
|
-
const
|
|
35
|
+
const htmlStream = isAppSsrRenderResult(htmlResult) ? htmlResult.htmlStream : htmlResult;
|
|
36
|
+
const linkHeader = buildAppPageLinkHeader(isAppSsrRenderResult(htmlResult) ? htmlResult.linkHeader : void 0, buildAppPageFontLinkHeader(fontPreloads), options.reactMaxHeadersLength);
|
|
37
|
+
const html = await readStreamAsText(htmlStream);
|
|
35
38
|
let rscData;
|
|
36
39
|
if (options.captureRscData) {
|
|
37
40
|
const capturedPromise = capturedRscDataRef.value;
|
|
@@ -60,6 +63,7 @@ async function renderAppPageCacheArtifacts(options) {
|
|
|
60
63
|
params: options.navigationParams,
|
|
61
64
|
state: observationState
|
|
62
65
|
}),
|
|
66
|
+
...linkHeader ? { linkHeader } : {},
|
|
63
67
|
tags,
|
|
64
68
|
cacheControl: typeof cacheLife?.revalidate === "number" ? {
|
|
65
69
|
revalidate: cacheLife.revalidate,
|
|
@@ -4,7 +4,7 @@ import { applyCdnResponseHeaders } from "./cache-control.js";
|
|
|
4
4
|
import { decideIsr } from "./isr-decision.js";
|
|
5
5
|
import { buildAppPageCacheValue } from "./isr-cache.js";
|
|
6
6
|
import { encodeCacheTag } from "../utils/encode-cache-tag.js";
|
|
7
|
-
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
|
|
7
|
+
import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader } from "./app-rsc-cache-busting.js";
|
|
8
8
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
9
9
|
import { applyEdgeRuntimeHeader } from "./app-page-response.js";
|
|
10
10
|
import { hasCompleteNegativeRequestApiProof } from "./cache-proof.js";
|
|
@@ -19,7 +19,7 @@ function recordAppPageCacheOutcome(recordCacheOutcome, input) {
|
|
|
19
19
|
function buildAppPageCacheTags(pathname, extraTags) {
|
|
20
20
|
const tags = [
|
|
21
21
|
pathname,
|
|
22
|
-
`_N_T_${pathname}`,
|
|
22
|
+
`_N_T_${pathname.length > 1 && pathname.endsWith("/") ? pathname.slice(0, -1) : pathname}`,
|
|
23
23
|
"_N_T_/layout"
|
|
24
24
|
];
|
|
25
25
|
const segments = pathname.split("/");
|
|
@@ -43,6 +43,8 @@ function buildAppPageCachedHeaders(options) {
|
|
|
43
43
|
applyCdnResponseHeaders(headers, { cacheControl: options.cacheControl });
|
|
44
44
|
setCacheStateHeaders(headers, options.cacheState);
|
|
45
45
|
applyEdgeRuntimeHeader(headers, options.isEdgeRuntime);
|
|
46
|
+
if (options.linkHeader) if (Array.isArray(options.linkHeader)) for (const value of options.linkHeader) headers.append("Link", value);
|
|
47
|
+
else headers.set("Link", options.linkHeader);
|
|
46
48
|
if (options.mountedSlotsHeader) headers.set(VINEXT_MOUNTED_SLOTS_HEADER, options.mountedSlotsHeader);
|
|
47
49
|
mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders ?? null);
|
|
48
50
|
return headers;
|
|
@@ -53,6 +55,15 @@ function getCachedAppPageValue(entry) {
|
|
|
53
55
|
function hasQueryInvariantAppPageProof(cachedValue) {
|
|
54
56
|
return cachedValue.renderObservation !== void 0 && hasCompleteNegativeRequestApiProof(cachedValue.renderObservation, ["searchParams"]);
|
|
55
57
|
}
|
|
58
|
+
function resolveRegeneratedAppPageCachePolicy(options) {
|
|
59
|
+
let revalidateSeconds = options.routeRevalidateSeconds;
|
|
60
|
+
const renderRevalidateSeconds = options.renderCacheControl?.revalidate;
|
|
61
|
+
if (renderRevalidateSeconds !== void 0) revalidateSeconds = revalidateSeconds > 0 ? Math.min(revalidateSeconds, renderRevalidateSeconds) : renderRevalidateSeconds;
|
|
62
|
+
return {
|
|
63
|
+
expireSeconds: options.renderCacheControl?.expire ?? options.expireSeconds,
|
|
64
|
+
revalidateSeconds
|
|
65
|
+
};
|
|
66
|
+
}
|
|
56
67
|
function buildAppPageCachedResponse(cachedValue, options) {
|
|
57
68
|
const status = options.middlewareStatus ?? (cachedValue.status || 200);
|
|
58
69
|
const { cacheControl } = decideIsr({
|
|
@@ -73,6 +84,7 @@ function buildAppPageCachedResponse(cachedValue, options) {
|
|
|
73
84
|
mountedSlotsHeader: options.mountedSlotsHeader
|
|
74
85
|
});
|
|
75
86
|
applyRscCompatibilityIdHeader(rscHeaders);
|
|
87
|
+
applyRscDeploymentIdHeader(rscHeaders);
|
|
76
88
|
return new Response(cachedValue.rscData, {
|
|
77
89
|
status,
|
|
78
90
|
headers: rscHeaders
|
|
@@ -84,6 +96,7 @@ function buildAppPageCachedResponse(cachedValue, options) {
|
|
|
84
96
|
cacheState: options.cacheState,
|
|
85
97
|
contentType: "text/html; charset=utf-8",
|
|
86
98
|
isEdgeRuntime: options.isEdgeRuntime,
|
|
99
|
+
linkHeader: cachedValue.headers?.link,
|
|
87
100
|
middlewareHeaders: options.middlewareHeaders
|
|
88
101
|
});
|
|
89
102
|
return new Response(cachedValue.html, {
|
|
@@ -115,7 +128,11 @@ async function serveAppPageCachedHtml(options, transformValue) {
|
|
|
115
128
|
return response;
|
|
116
129
|
}
|
|
117
130
|
async function readAppPageCacheResponse(options) {
|
|
118
|
-
|
|
131
|
+
if (options.isRscRequest && options.mountedSlotsHeader) {
|
|
132
|
+
options.isrDebug?.("MISS (mounted slots RSC variant)", options.cleanPathname);
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
const isrKey = options.isRscRequest ? options.isrRscKey(options.cleanPathname, null, options.renderMode, options.interceptionContext) : options.isrHtmlKey(options.cleanPathname);
|
|
119
136
|
const artifact = options.isRscRequest ? "rsc" : "html";
|
|
120
137
|
try {
|
|
121
138
|
const cached = await options.isrGet(isrKey);
|
|
@@ -174,10 +191,13 @@ async function readAppPageCacheResponse(options) {
|
|
|
174
191
|
if (cached?.isStale && cachedValue) {
|
|
175
192
|
options.scheduleBackgroundRegeneration(isrKey, async () => {
|
|
176
193
|
const revalidatedPage = await options.renderFreshPageForCache();
|
|
177
|
-
const
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
194
|
+
const cachePolicy = resolveRegeneratedAppPageCachePolicy({
|
|
195
|
+
expireSeconds: options.expireSeconds,
|
|
196
|
+
renderCacheControl: revalidatedPage.cacheControl,
|
|
197
|
+
routeRevalidateSeconds: options.revalidateSeconds
|
|
198
|
+
});
|
|
199
|
+
const writes = [options.isrSet(options.isRscRequest ? isrKey : options.isrRscKey(options.cleanPathname, null, options.renderMode, options.interceptionContext), buildAppPageCacheValue("", revalidatedPage.rscData, 200, revalidatedPage.rscRenderObservation), cachePolicy.revalidateSeconds, revalidatedPage.tags, cachePolicy.expireSeconds)];
|
|
200
|
+
if (!options.isRscRequest) writes.push(options.isrSet(isrKey, buildAppPageCacheValue(revalidatedPage.html, void 0, 200, revalidatedPage.htmlRenderObservation, revalidatedPage.linkHeader ? { link: revalidatedPage.linkHeader } : void 0), cachePolicy.revalidateSeconds, revalidatedPage.tags, cachePolicy.expireSeconds));
|
|
181
201
|
await Promise.all(writes);
|
|
182
202
|
options.isrDebug?.("regen complete", options.cleanPathname);
|
|
183
203
|
});
|
|
@@ -199,6 +199,7 @@ type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
|
|
|
199
199
|
}>;
|
|
200
200
|
request: Request;
|
|
201
201
|
revalidateSeconds: number | null;
|
|
202
|
+
renderedPathAndSearch?: string | null;
|
|
202
203
|
resolveRouteFetchCacheMode?: (route: TRoute) => FetchCacheMode | null;
|
|
203
204
|
resolveRouteDynamicConfig?: (route: TRoute) => string | null | undefined;
|
|
204
205
|
rootForbiddenModule?: AppPageModule | null;
|