@rangojs/router 0.0.0-experimental.bd6e11bc → 0.0.0-experimental.bdaf10aa
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/AGENTS.md +8 -4
- package/README.md +296 -887
- package/dist/bin/rango.js +459 -91
- package/dist/testing/vitest.js +36 -2
- package/dist/vite/index.js +1708 -414
- package/package.json +35 -10
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +82 -5
- package/skills/bundle-analysis/SKILL.md +2 -2
- package/skills/cache-guide/SKILL.md +14 -9
- package/skills/caching/SKILL.md +221 -12
- package/skills/catalog.json +271 -0
- package/skills/comparison/SKILL.md +50 -0
- package/skills/comparison/agents/openai.yaml +4 -0
- package/skills/comparison/references/framework-comparison.md +837 -0
- package/skills/composability/SKILL.md +83 -2
- package/skills/css/SKILL.md +76 -0
- package/skills/debug-manifest/SKILL.md +5 -3
- package/skills/defer-hydration/SKILL.md +235 -0
- package/skills/document-cache/SKILL.md +11 -3
- package/skills/fonts/SKILL.md +1 -1
- package/skills/handler-use/SKILL.md +9 -9
- package/skills/hooks/SKILL.md +73 -900
- package/skills/hooks/data.md +273 -0
- package/skills/hooks/handle-and-actions.md +103 -0
- package/skills/hooks/navigation.md +110 -0
- package/skills/hooks/outlets.md +41 -0
- package/skills/hooks/state.md +228 -0
- package/skills/hooks/urls.md +135 -0
- package/skills/host-router/SKILL.md +84 -7
- package/skills/i18n/SKILL.md +1 -1
- package/skills/intercept/SKILL.md +51 -17
- package/skills/layout/SKILL.md +38 -16
- package/skills/links/SKILL.md +1 -1
- package/skills/loader/SKILL.md +48 -20
- package/skills/middleware/SKILL.md +11 -5
- package/skills/migrate-nextjs/SKILL.md +203 -20
- package/skills/migrate-react-router/SKILL.md +59 -675
- package/skills/migrate-react-router/cloudflare-workers.md +129 -0
- package/skills/migrate-react-router/component-migration.md +196 -0
- package/skills/migrate-react-router/data-and-actions.md +225 -0
- package/skills/migrate-react-router/route-mapping.md +271 -0
- package/skills/mime-routes/SKILL.md +3 -3
- package/skills/observability/SKILL.md +70 -5
- package/skills/parallel/SKILL.md +32 -8
- package/skills/ppr/SKILL.md +622 -0
- package/skills/prerender/SKILL.md +59 -28
- package/skills/rango/SKILL.md +124 -50
- package/skills/response-routes/SKILL.md +78 -46
- package/skills/route/SKILL.md +85 -6
- package/skills/router-setup/SKILL.md +41 -6
- package/skills/scripts/SKILL.md +179 -0
- package/skills/server-actions/SKILL.md +28 -3
- package/skills/shell-manifest/SKILL.md +185 -0
- package/skills/streams-and-websockets/SKILL.md +1 -1
- package/skills/tailwind/SKILL.md +28 -4
- package/skills/testing/SKILL.md +68 -654
- package/skills/testing/bindings.md +103 -0
- package/skills/testing/cache-prerender.md +127 -0
- package/skills/testing/client-components.md +124 -0
- package/skills/testing/e2e-parity.md +125 -0
- package/skills/testing/flight.md +91 -0
- package/skills/testing/handles.md +131 -0
- package/skills/testing/loader.md +128 -0
- package/skills/testing/middleware.md +99 -0
- package/skills/testing/render-handler.md +122 -0
- package/skills/testing/response-routes.md +95 -0
- package/skills/testing/reverse-and-types.md +85 -0
- package/skills/testing/server-actions.md +107 -0
- package/skills/testing/server-tree.md +128 -0
- package/skills/testing/setup.md +123 -0
- package/skills/theme/SKILL.md +1 -1
- package/skills/typesafety/SKILL.md +45 -918
- package/skills/typesafety/env-and-bindings.md +254 -0
- package/skills/typesafety/generated-files-and-cli.md +335 -0
- package/skills/typesafety/params-and-search.md +153 -0
- package/skills/typesafety/route-types.md +209 -0
- package/skills/use-cache/SKILL.md +47 -17
- package/skills/vercel/SKILL.md +128 -0
- package/skills/view-transitions/SKILL.md +44 -1
- package/src/__augment-tests__/augmented.check.ts +2 -3
- package/src/__internal.ts +0 -65
- package/src/browser/action-coordinator.ts +1 -1
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/app-shell.ts +14 -27
- package/src/browser/connection-warmup.ts +134 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +178 -100
- package/src/browser/invalidate-client-cache.ts +52 -0
- package/src/browser/logging.ts +28 -0
- package/src/browser/merge-segment-loaders.ts +6 -4
- package/src/browser/navigation-bridge.ts +81 -68
- package/src/browser/navigation-client.ts +115 -70
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +153 -88
- package/src/browser/navigation-transaction.ts +0 -32
- package/src/browser/network-error-handler.ts +34 -7
- package/src/browser/partial-update.ts +157 -144
- package/src/browser/prefetch/cache.ts +148 -81
- package/src/browser/prefetch/fetch.ts +231 -51
- package/src/browser/prefetch/queue.ts +25 -7
- package/src/browser/rango-state.ts +157 -115
- package/src/browser/react/Link.tsx +40 -7
- package/src/browser/react/NavigationProvider.tsx +140 -99
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/filter-segment-order.ts +17 -2
- package/src/browser/react/index.ts +0 -51
- package/src/browser/react/location-state-shared.ts +14 -15
- package/src/browser/react/location-state.ts +0 -1
- package/src/browser/react/use-action.ts +6 -15
- package/src/browser/react/use-handle.ts +0 -5
- package/src/browser/react/use-href.tsx +8 -1
- package/src/browser/react/use-link-status.ts +33 -8
- package/src/browser/react/use-navigation.ts +10 -5
- package/src/browser/react/use-params.ts +0 -2
- package/src/browser/react/use-router.ts +6 -4
- package/src/browser/react/use-search-params.ts +0 -5
- package/src/browser/react/use-segments.ts +0 -13
- package/src/browser/response-adapter.ts +74 -8
- package/src/browser/rsc-router.tsx +97 -22
- package/src/browser/scroll-restoration.ts +15 -8
- package/src/browser/segment-reconciler.ts +31 -21
- package/src/browser/server-action-bridge.ts +216 -38
- package/src/browser/types.ts +94 -22
- package/src/browser/validate-redirect-origin.ts +43 -16
- package/src/build/generate-manifest.ts +155 -131
- package/src/build/generate-route-types.ts +1 -1
- package/src/build/index.ts +11 -5
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +152 -22
- package/src/build/route-types/ast-route-extraction.ts +15 -8
- package/src/build/route-types/codegen.ts +12 -1
- package/src/build/route-types/include-resolution.ts +455 -61
- package/src/build/route-types/param-extraction.ts +6 -3
- package/src/build/route-types/per-module-writer.ts +15 -2
- package/src/build/route-types/router-processing.ts +77 -41
- package/src/build/route-types/source-scan.ts +105 -7
- package/src/build/runtime-discovery.ts +4 -1
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-key-utils.ts +58 -13
- package/src/cache/cache-policy.ts +108 -34
- package/src/cache/cache-runtime.ts +454 -101
- package/src/cache/cache-scope.ts +159 -54
- package/src/cache/cache-tag.ts +149 -0
- package/src/cache/cf/cf-base64.ts +33 -0
- package/src/cache/cf/cf-cache-constants.ts +127 -0
- package/src/cache/cf/cf-cache-store.ts +2170 -377
- package/src/cache/cf/cf-cache-types.ts +349 -0
- package/src/cache/cf/cf-kv-utils.ts +46 -0
- package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
- package/src/cache/cf/index.ts +6 -16
- package/src/cache/document-cache.ts +126 -41
- package/src/cache/handle-snapshot.ts +70 -0
- package/src/cache/index.ts +23 -20
- package/src/cache/memory-segment-store.ts +243 -37
- package/src/cache/profile-registry.ts +46 -31
- package/src/cache/read-through-swr.ts +56 -12
- package/src/cache/segment-codec.ts +13 -21
- package/src/cache/shell-snapshot.ts +417 -0
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/types.ts +194 -99
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +1132 -0
- package/src/client.rsc.tsx +39 -22
- package/src/client.tsx +28 -58
- package/src/cloudflare/index.ts +11 -0
- package/src/cloudflare/tracing.ts +108 -0
- package/src/component-utils.ts +19 -0
- package/src/components/DefaultDocument.tsx +8 -2
- package/src/context-var.ts +13 -1
- package/src/decode-loader-results.ts +18 -2
- package/src/defer.ts +185 -0
- package/src/deps/ssr.ts +0 -1
- package/src/encode-kv.ts +49 -0
- package/src/errors.ts +0 -3
- package/src/escape-script.ts +52 -0
- package/src/handle.ts +57 -40
- package/src/handles/MetaTags.tsx +24 -53
- package/src/handles/Scripts.tsx +183 -0
- package/src/handles/breadcrumbs.ts +35 -8
- package/src/handles/deferred-resolution.ts +127 -0
- package/src/handles/is-thenable.ts +18 -0
- package/src/handles/meta.ts +14 -40
- package/src/handles/script.ts +244 -0
- package/src/host/cookie-handler.ts +9 -60
- package/src/host/errors.ts +13 -22
- package/src/host/index.ts +7 -0
- package/src/host/pattern-matcher.ts +23 -52
- package/src/host/router.ts +1 -65
- package/src/host/testing.ts +40 -27
- package/src/host/types.ts +6 -2
- package/src/href-client.ts +7 -12
- package/src/index.rsc.ts +88 -8
- package/src/index.ts +90 -16
- package/src/internal-debug.ts +11 -10
- package/src/loader.rsc.ts +19 -9
- package/src/loader.ts +12 -4
- package/src/outlet-provider.tsx +1 -5
- package/src/prerender/param-hash.ts +16 -16
- package/src/prerender/store.ts +32 -37
- package/src/prerender.ts +75 -7
- package/src/redirect-origin.ts +114 -0
- package/src/regex-escape.ts +8 -0
- package/src/render-error-thrower.tsx +20 -0
- package/src/response-utils.ts +25 -0
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +13 -49
- package/src/route-definition/dsl-helpers.ts +60 -53
- package/src/route-definition/helper-factories.ts +0 -2
- package/src/route-definition/helpers-types.ts +46 -46
- package/src/route-definition/index.ts +1 -2
- package/src/route-definition/redirect.ts +44 -11
- package/src/route-definition/resolve-handler-use.ts +6 -1
- package/src/route-definition/use-item-types.ts +3 -6
- package/src/route-map-builder.ts +41 -20
- package/src/route-types.ts +0 -5
- package/src/router/content-negotiation.ts +58 -23
- package/src/router/error-handling.ts +44 -17
- package/src/router/find-match.ts +129 -30
- package/src/router/handler-context.ts +6 -1
- package/src/router/instrument.ts +355 -0
- package/src/router/intercept-resolution.ts +35 -2
- package/src/router/lazy-includes.ts +79 -56
- package/src/router/loader-resolution.ts +151 -73
- package/src/router/logging.ts +0 -6
- package/src/router/manifest.ts +74 -40
- package/src/router/match-api.ts +76 -52
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +181 -178
- package/src/router/match-middleware/background-revalidation.ts +40 -24
- package/src/router/match-middleware/cache-lookup.ts +115 -194
- package/src/router/match-middleware/cache-store.ts +61 -50
- package/src/router/match-middleware/intercept-resolution.ts +0 -22
- package/src/router/match-middleware/segment-resolution.ts +0 -22
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +36 -67
- package/src/router/metrics.ts +0 -34
- package/src/router/middleware-types.ts +0 -116
- package/src/router/middleware.ts +231 -120
- package/src/router/navigation-snapshot.ts +7 -56
- package/src/router/params-util.ts +23 -0
- package/src/router/parse-pattern.ts +115 -0
- package/src/router/pattern-matching.ts +99 -152
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prefetch-limits.ts +37 -0
- package/src/router/prerender-match.ts +111 -66
- package/src/router/preview-match.ts +3 -1
- package/src/router/request-classification.ts +47 -42
- package/src/router/revalidation.ts +75 -81
- package/src/router/route-snapshot.ts +14 -3
- package/src/router/router-context.ts +6 -29
- package/src/router/router-interfaces.ts +70 -8
- package/src/router/router-options.ts +126 -4
- package/src/router/segment-resolution/fresh.ts +104 -80
- package/src/router/segment-resolution/helpers.ts +86 -6
- package/src/router/segment-resolution/loader-cache.ts +155 -39
- package/src/router/segment-resolution/loader-mask.ts +60 -0
- package/src/router/segment-resolution/loader-snapshot.ts +259 -0
- package/src/router/segment-resolution/mask-nested.ts +83 -0
- package/src/router/segment-resolution/revalidation.ts +215 -304
- package/src/router/segment-resolution/static-store.ts +19 -5
- package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
- package/src/router/segment-resolution/view-transition-default.ts +35 -15
- package/src/router/segment-resolution.ts +5 -1
- package/src/router/segment-wrappers.ts +6 -5
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/substitute-pattern-params.ts +54 -35
- package/src/router/telemetry-otel.ts +160 -200
- package/src/router/telemetry.ts +9 -23
- package/src/router/timeout.ts +0 -20
- package/src/router/tracing.ts +215 -0
- package/src/router/trie-matching.ts +171 -64
- package/src/router/types.ts +1 -63
- package/src/router/url-params.ts +13 -5
- package/src/router.ts +119 -48
- package/src/rsc/full-payload.ts +70 -0
- package/src/rsc/handler-context.ts +1 -0
- package/src/rsc/handler.ts +267 -152
- package/src/rsc/helpers.ts +78 -4
- package/src/rsc/index.ts +1 -4
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +114 -38
- package/src/rsc/manifest-init.ts +29 -42
- package/src/rsc/nonce.ts +10 -1
- package/src/rsc/origin-guard.ts +11 -15
- package/src/rsc/progressive-enhancement.ts +120 -13
- package/src/rsc/redirect-guard.ts +100 -0
- package/src/rsc/response-cache-serve.ts +238 -0
- package/src/rsc/response-error.ts +79 -12
- package/src/rsc/response-route-handler.ts +58 -141
- package/src/rsc/rsc-rendering.ts +492 -49
- package/src/rsc/runtime-warnings.ts +14 -0
- package/src/rsc/server-action.ts +268 -82
- package/src/rsc/shell-capture.ts +1190 -0
- package/src/rsc/shell-serve.ts +181 -0
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +45 -3
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +31 -26
- package/src/segment-loader-promise.ts +49 -4
- package/src/segment-system.tsx +260 -95
- package/src/server/context.ts +99 -9
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +125 -2
- package/src/server/handle-store.ts +21 -38
- package/src/server/loader-registry.ts +33 -42
- package/src/server/request-context.ts +379 -138
- package/src/ssr/index.tsx +491 -182
- package/src/ssr/inject-rsc-eager.ts +167 -0
- package/src/ssr/ssr-root.tsx +228 -0
- package/src/static-handler.ts +10 -13
- package/src/testing/cache-status.ts +44 -48
- package/src/testing/collect-handle.ts +14 -31
- package/src/testing/dispatch.ts +533 -160
- package/src/testing/e2e/fixture.ts +45 -11
- package/src/testing/e2e/index.ts +1 -22
- package/src/testing/e2e/matchers.ts +0 -16
- package/src/testing/e2e/parity.ts +85 -4
- package/src/testing/e2e/server.ts +12 -0
- package/src/testing/flight-matchers.ts +7 -14
- package/src/testing/flight-normalize.ts +11 -0
- package/src/testing/flight-runtime.d.ts +36 -0
- package/src/testing/flight-tree.ts +682 -0
- package/src/testing/flight.entry.ts +30 -0
- package/src/testing/flight.ts +145 -70
- package/src/testing/generated-routes.ts +26 -50
- package/src/testing/index.ts +18 -19
- package/src/testing/internal/context.ts +184 -68
- package/src/testing/internal/flight-client-globals.ts +30 -0
- package/src/testing/internal/seed-vars.ts +54 -0
- package/src/testing/render-handler.ts +357 -0
- package/src/testing/render-route.tsx +134 -115
- package/src/testing/run-loader.ts +140 -51
- package/src/testing/run-middleware.ts +59 -33
- package/src/testing/run-transition-when.ts +164 -0
- package/src/testing/vitest-stubs/cloudflare-email.ts +1 -1
- package/src/testing/vitest-stubs/cloudflare-workers.ts +1 -1
- package/src/testing/vitest.ts +138 -16
- package/src/theme/ThemeProvider.tsx +56 -84
- package/src/theme/ThemeScript.tsx +7 -9
- package/src/theme/constants.ts +52 -13
- package/src/theme/index.ts +0 -7
- package/src/theme/theme-context.ts +1 -5
- package/src/theme/theme-script.ts +22 -21
- package/src/theme/use-theme.ts +0 -3
- package/src/types/boundaries.ts +0 -35
- package/src/types/cache-types.ts +13 -4
- package/src/types/error-types.ts +30 -90
- package/src/types/global-namespace.ts +15 -15
- package/src/types/handler-context.ts +45 -15
- package/src/types/index.ts +2 -10
- package/src/types/loader-types.ts +6 -3
- package/src/types/request-scope.ts +8 -22
- package/src/types/route-config.ts +20 -52
- package/src/types/route-entry.ts +0 -6
- package/src/types/segments.ts +100 -13
- package/src/urls/include-helper.ts +10 -12
- package/src/urls/include-provider.ts +71 -0
- package/src/urls/index.ts +2 -8
- package/src/urls/path-helper-types.ts +52 -14
- package/src/urls/path-helper.ts +5 -54
- package/src/urls/pattern-types.ts +36 -0
- package/src/urls/type-extraction.ts +76 -42
- package/src/urls/urls-function.ts +0 -14
- package/src/use-loader.tsx +0 -186
- package/src/vercel/index.ts +11 -0
- package/src/vercel/tracing.ts +88 -0
- package/src/vite/discovery/bundle-postprocess.ts +2 -1
- package/src/vite/discovery/dev-prerender-cache.ts +117 -0
- package/src/vite/discovery/discover-routers.ts +34 -43
- package/src/vite/discovery/discovery-errors.ts +61 -0
- package/src/vite/discovery/prerender-collection.ts +33 -46
- package/src/vite/discovery/state.ts +12 -1
- package/src/vite/discovery/virtual-module-codegen.ts +1 -11
- package/src/vite/index.ts +9 -0
- package/src/vite/inject-client-debug.ts +88 -0
- package/src/vite/plugin-types.ts +143 -10
- package/src/vite/plugins/cjs-to-esm.ts +8 -12
- package/src/vite/plugins/client-ref-dedup.ts +0 -11
- package/src/vite/plugins/client-ref-hashing.ts +0 -10
- package/src/vite/plugins/cloudflare-protocol-stub.ts +0 -20
- package/src/vite/plugins/expose-action-id.ts +2 -73
- package/src/vite/plugins/expose-id-utils.ts +85 -56
- package/src/vite/plugins/expose-ids/export-analysis.ts +30 -43
- package/src/vite/plugins/expose-ids/handler-transform.ts +5 -31
- package/src/vite/plugins/expose-ids/loader-transform.ts +12 -20
- package/src/vite/plugins/expose-ids/router-transform.ts +98 -26
- package/src/vite/plugins/expose-internal-ids.ts +10 -1
- package/src/vite/plugins/performance-tracks.ts +0 -3
- package/src/vite/plugins/refresh-cmd.ts +1 -1
- package/src/vite/plugins/use-cache-transform.ts +21 -46
- package/src/vite/plugins/vercel-output.ts +384 -0
- package/src/vite/plugins/version-injector.ts +22 -27
- package/src/vite/plugins/version-plugin.ts +6 -66
- package/src/vite/plugins/virtual-entries.ts +137 -26
- package/src/vite/rango.ts +146 -135
- package/src/vite/router-discovery.ts +189 -48
- package/src/vite/utils/ast-handler-extract.ts +11 -20
- package/src/vite/utils/bundle-analysis.ts +6 -13
- package/src/vite/utils/client-chunks.ts +0 -6
- package/src/vite/utils/directive-prologue.ts +40 -0
- package/src/vite/utils/forward-user-plugins.ts +0 -22
- package/src/vite/utils/manifest-utils.ts +4 -75
- package/src/vite/utils/package-resolution.ts +1 -73
- package/src/vite/utils/prerender-utils.ts +71 -44
- package/src/vite/utils/shared-utils.ts +55 -37
- package/src/browser/react/use-client-cache.ts +0 -58
- package/src/browser/shallow.ts +0 -40
- package/src/handles/index.ts +0 -7
- package/src/network-error-thrower.tsx +0 -23
- package/src/router/middleware-cookies.ts +0 -55
package/src/router/url-params.ts
CHANGED
|
@@ -25,11 +25,6 @@ export function safeDecodeURIComponent(raw: string): string {
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
// encodeURIComponent over-encodes for path segments. After running it,
|
|
29
|
-
// un-encode the pchar sub-delims + (`:` / `@`) so the resulting URL
|
|
30
|
-
// keeps human-readable characters that are legal in a path segment.
|
|
31
|
-
// Everything dangerous — `/ ? # %` and space/control/non-ASCII — stays
|
|
32
|
-
// encoded.
|
|
33
28
|
const PATH_SAFE_ESCAPES: Record<string, string> = {
|
|
34
29
|
"%3A": ":",
|
|
35
30
|
"%40": "@",
|
|
@@ -47,3 +42,16 @@ export function encodePathSegment(value: string): string {
|
|
|
47
42
|
(match) => PATH_SAFE_ESCAPES[match.toUpperCase()] ?? match,
|
|
48
43
|
);
|
|
49
44
|
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Encode a catch-all remainder: encode each `/`-separated segment but keep the
|
|
48
|
+
* separators, so `a/b c` -> `a/b%20c` (not `a%2Fb%20c`). Shared by the reverse
|
|
49
|
+
* helper and the build-time prerender substitution so both produce identical
|
|
50
|
+
* URLs. `encode` defaults to the path-safe `encodePathSegment`.
|
|
51
|
+
*/
|
|
52
|
+
export function encodePathRemainder(
|
|
53
|
+
value: string,
|
|
54
|
+
encode: (segment: string) => string = encodePathSegment,
|
|
55
|
+
): string {
|
|
56
|
+
return value.split("/").map(encode).join("/");
|
|
57
|
+
}
|
package/src/router.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import { createCacheScope } from "./cache/cache-scope.js";
|
|
3
|
-
import {
|
|
4
|
-
setCacheProfiles,
|
|
5
|
-
resolveCacheProfiles,
|
|
6
|
-
} from "./cache/profile-registry.js";
|
|
3
|
+
import { resolveCacheProfiles } from "./cache/profile-registry.js";
|
|
7
4
|
import { isCachedFunction } from "./cache/taint.js";
|
|
8
5
|
import { assertClientComponent } from "./component-utils.js";
|
|
9
6
|
import { DefaultDocument } from "./components/DefaultDocument.js";
|
|
@@ -21,6 +18,7 @@ import type { AllUseItems } from "./route-types.js";
|
|
|
21
18
|
import type { UrlPatterns } from "./urls.js";
|
|
22
19
|
import type { UrlBuilder } from "./urls/pattern-types.js";
|
|
23
20
|
import { urls } from "./urls.js";
|
|
21
|
+
import { buildPrecomputedByPrefix } from "./build/prefix-tree-utils.js";
|
|
24
22
|
import {
|
|
25
23
|
type EntryData,
|
|
26
24
|
getContext,
|
|
@@ -65,15 +63,17 @@ import {
|
|
|
65
63
|
import { loadManifest } from "./router/manifest.js";
|
|
66
64
|
import { createMetricsStore } from "./router/metrics.js";
|
|
67
65
|
import {
|
|
68
|
-
|
|
66
|
+
compileMiddlewarePattern,
|
|
69
67
|
type MiddlewareEntry,
|
|
70
68
|
type MiddlewareFn,
|
|
71
69
|
} from "./router/middleware.js";
|
|
72
70
|
import {
|
|
73
71
|
extractStaticPrefix,
|
|
72
|
+
joinPrefix,
|
|
74
73
|
traverseBack,
|
|
75
74
|
} from "./router/pattern-matching.js";
|
|
76
75
|
import { resolveSink, safeEmit, getRequestId } from "./router/telemetry.js";
|
|
76
|
+
import { resolveTracing } from "./router/tracing.js";
|
|
77
77
|
import { evaluateRevalidation } from "./router/revalidation.js";
|
|
78
78
|
import {
|
|
79
79
|
type RouterContext,
|
|
@@ -109,6 +109,12 @@ import {
|
|
|
109
109
|
matchForPrerender as _matchForPrerender,
|
|
110
110
|
renderStaticSegment as _renderStaticSegment,
|
|
111
111
|
} from "./router/prerender-match.js";
|
|
112
|
+
import { resolveStateCookieName } from "./router/state-cookie-name.js";
|
|
113
|
+
import { resolvePrefetchCacheTTL } from "./router/prefetch-cache-ttl.js";
|
|
114
|
+
import {
|
|
115
|
+
resolvePrefetchCacheSize,
|
|
116
|
+
resolvePrefetchConcurrency,
|
|
117
|
+
} from "./router/prefetch-limits.js";
|
|
112
118
|
|
|
113
119
|
// Re-export public types and values from extracted modules
|
|
114
120
|
export { RSC_ROUTER_BRAND, RouterRegistry } from "./router/router-registry.js";
|
|
@@ -148,9 +154,13 @@ export function createRouter<TEnv = any>(
|
|
|
148
154
|
nonce,
|
|
149
155
|
version,
|
|
150
156
|
prefetchCacheTTL: prefetchCacheTTLOption,
|
|
157
|
+
prefetchCacheSize: prefetchCacheSizeOption,
|
|
158
|
+
prefetchConcurrency: prefetchConcurrencyOption,
|
|
159
|
+
stateCookiePrefix: stateCookiePrefixOption,
|
|
151
160
|
warmup: warmupOption,
|
|
152
161
|
allowDebugManifest: allowDebugManifestOption = false,
|
|
153
162
|
telemetry: telemetrySink,
|
|
163
|
+
tracing: tracingOption,
|
|
154
164
|
ssr: ssrOption,
|
|
155
165
|
timeout: timeoutShorthand,
|
|
156
166
|
timeouts: timeoutsOption,
|
|
@@ -158,6 +168,7 @@ export function createRouter<TEnv = any>(
|
|
|
158
168
|
originCheck: originCheckOption,
|
|
159
169
|
viewTransition: viewTransitionOption = "auto",
|
|
160
170
|
debugCacheSignal: debugCacheSignalOption = false,
|
|
171
|
+
strictMode: strictModeOption = true,
|
|
161
172
|
} = options;
|
|
162
173
|
|
|
163
174
|
// Debug cache signal gate (DEVELOPMENT/TEST ONLY). Enabled by the
|
|
@@ -177,11 +188,14 @@ export function createRouter<TEnv = any>(
|
|
|
177
188
|
// Resolve telemetry sink (no-op when not configured)
|
|
178
189
|
const telemetry = resolveSink(telemetrySink);
|
|
179
190
|
|
|
180
|
-
// Resolve
|
|
181
|
-
//
|
|
182
|
-
|
|
191
|
+
// Resolve span tracing (undefined when not configured; every traceSpan() call
|
|
192
|
+
// is then a direct pass-through with zero behavior change).
|
|
193
|
+
const resolvedTracing = resolveTracing(tracingOption);
|
|
194
|
+
|
|
195
|
+
// Resolve cache profiles: merge user config with the guaranteed default
|
|
196
|
+
// profile. This resolved map is threaded onto each request context; the
|
|
197
|
+
// "use cache: <profile>" runtime path reads it request-scoped.
|
|
183
198
|
const resolvedCacheProfiles = resolveCacheProfiles(cacheProfilesOption);
|
|
184
|
-
setCacheProfiles(resolvedCacheProfiles);
|
|
185
199
|
|
|
186
200
|
// Source file: prefer Vite-injected path (zero cost), fall back to
|
|
187
201
|
// stack trace parsing for non-Vite environments (e.g. tests).
|
|
@@ -216,21 +230,40 @@ export function createRouter<TEnv = any>(
|
|
|
216
230
|
const routerId =
|
|
217
231
|
userProvidedId ?? injectedId ?? `router_${nextRouterAutoId()}`;
|
|
218
232
|
|
|
219
|
-
// Resolve
|
|
220
|
-
//
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
233
|
+
// Resolve the rango state cookie name once, here, so the two cookie writers
|
|
234
|
+
// (the client document.cookie writer and the server Set-Cookie writer)
|
|
235
|
+
// consume one pre-composed name and cannot drift.
|
|
236
|
+
const resolvedStateCookieName = resolveStateCookieName(
|
|
237
|
+
stateCookiePrefixOption,
|
|
238
|
+
routerId,
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
// Resolve prefetch cache TTL (default: 300 seconds / 5 minutes). Clamps to a
|
|
242
|
+
// non-negative integer and guards non-finite (NaN/Infinity) inputs so a
|
|
243
|
+
// malformed `Cache-Control: max-age=NaN` can never reach the wire.
|
|
244
|
+
const resolvedPrefetchCacheTTL = resolvePrefetchCacheTTL(
|
|
245
|
+
prefetchCacheTTLOption,
|
|
246
|
+
);
|
|
247
|
+
const prefetchCacheTTL = resolvedPrefetchCacheTTL.ms;
|
|
226
248
|
const prefetchCacheControl: string | false =
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
249
|
+
resolvedPrefetchCacheTTL.cacheControl;
|
|
250
|
+
|
|
251
|
+
// Resolve client-side prefetch limits (in-memory cache size and queue
|
|
252
|
+
// concurrency). Both are positive-integer counts; sub-1/non-finite inputs
|
|
253
|
+
// fall back to the defaults. Shipped to the client in payload metadata.
|
|
254
|
+
const prefetchCacheSize = resolvePrefetchCacheSize(prefetchCacheSizeOption);
|
|
255
|
+
const prefetchConcurrency = resolvePrefetchConcurrency(
|
|
256
|
+
prefetchConcurrencyOption,
|
|
257
|
+
);
|
|
230
258
|
|
|
231
259
|
// Resolve warmup enabled flag (default: true)
|
|
232
260
|
const warmupEnabled = warmupOption !== false;
|
|
233
261
|
|
|
262
|
+
// Resolve StrictMode flag (default: true). Shipped to the client in payload
|
|
263
|
+
// metadata; the browser entry reads it once to decide whether to wrap the
|
|
264
|
+
// hydrated tree in React.StrictMode.
|
|
265
|
+
const strictMode = strictModeOption !== false;
|
|
266
|
+
|
|
234
267
|
// Resolve theme config (null if theme not enabled)
|
|
235
268
|
const resolvedThemeConfig = themeOption
|
|
236
269
|
? resolveThemeConfig(themeOption)
|
|
@@ -262,9 +295,14 @@ export function createRouter<TEnv = any>(
|
|
|
262
295
|
invokeOnError(onError, error, phase, context, "Router");
|
|
263
296
|
}
|
|
264
297
|
|
|
265
|
-
// Validate document is a client component
|
|
298
|
+
// Validate document is a client component. Under a test runner the "use
|
|
299
|
+
// client" transform has not run, so a real exported document has no marker;
|
|
300
|
+
// allowServerInTest lets the router construct in a bare unit test (for
|
|
301
|
+
// dispatch / assertGeneratedRoutesMatch) while a real build still throws.
|
|
266
302
|
if (documentOption !== undefined) {
|
|
267
|
-
assertClientComponent(documentOption, "document"
|
|
303
|
+
assertClientComponent(documentOption, "document", {
|
|
304
|
+
allowServerInTest: true,
|
|
305
|
+
});
|
|
268
306
|
}
|
|
269
307
|
|
|
270
308
|
// Use default document if none provided (keeps internal name as rootLayout)
|
|
@@ -328,7 +366,7 @@ export function createRouter<TEnv = any>(
|
|
|
328
366
|
let regex: RegExp | null = null;
|
|
329
367
|
let paramNames: string[] = [];
|
|
330
368
|
if (fullPattern) {
|
|
331
|
-
const parsed =
|
|
369
|
+
const parsed = compileMiddlewarePattern(fullPattern);
|
|
332
370
|
regex = parsed.regex;
|
|
333
371
|
paramNames = parsed.paramNames;
|
|
334
372
|
}
|
|
@@ -338,7 +376,6 @@ export function createRouter<TEnv = any>(
|
|
|
338
376
|
regex,
|
|
339
377
|
paramNames,
|
|
340
378
|
handler,
|
|
341
|
-
mountPrefix,
|
|
342
379
|
});
|
|
343
380
|
}
|
|
344
381
|
|
|
@@ -372,23 +409,28 @@ export function createRouter<TEnv = any>(
|
|
|
372
409
|
getRouterPrecomputedEntries(routerId) ?? getPrecomputedEntries();
|
|
373
410
|
if (current !== precomputedSource) {
|
|
374
411
|
precomputedSource = current;
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
412
|
+
// buildPrecomputedByPrefix drops any staticPrefix owned by more than one
|
|
413
|
+
// leaf include instead of collapsing it last-wins (which would mis-assign
|
|
414
|
+
// one include's routes to another's entry and 500 a valid sibling route).
|
|
415
|
+
// Such shared-prefix includes resolve via the handler path instead.
|
|
416
|
+
precomputedByPrefix = current ? buildPrecomputedByPrefix(current) : null;
|
|
378
417
|
}
|
|
379
418
|
return precomputedByPrefix;
|
|
380
419
|
}
|
|
381
420
|
|
|
382
421
|
// Wrapper to pass debugPerformance to external createMetricsStore.
|
|
383
422
|
// Also checks per-request flag set by ctx.debugPerformance() in middleware.
|
|
423
|
+
// With no active request context there is nowhere to hang the store, so return
|
|
424
|
+
// undefined: an orphan store would collect metrics no reader can reach (nothing
|
|
425
|
+
// holds it, and appendMetric(undefined, ...) is already a no-op).
|
|
384
426
|
const getMetricsStore = () => {
|
|
385
427
|
const reqCtx = _getRequestContext();
|
|
386
428
|
const enabled = debugPerformance || !!reqCtx?._debugPerformance;
|
|
387
|
-
if (!enabled) return undefined;
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
reqCtx._metricsStore ??= createMetricsStore(true);
|
|
429
|
+
if (!enabled || !reqCtx) return undefined;
|
|
430
|
+
// Anchor a mid-request store to the true request entry (reqCtx._handlerStart),
|
|
431
|
+
// not this call's performance.now(); undefined falls back to now() inside
|
|
432
|
+
// createMetricsStore (metrics.ts).
|
|
433
|
+
reqCtx._metricsStore ??= createMetricsStore(true, reqCtx._handlerStart);
|
|
392
434
|
return reqCtx._metricsStore;
|
|
393
435
|
};
|
|
394
436
|
|
|
@@ -399,11 +441,6 @@ export function createRouter<TEnv = any>(
|
|
|
399
441
|
const findNearestNotFoundBoundary = (entry: EntryData | null) =>
|
|
400
442
|
findNotFoundBoundary(entry, defaultNotFoundBoundary);
|
|
401
443
|
|
|
402
|
-
// Helper to get handleStore from request context
|
|
403
|
-
const getHandleStore = (): HandleStore | undefined => {
|
|
404
|
-
return _getRequestContext()?._handleStore;
|
|
405
|
-
};
|
|
406
|
-
|
|
407
444
|
// Track a pending handler promise (non-blocking).
|
|
408
445
|
// Attaches a side-effect .catch() to report streaming handler errors to onError
|
|
409
446
|
// without altering the rejection chain (React's streaming error boundary still handles it).
|
|
@@ -414,13 +451,14 @@ export function createRouter<TEnv = any>(
|
|
|
414
451
|
segmentType?: string;
|
|
415
452
|
},
|
|
416
453
|
): Promise<T> => {
|
|
417
|
-
|
|
454
|
+
// One ALS read serves both the store lookup and the onError closure.
|
|
455
|
+
const reqCtx = _getRequestContext();
|
|
456
|
+
const store = reqCtx?._handleStore;
|
|
418
457
|
const tracked = store ? store.track(promise) : promise;
|
|
419
458
|
|
|
420
459
|
// Report streaming handler errors to onError as a side-effect.
|
|
421
460
|
// The rejection still propagates to the RSC stream for client error boundaries.
|
|
422
461
|
// Captures request context eagerly (closure) so the catch handler has full context.
|
|
423
|
-
const reqCtx = _getRequestContext();
|
|
424
462
|
if (reqCtx && onError) {
|
|
425
463
|
tracked.catch((error) => {
|
|
426
464
|
callOnError(error, "handler", {
|
|
@@ -462,8 +500,12 @@ export function createRouter<TEnv = any>(
|
|
|
462
500
|
? getRequestId(errorContext.request)
|
|
463
501
|
: undefined
|
|
464
502
|
: undefined;
|
|
503
|
+
// Derived once here for both the loader.start and loader.end emits (the
|
|
504
|
+
// loader.error emit uses ctx.loaderName from wrapLoaderWithErrorHandling).
|
|
505
|
+
const loaderName = telemetrySink
|
|
506
|
+
? segmentId.split(".").pop() || "unknown"
|
|
507
|
+
: "";
|
|
465
508
|
if (telemetrySink) {
|
|
466
|
-
const loaderName = segmentId.split(".").pop() || "unknown";
|
|
467
509
|
safeEmit(telemetry, {
|
|
468
510
|
type: "loader.start",
|
|
469
511
|
timestamp: loaderStart,
|
|
@@ -517,7 +559,6 @@ export function createRouter<TEnv = any>(
|
|
|
517
559
|
|
|
518
560
|
// Emit loader.end after the promise settles (fire-and-forget)
|
|
519
561
|
if (telemetrySink) {
|
|
520
|
-
const loaderName = segmentId.split(".").pop() || "unknown";
|
|
521
562
|
result.then((r) => {
|
|
522
563
|
safeEmit(telemetry, {
|
|
523
564
|
type: "loader.end",
|
|
@@ -581,8 +622,15 @@ export function createRouter<TEnv = any>(
|
|
|
581
622
|
routerId,
|
|
582
623
|
};
|
|
583
624
|
|
|
584
|
-
|
|
585
|
-
|
|
625
|
+
// Must return the Promise from _evaluateLazyEntry: an async include provider
|
|
626
|
+
// (`() => import("./routes")`) resolves off the startup path, and createFindMatch
|
|
627
|
+
// awaits this to know when the import + expansion have completed. Dropping it
|
|
628
|
+
// (typing this `void`) makes the import fire-and-forget, so findMatch spins the
|
|
629
|
+
// lazy-eval retry loop to its cap and returns null on the first request to any
|
|
630
|
+
// async include whose prefix isn't already covered by a unique precomputed entry
|
|
631
|
+
// (nested includes, shared prefixes, regex fallback).
|
|
632
|
+
function evaluateLazyEntry(entry: RouteEntry<TEnv>): void | Promise<void> {
|
|
633
|
+
return _evaluateLazyEntry(entry, lazyEvalDeps);
|
|
586
634
|
}
|
|
587
635
|
|
|
588
636
|
// Create findMatch with single-entry cache, bound to router state
|
|
@@ -842,10 +890,13 @@ export function createRouter<TEnv = any>(
|
|
|
842
890
|
|
|
843
891
|
// Create placeholder RouteEntry for each lazy include
|
|
844
892
|
for (const lazyInclude of lazyIncludes) {
|
|
845
|
-
// Compute the full URL prefix (combining parent prefix if any)
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
893
|
+
// Compute the full URL prefix (combining parent prefix if any). Use the
|
|
894
|
+
// slash-collapsing join so a trailing-slash parent prefix does not
|
|
895
|
+
// produce a double-slash staticPrefix the trie's sp can never match.
|
|
896
|
+
const fullPrefix = joinPrefix(
|
|
897
|
+
lazyInclude.context.urlPrefix,
|
|
898
|
+
lazyInclude.prefix,
|
|
899
|
+
);
|
|
849
900
|
|
|
850
901
|
const lazyEntry: RouteEntry<TEnv> & { _lazyPrefix?: string } = {
|
|
851
902
|
prefix: "",
|
|
@@ -940,13 +991,31 @@ export function createRouter<TEnv = any>(
|
|
|
940
991
|
// Expose prefetch cache settings
|
|
941
992
|
prefetchCacheControl,
|
|
942
993
|
prefetchCacheTTL,
|
|
994
|
+
prefetchCacheSize,
|
|
995
|
+
prefetchConcurrency,
|
|
996
|
+
|
|
997
|
+
// Expose the resolved rango state cookie name for the server-side writer
|
|
998
|
+
// (invalidateClientCache) and for shipping to the client in metadata.
|
|
999
|
+
resolvedStateCookieName,
|
|
943
1000
|
|
|
944
1001
|
// Expose warmup enabled flag for handler and client
|
|
945
1002
|
warmupEnabled,
|
|
946
1003
|
|
|
1004
|
+
// Expose StrictMode flag for the initial-render payload metadata
|
|
1005
|
+
strictMode,
|
|
1006
|
+
|
|
947
1007
|
// Expose router-wide performance debugging for request-level metrics setup
|
|
948
1008
|
debugPerformance,
|
|
949
1009
|
|
|
1010
|
+
// Expose resolved span tracing for the handler (Cloudflare custom spans)
|
|
1011
|
+
tracing: resolvedTracing,
|
|
1012
|
+
|
|
1013
|
+
// Expose the raw telemetry sink so handler-level emitters (timeout, origin
|
|
1014
|
+
// rejection, late-handle handler.error) can emit outside the match ALS.
|
|
1015
|
+
// Raw (not the resolveSink no-op wrapper) so router.telemetry stays
|
|
1016
|
+
// undefined when unconfigured and call sites gate on truthiness.
|
|
1017
|
+
telemetry: telemetrySink,
|
|
1018
|
+
|
|
950
1019
|
// Expose debug manifest flag for handler
|
|
951
1020
|
allowDebugManifest: allowDebugManifestOption,
|
|
952
1021
|
|
|
@@ -1032,8 +1101,10 @@ export function createRouter<TEnv = any>(
|
|
|
1032
1101
|
if (!handler) {
|
|
1033
1102
|
// Lazy import deferred to first request to avoid dev mode issues
|
|
1034
1103
|
const { createRSCHandler } = await import("./rsc/handler.js");
|
|
1035
|
-
// Cast:
|
|
1036
|
-
//
|
|
1104
|
+
// Cast: createRSCHandler receives `router as any`, which erases TEnv
|
|
1105
|
+
// and infers its handler as RouterRequestInput<unknown>. Re-narrow the
|
|
1106
|
+
// returned handler to RouterRequestInput<TEnv> so the call below stays
|
|
1107
|
+
// typed. (The handler already accepts (request, RouterRequestInput).)
|
|
1037
1108
|
handler = createRSCHandler({
|
|
1038
1109
|
router: router as any,
|
|
1039
1110
|
cache,
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Full (initial-load / document) RSC payload builder.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from rsc-rendering.ts so both the foreground render AND the PPR
|
|
5
|
+
* background shell capture (shell-capture.ts) build the SAME payload shape over
|
|
6
|
+
* their own handle store. `resume` requires the captured tree to match the served
|
|
7
|
+
* tree; building an identical payload over the same replayed segments is what
|
|
8
|
+
* makes that hold. Keep this byte-identical to the normal full-render path.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { MatchResult } from "../types.js";
|
|
12
|
+
import type { RscPayload } from "./types.js";
|
|
13
|
+
import type { HandlerContext } from "./handler-context.js";
|
|
14
|
+
import type { RequestContext } from "../server/request-context.js";
|
|
15
|
+
import type { HandleStore } from "../server/handle-store.js";
|
|
16
|
+
import { gateTransitions } from "./transition-gate.js";
|
|
17
|
+
import { resolvedHandleStream } from "../handles/deferred-resolution.js";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Build the metadata payload for a full (non-partial) document render.
|
|
21
|
+
*
|
|
22
|
+
* @param handleStore - the store whose resolved handle stream feeds the payload;
|
|
23
|
+
* the foreground passes reqCtx's store, the background capture passes its fresh
|
|
24
|
+
* derived-context store.
|
|
25
|
+
*/
|
|
26
|
+
export function buildFullPayload(
|
|
27
|
+
m: MatchResult,
|
|
28
|
+
// env is opaque here (the payload never reads it); `any` avoids the invariance
|
|
29
|
+
// friction of HandlerContext<TEnv> vs the ambient RequestContext env at the two
|
|
30
|
+
// call sites (foreground render + background capture).
|
|
31
|
+
ctx: HandlerContext<any>,
|
|
32
|
+
url: URL,
|
|
33
|
+
reqCtx: RequestContext<any>,
|
|
34
|
+
handleStore: HandleStore,
|
|
35
|
+
): RscPayload {
|
|
36
|
+
return {
|
|
37
|
+
metadata: {
|
|
38
|
+
pathname: url.pathname,
|
|
39
|
+
routerId: ctx.router.id,
|
|
40
|
+
basename: ctx.router.basename,
|
|
41
|
+
segments: gateTransitions(m.segments, reqCtx, ctx.router.onError),
|
|
42
|
+
matched: m.matched,
|
|
43
|
+
diff: m.diff,
|
|
44
|
+
resolvedIds: m.resolvedIds,
|
|
45
|
+
params: m.params,
|
|
46
|
+
isPartial: false,
|
|
47
|
+
rootLayout: ctx.router.rootLayout,
|
|
48
|
+
// Full render: resolve deferred handle values server-side so SSR markup and
|
|
49
|
+
// the first sync useHandle read see resolved values. Partial payloads
|
|
50
|
+
// (rsc-rendering.ts) keep streaming (handleStore.stream()).
|
|
51
|
+
handles: resolvedHandleStream(handleStore),
|
|
52
|
+
version: ctx.version,
|
|
53
|
+
prefetchCacheTTL: ctx.router.prefetchCacheTTL,
|
|
54
|
+
prefetchCacheSize: ctx.router.prefetchCacheSize,
|
|
55
|
+
prefetchConcurrency: ctx.router.prefetchConcurrency,
|
|
56
|
+
stateCookieName: ctx.router.resolvedStateCookieName,
|
|
57
|
+
themeConfig: ctx.router.themeConfig,
|
|
58
|
+
// Carry warmupEnabled on the initial full-render payload so the client
|
|
59
|
+
// respects warmup:false from first load. The 404 and PE payloads already
|
|
60
|
+
// include it; without it here warmup could never be disabled on the
|
|
61
|
+
// normal full-load path (partial payloads omit it by design).
|
|
62
|
+
warmupEnabled: ctx.router.warmupEnabled,
|
|
63
|
+
// Carry strictMode on the initial full-render payload so the browser
|
|
64
|
+
// entry knows whether to wrap hydration in React.StrictMode. Partial
|
|
65
|
+
// (navigation) payloads omit it by design; StrictMode is decided once.
|
|
66
|
+
strictMode: ctx.router.strictMode,
|
|
67
|
+
initialTheme: reqCtx.theme,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|