@rangojs/router 0.0.0-experimental.1878aa49 → 0.0.0-experimental.190fb30d
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 +303 -741
- package/dist/bin/rango.js +605 -146
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +4117 -1211
- package/dist/vite/index.js.bak +5448 -0
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +86 -15
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +85 -6
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +228 -33
- package/skills/caching/SKILL.md +336 -19
- 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 +110 -4
- 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 +87 -56
- package/skills/fonts/SKILL.md +1 -1
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +73 -691
- 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 +129 -27
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +94 -18
- package/skills/layout/SKILL.md +62 -19
- package/skills/links/SKILL.md +247 -17
- package/skills/loader/SKILL.md +248 -10
- package/skills/middleware/SKILL.md +57 -16
- package/skills/migrate-nextjs/SKILL.md +745 -0
- package/skills/migrate-react-router/SKILL.md +153 -0
- 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 +29 -2
- package/skills/observability/SKILL.md +202 -0
- package/skills/parallel/SKILL.md +99 -10
- package/skills/ppr/SKILL.md +618 -0
- package/skills/prerender/SKILL.md +178 -124
- package/skills/rango/SKILL.md +318 -24
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +138 -49
- package/skills/route/SKILL.md +141 -9
- package/skills/router-setup/SKILL.md +44 -9
- package/skills/scripts/SKILL.md +179 -0
- package/skills/server-actions/SKILL.md +776 -0
- package/skills/shell-manifest/SKILL.md +185 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/tailwind/SKILL.md +28 -4
- package/skills/testing/SKILL.md +130 -0
- 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 -626
- 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 +74 -15
- package/skills/vercel/SKILL.md +128 -0
- package/skills/view-transitions/SKILL.md +337 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +116 -0
- package/src/__internal.ts +1 -66
- package/src/browser/action-coordinator.ts +53 -36
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/app-shell.ts +39 -0
- package/src/browser/connection-warmup.ts +134 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +252 -158
- package/src/browser/history-state.ts +21 -0
- package/src/browser/index.ts +3 -3
- 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 +115 -27
- package/src/browser/navigation-client.ts +163 -70
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +161 -73
- package/src/browser/navigation-transaction.ts +9 -59
- package/src/browser/network-error-handler.ts +34 -7
- package/src/browser/partial-update.ts +186 -135
- package/src/browser/prefetch/cache.ts +246 -71
- package/src/browser/prefetch/fetch.ts +350 -38
- package/src/browser/prefetch/queue.ts +61 -12
- package/src/browser/rango-state.ts +158 -76
- package/src/browser/react/Link.tsx +70 -9
- package/src/browser/react/NavigationProvider.tsx +202 -120
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/filter-segment-order.ts +66 -7
- package/src/browser/react/index.ts +0 -48
- package/src/browser/react/location-state-shared.ts +178 -8
- package/src/browser/react/location-state.ts +39 -14
- package/src/browser/react/use-action.ts +6 -15
- package/src/browser/react/use-handle.ts +23 -69
- 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 +32 -7
- package/src/browser/react/use-params.ts +20 -10
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +25 -3
- package/src/browser/react/use-search-params.ts +0 -5
- package/src/browser/react/use-segments.ts +11 -21
- package/src/browser/response-adapter.ts +99 -8
- package/src/browser/rsc-router.tsx +145 -28
- package/src/browser/scroll-restoration.ts +44 -27
- package/src/browser/segment-reconciler.ts +44 -12
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +236 -65
- package/src/browser/types.ts +102 -9
- package/src/browser/validate-redirect-origin.ts +43 -16
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +205 -159
- package/src/build/generate-route-types.ts +3 -1
- package/src/build/index.ts +11 -3
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +198 -41
- package/src/build/route-types/ast-route-extraction.ts +15 -8
- package/src/build/route-types/codegen.ts +16 -5
- package/src/build/route-types/include-resolution.ts +456 -62
- package/src/build/route-types/param-extraction.ts +6 -3
- package/src/build/route-types/per-module-writer.ts +22 -6
- package/src/build/route-types/router-processing.ts +128 -51
- package/src/build/route-types/scan-filter.ts +9 -2
- package/src/build/route-types/source-scan.ts +216 -0
- package/src/build/runtime-discovery.ts +13 -21
- 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 +187 -96
- 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 +2206 -372
- 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 +41 -21
- package/src/client.tsx +116 -290
- 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 +18 -6
- package/src/decode-loader-results.ts +52 -0
- package/src/defer.ts +185 -0
- package/src/deps/ssr.ts +0 -1
- package/src/encode-kv.ts +49 -0
- package/src/errors.ts +30 -4
- package/src/escape-script.ts +52 -0
- package/src/handle.ts +104 -34
- 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 +9 -2
- package/src/host/pattern-matcher.ts +23 -52
- package/src/host/router.ts +107 -99
- package/src/host/testing.ts +40 -27
- package/src/host/types.ts +37 -4
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +137 -22
- package/src/index.rsc.ts +100 -13
- package/src/index.ts +143 -19
- package/src/internal-debug.ts +11 -10
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +20 -13
- package/src/loader.ts +12 -11
- package/src/missing-id-error.ts +68 -0
- package/src/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +1 -5
- package/src/prerender/param-hash.ts +16 -16
- package/src/prerender/store.ts +37 -41
- package/src/prerender.ts +215 -86
- 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 +62 -0
- package/src/reverse.ts +65 -15
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +19 -77
- package/src/route-definition/dsl-helpers.ts +461 -304
- package/src/route-definition/helper-factories.ts +28 -140
- package/src/route-definition/helpers-types.ts +147 -72
- package/src/route-definition/index.ts +4 -2
- package/src/route-definition/redirect.ts +44 -11
- package/src/route-definition/resolve-handler-use.ts +160 -0
- package/src/route-definition/use-item-types.ts +29 -0
- package/src/route-map-builder.ts +41 -20
- package/src/route-types.ts +37 -46
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +164 -17
- package/src/router/error-handling.ts +45 -18
- package/src/router/find-match.ts +129 -30
- package/src/router/handler-context.ts +47 -22
- package/src/router/instrument.ts +355 -0
- package/src/router/intercept-resolution.ts +39 -20
- package/src/router/lazy-includes.ts +85 -62
- package/src/router/loader-resolution.ts +277 -54
- package/src/router/logging.ts +0 -6
- package/src/router/manifest.ts +97 -57
- package/src/router/match-api.ts +178 -218
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +211 -165
- package/src/router/match-middleware/background-revalidation.ts +40 -24
- package/src/router/match-middleware/cache-lookup.ts +168 -277
- package/src/router/match-middleware/cache-store.ts +64 -52
- package/src/router/match-middleware/intercept-resolution.ts +0 -22
- package/src/router/match-middleware/segment-resolution.ts +45 -14
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +113 -45
- package/src/router/metrics.ts +0 -34
- package/src/router/middleware-types.ts +7 -134
- package/src/router/middleware.ts +298 -172
- package/src/router/navigation-snapshot.ts +133 -0
- package/src/router/params-util.ts +23 -0
- package/src/router/parse-pattern.ts +115 -0
- package/src/router/pattern-matching.ts +181 -150
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prefetch-limits.ts +37 -0
- package/src/router/prerender-match.ts +201 -56
- package/src/router/preview-match.ts +35 -103
- package/src/router/request-classification.ts +291 -0
- package/src/router/revalidation.ts +123 -73
- package/src/router/route-snapshot.ts +256 -0
- package/src/router/router-context.ts +6 -29
- package/src/router/router-interfaces.ts +125 -35
- package/src/router/router-options.ts +166 -5
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +188 -86
- 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 +67 -0
- package/src/router/segment-resolution/loader-snapshot.ts +308 -0
- package/src/router/segment-resolution/revalidation.ts +344 -319
- 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 +56 -0
- 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 +75 -0
- package/src/router/telemetry-otel.ts +160 -200
- package/src/router/telemetry.ts +105 -20
- package/src/router/timeout.ts +0 -20
- package/src/router/tracing.ts +215 -0
- package/src/router/trie-matching.ts +171 -59
- package/src/router/types.ts +9 -63
- package/src/router/url-params.ts +57 -0
- package/src/router.ts +170 -72
- package/src/rsc/full-payload.ts +70 -0
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +678 -513
- package/src/rsc/helpers.ts +168 -46
- package/src/rsc/index.ts +2 -5
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +127 -31
- package/src/rsc/manifest-init.ts +29 -42
- package/src/rsc/nonce.ts +10 -1
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +134 -15
- 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 +99 -189
- package/src/rsc/rsc-rendering.ts +497 -77
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +286 -114
- package/src/rsc/shell-capture.ts +1166 -0
- package/src/rsc/shell-serve.ts +181 -0
- package/src/rsc/ssr-setup.ts +17 -1
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +54 -5
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +35 -30
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +167 -0
- package/src/segment-system.tsx +355 -204
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +247 -54
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +152 -5
- package/src/server/handle-store.ts +40 -38
- package/src/server/loader-registry.ts +33 -42
- package/src/server/request-context.ts +502 -161
- package/src/ssr/index.tsx +467 -178
- package/src/ssr/inject-rsc-eager.ts +167 -0
- package/src/ssr/ssr-root.tsx +228 -0
- package/src/static-handler.ts +27 -18
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +46 -0
- package/src/testing/dispatch.ts +813 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +188 -0
- package/src/testing/e2e/index.ts +128 -0
- package/src/testing/e2e/matchers.ts +35 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +387 -0
- package/src/testing/e2e/server.ts +195 -0
- package/src/testing/flight-matchers.ts +97 -0
- package/src/testing/flight-normalize.ts +11 -0
- package/src/testing/flight-runtime.d.ts +57 -0
- package/src/testing/flight-tree.ts +682 -0
- package/src/testing/flight.entry.ts +52 -0
- package/src/testing/flight.ts +257 -0
- package/src/testing/generated-routes.ts +199 -0
- package/src/testing/index.ts +105 -0
- package/src/testing/internal/context.ts +371 -0
- 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 +584 -0
- package/src/testing/run-loader.ts +385 -0
- package/src/testing/run-middleware.ts +205 -0
- package/src/testing/run-transition-when.ts +164 -0
- package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
- package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
- package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
- package/src/testing/vitest-stubs/version.ts +5 -0
- package/src/testing/vitest.ts +305 -0
- 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 +54 -41
- package/src/types/handler-context.ts +120 -62
- package/src/types/index.ts +3 -10
- package/src/types/loader-types.ts +40 -10
- package/src/types/request-scope.ts +112 -0
- package/src/types/route-config.ts +20 -52
- package/src/types/route-entry.ts +12 -7
- package/src/types/segments.ts +136 -15
- package/src/urls/include-helper.ts +40 -75
- package/src/urls/include-provider.ts +71 -0
- package/src/urls/index.ts +2 -11
- package/src/urls/path-helper-types.ts +102 -23
- package/src/urls/path-helper.ts +62 -111
- package/src/urls/pattern-types.ts +72 -19
- package/src/urls/response-types.ts +25 -22
- package/src/urls/type-extraction.ts +98 -154
- package/src/urls/urls-function.ts +1 -19
- package/src/use-loader.tsx +346 -89
- package/src/vercel/index.ts +11 -0
- package/src/vercel/tracing.ts +88 -0
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +36 -38
- package/src/vite/discovery/dev-prerender-cache.ts +117 -0
- package/src/vite/discovery/discover-routers.ts +127 -86
- package/src/vite/discovery/discovery-errors.ts +255 -0
- package/src/vite/discovery/gate-state.ts +171 -0
- package/src/vite/discovery/prerender-collection.ts +214 -132
- package/src/vite/discovery/route-types-writer.ts +40 -84
- package/src/vite/discovery/self-gen-tracking.ts +27 -1
- package/src/vite/discovery/state.ts +57 -4
- package/src/vite/discovery/virtual-module-codegen.ts +14 -34
- package/src/vite/index.ts +15 -0
- package/src/vite/inject-client-debug.ts +88 -0
- package/src/vite/plugin-types.ts +261 -6
- package/src/vite/plugins/cjs-to-esm.ts +16 -19
- package/src/vite/plugins/client-ref-dedup.ts +16 -11
- package/src/vite/plugins/client-ref-hashing.ts +28 -15
- package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
- package/src/vite/plugins/expose-action-id.ts +48 -95
- package/src/vite/plugins/expose-id-utils.ts +96 -51
- package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
- package/src/vite/plugins/expose-ids/handler-transform.ts +15 -64
- package/src/vite/plugins/expose-ids/loader-transform.ts +14 -24
- package/src/vite/plugins/expose-ids/router-transform.ts +118 -29
- package/src/vite/plugins/expose-internal-ids.ts +553 -317
- package/src/vite/plugins/performance-tracks.ts +26 -25
- package/src/vite/plugins/refresh-cmd.ts +89 -27
- package/src/vite/plugins/use-cache-transform.ts +73 -83
- package/src/vite/plugins/vercel-output.ts +384 -0
- package/src/vite/plugins/version-injector.ts +40 -29
- package/src/vite/plugins/version-plugin.ts +37 -40
- package/src/vite/plugins/virtual-entries.ts +138 -27
- package/src/vite/rango.ts +238 -139
- package/src/vite/router-discovery.ts +1091 -159
- package/src/vite/utils/ast-handler-extract.ts +26 -35
- package/src/vite/utils/banner.ts +1 -1
- package/src/vite/utils/bundle-analysis.ts +10 -15
- package/src/vite/utils/client-chunks.ts +184 -0
- package/src/vite/utils/directive-prologue.ts +40 -0
- package/src/vite/utils/forward-user-plugins.ts +171 -0
- package/src/vite/utils/manifest-utils.ts +4 -59
- package/src/vite/utils/package-resolution.ts +20 -52
- package/src/vite/utils/prerender-utils.ts +98 -38
- package/src/vite/utils/shared-utils.ts +142 -43
- package/src/browser/action-response-classifier.ts +0 -99
- 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
|
@@ -93,15 +93,17 @@
|
|
|
93
93
|
*/
|
|
94
94
|
import type { ResolvedSegment } from "../../types.js";
|
|
95
95
|
import type { MatchContext, MatchPipelineState } from "../match-context.js";
|
|
96
|
-
import { getRouterContext } from "../router-context.js";
|
|
97
|
-
import {
|
|
96
|
+
import { getRouterContext, type RouterContext } from "../router-context.js";
|
|
97
|
+
import { observeEvent } from "../instrument.js";
|
|
98
98
|
import { pushRevalidationTraceEntry, isTraceActive } from "../logging.js";
|
|
99
|
+
import { treeHasStreaming } from "./segment-resolution.js";
|
|
99
100
|
import type { PrerenderStore, PrerenderEntry } from "../../prerender/store.js";
|
|
100
101
|
import type { HandleStore } from "../../server/handle-store.js";
|
|
101
102
|
import {
|
|
102
103
|
getRequestContext,
|
|
103
104
|
_getRequestContext,
|
|
104
105
|
} from "../../server/request-context.js";
|
|
106
|
+
import { paramsEqual } from "../params-util.js";
|
|
105
107
|
|
|
106
108
|
// Lazily initialized prerender store singleton and dynamically imported deps.
|
|
107
109
|
// Dynamic imports prevent pulling in @vitejs/plugin-rsc/rsc virtual module at
|
|
@@ -113,6 +115,9 @@ let _deserializeSegments:
|
|
|
113
115
|
let _restoreHandles:
|
|
114
116
|
| typeof import("../../cache/handle-snapshot.js").restoreHandles
|
|
115
117
|
| undefined;
|
|
118
|
+
let _decodeHandles:
|
|
119
|
+
| typeof import("../../cache/handle-snapshot.js").decodeHandles
|
|
120
|
+
| undefined;
|
|
116
121
|
let _hashParams:
|
|
117
122
|
| typeof import("../../prerender/param-hash.js").hashParams
|
|
118
123
|
| undefined;
|
|
@@ -120,22 +125,6 @@ let _lazyGetRequestContext:
|
|
|
120
125
|
| typeof import("../../server/request-context.js").getRequestContext
|
|
121
126
|
| undefined;
|
|
122
127
|
|
|
123
|
-
function paramsEqual(
|
|
124
|
-
a: Record<string, string>,
|
|
125
|
-
b: Record<string, string>,
|
|
126
|
-
): boolean {
|
|
127
|
-
if (a === b) return true;
|
|
128
|
-
|
|
129
|
-
const keysA = Object.keys(a);
|
|
130
|
-
if (keysA.length !== Object.keys(b).length) return false;
|
|
131
|
-
|
|
132
|
-
for (const key of keysA) {
|
|
133
|
-
if (a[key] !== b[key]) return false;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
return true;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
128
|
async function ensurePrerenderDeps() {
|
|
140
129
|
if (!_deserializeSegments) {
|
|
141
130
|
const [codec, snapshot, paramHash, reqCtx, store] = await Promise.all([
|
|
@@ -147,6 +136,7 @@ async function ensurePrerenderDeps() {
|
|
|
147
136
|
]);
|
|
148
137
|
_deserializeSegments = codec.deserializeSegments;
|
|
149
138
|
_restoreHandles = snapshot.restoreHandles;
|
|
139
|
+
_decodeHandles = snapshot.decodeHandles;
|
|
150
140
|
_hashParams = paramHash.hashParams;
|
|
151
141
|
_lazyGetRequestContext = reqCtx.getRequestContext;
|
|
152
142
|
if (prerenderStoreInstance === undefined) {
|
|
@@ -160,59 +150,21 @@ async function ensurePrerenderDeps() {
|
|
|
160
150
|
* Deserializes segments, replays handle data, yields segments with partial
|
|
161
151
|
* navigation nullification, and resolves fresh loaders.
|
|
162
152
|
*/
|
|
163
|
-
|
|
164
|
-
|
|
153
|
+
// Resolve loaders fresh on a cache hit (loaders are NEVER cached) and yield
|
|
154
|
+
// the loader segments, updating state.matchedIds and pushing the loader-resolve
|
|
155
|
+
// + cache-hit metrics. Shared verbatim by the prerender-store path
|
|
156
|
+
// (yieldFromStore) and the runtime cache-hit path (withCacheLookup). The router
|
|
157
|
+
// resolve fns are passed in (captured early by the callers) rather than re-read
|
|
158
|
+
// from getRouterContext() here, because that is ALS-backed and the callers run
|
|
159
|
+
// awaits before reaching this point (workerd can disrupt ALS mid-pipeline).
|
|
160
|
+
async function* resolveFreshLoadersAndYield<TEnv>(
|
|
165
161
|
ctx: MatchContext<TEnv>,
|
|
166
162
|
state: MatchPipelineState,
|
|
167
163
|
pipelineStart: number,
|
|
168
|
-
|
|
164
|
+
ms: MatchContext<TEnv>["metricsStore"],
|
|
165
|
+
resolveLoadersOnly: RouterContext<TEnv>["resolveLoadersOnly"],
|
|
166
|
+
resolveLoadersOnlyWithRevalidation: RouterContext<TEnv>["resolveLoadersOnlyWithRevalidation"],
|
|
169
167
|
): AsyncGenerator<ResolvedSegment> {
|
|
170
|
-
const { resolveLoadersOnlyWithRevalidation, resolveLoadersOnly } =
|
|
171
|
-
getRouterContext<TEnv>();
|
|
172
|
-
|
|
173
|
-
if (
|
|
174
|
-
!_deserializeSegments ||
|
|
175
|
-
!_restoreHandles ||
|
|
176
|
-
!_hashParams ||
|
|
177
|
-
!_lazyGetRequestContext
|
|
178
|
-
) {
|
|
179
|
-
throw new Error("yieldFromStore called before ensurePrerenderDeps");
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const segments = await _deserializeSegments(entry.segments);
|
|
183
|
-
|
|
184
|
-
// Replay handle data (same as runtime cache hit path).
|
|
185
|
-
// Prefer the eagerly-captured handleStoreRef to avoid ALS disruption in workerd.
|
|
186
|
-
const handleStore = handleStoreRef ?? _lazyGetRequestContext()?._handleStore;
|
|
187
|
-
if (handleStore) {
|
|
188
|
-
_restoreHandles(entry.handles, handleStore);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
state.cacheHit = true;
|
|
192
|
-
state.cacheSource = "prerender";
|
|
193
|
-
state.cachedSegments = segments;
|
|
194
|
-
state.cachedMatchedIds = segments.map((s) => s.id);
|
|
195
|
-
|
|
196
|
-
// For partial navigation, nullify components the client already has
|
|
197
|
-
// so parent layouts stay live (client keeps its existing versions).
|
|
198
|
-
// When params changed (e.g., different guide slug), the segments have
|
|
199
|
-
// different content, so we must NOT nullify.
|
|
200
|
-
const paramsChanged =
|
|
201
|
-
!ctx.isFullMatch && !paramsEqual(ctx.matched.params, ctx.prevParams);
|
|
202
|
-
for (const segment of segments) {
|
|
203
|
-
if (
|
|
204
|
-
!ctx.isFullMatch &&
|
|
205
|
-
!paramsChanged &&
|
|
206
|
-
ctx.clientSegmentSet.has(segment.id)
|
|
207
|
-
) {
|
|
208
|
-
segment.component = null;
|
|
209
|
-
segment.loading = undefined;
|
|
210
|
-
}
|
|
211
|
-
yield segment;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// Resolve loaders fresh (loaders are never pre-rendered/cached)
|
|
215
|
-
const ms = ctx.metricsStore;
|
|
216
168
|
const loaderStart = performance.now();
|
|
217
169
|
|
|
218
170
|
if (ctx.isFullMatch) {
|
|
@@ -240,6 +192,9 @@ async function* yieldFromStore<TEnv>(
|
|
|
240
192
|
ctx.url,
|
|
241
193
|
ctx.routeKey,
|
|
242
194
|
ctx.actionContext,
|
|
195
|
+
// Loaders are never cached in the segment cache, so segment staleness
|
|
196
|
+
// must not propagate; browser-sent staleness (ctx.stale) still must.
|
|
197
|
+
ctx.stale || undefined,
|
|
243
198
|
),
|
|
244
199
|
);
|
|
245
200
|
state.matchedIds = [
|
|
@@ -270,6 +225,115 @@ async function* yieldFromStore<TEnv>(
|
|
|
270
225
|
}
|
|
271
226
|
}
|
|
272
227
|
|
|
228
|
+
async function* yieldFromStore<TEnv>(
|
|
229
|
+
entry: PrerenderEntry,
|
|
230
|
+
ctx: MatchContext<TEnv>,
|
|
231
|
+
state: MatchPipelineState,
|
|
232
|
+
pipelineStart: number,
|
|
233
|
+
handleStoreRef?: HandleStore,
|
|
234
|
+
): AsyncGenerator<ResolvedSegment> {
|
|
235
|
+
const { resolveLoadersOnlyWithRevalidation, resolveLoadersOnly } =
|
|
236
|
+
getRouterContext<TEnv>();
|
|
237
|
+
|
|
238
|
+
if (
|
|
239
|
+
!_deserializeSegments ||
|
|
240
|
+
!_restoreHandles ||
|
|
241
|
+
!_decodeHandles ||
|
|
242
|
+
!_hashParams ||
|
|
243
|
+
!_lazyGetRequestContext
|
|
244
|
+
) {
|
|
245
|
+
throw new Error("yieldFromStore called before ensurePrerenderDeps");
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const segments = await _deserializeSegments(entry.segments);
|
|
249
|
+
|
|
250
|
+
// Replay handle data (same as runtime cache hit path). entry.handles is a
|
|
251
|
+
// Flight-encoded string ("" when none) — decode before restore so
|
|
252
|
+
// Promise/ReactNode handle values are revived, not the corrupted JSON form.
|
|
253
|
+
const handleStore = handleStoreRef ?? _lazyGetRequestContext()?._handleStore;
|
|
254
|
+
if (handleStore && entry.handles) {
|
|
255
|
+
const handlesRecord = await _decodeHandles(entry.handles);
|
|
256
|
+
if (handlesRecord) {
|
|
257
|
+
_restoreHandles(handlesRecord, handleStore);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
state.cacheHit = true;
|
|
262
|
+
state.cacheSource = "prerender";
|
|
263
|
+
state.cachedSegments = segments;
|
|
264
|
+
state.cachedMatchedIds = segments.map((s) => s.id);
|
|
265
|
+
|
|
266
|
+
// Set streaming flag (once) and resolve render barrier.
|
|
267
|
+
const reqCtx = handleStoreRef ? undefined : _lazyGetRequestContext?.();
|
|
268
|
+
const barrierReqCtx = reqCtx ?? _getRequestContext();
|
|
269
|
+
if (barrierReqCtx) {
|
|
270
|
+
if (barrierReqCtx._treeHasStreaming === undefined) {
|
|
271
|
+
barrierReqCtx._treeHasStreaming = treeHasStreaming(ctx.entries);
|
|
272
|
+
}
|
|
273
|
+
barrierReqCtx._resolveRenderBarrier(segments);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// For partial navigation, nullify components the client already has
|
|
277
|
+
// so parent layouts stay live (client keeps its existing versions).
|
|
278
|
+
// When params changed (e.g., different guide slug), the segments have
|
|
279
|
+
// different content, so we must NOT nullify.
|
|
280
|
+
const paramsChanged =
|
|
281
|
+
!ctx.isFullMatch && !paramsEqual(ctx.matched.params, ctx.prevParams);
|
|
282
|
+
for (const segment of segments) {
|
|
283
|
+
if (
|
|
284
|
+
!ctx.isFullMatch &&
|
|
285
|
+
!paramsChanged &&
|
|
286
|
+
ctx.clientSegmentSet.has(segment.id)
|
|
287
|
+
) {
|
|
288
|
+
segment.component = null;
|
|
289
|
+
segment.loading = undefined;
|
|
290
|
+
}
|
|
291
|
+
yield segment;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Resolve loaders fresh (loaders are never pre-rendered/cached).
|
|
295
|
+
yield* resolveFreshLoadersAndYield(
|
|
296
|
+
ctx,
|
|
297
|
+
state,
|
|
298
|
+
pipelineStart,
|
|
299
|
+
ctx.metricsStore,
|
|
300
|
+
resolveLoadersOnly,
|
|
301
|
+
resolveLoadersOnlyWithRevalidation,
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Look up a prerendered (build-time cached) entry for the current route and, on
|
|
307
|
+
* a hit, yield its segments. Returns true when an entry was served (the caller
|
|
308
|
+
* should stop the pipeline) and false on a miss. Intercept navigations consult
|
|
309
|
+
* only the intercept-specific entry (`paramHash + "/i"`); a miss there falls
|
|
310
|
+
* through to the normal pipeline so intercept-resolution can run. Callers must
|
|
311
|
+
* guard on `prerenderStoreInstance` after `ensurePrerenderDeps()`.
|
|
312
|
+
*/
|
|
313
|
+
async function* tryPrerenderLookup<TEnv>(
|
|
314
|
+
ctx: MatchContext<TEnv>,
|
|
315
|
+
state: MatchPipelineState,
|
|
316
|
+
pipelineStart: number,
|
|
317
|
+
handleStoreRef?: HandleStore,
|
|
318
|
+
): AsyncGenerator<ResolvedSegment, boolean> {
|
|
319
|
+
const paramHash = _hashParams!(ctx.matched.params);
|
|
320
|
+
const isPassthroughPrerenderRoute = ctx.entries.some(
|
|
321
|
+
(entry) => entry.type === "route" && entry.isPassthrough === true,
|
|
322
|
+
);
|
|
323
|
+
const lookupHash = ctx.isIntercept ? paramHash + "/i" : paramHash;
|
|
324
|
+
const entry = await prerenderStoreInstance!.get(
|
|
325
|
+
ctx.matched.routeKey,
|
|
326
|
+
lookupHash,
|
|
327
|
+
{
|
|
328
|
+
pathname: ctx.pathname,
|
|
329
|
+
isPassthroughRoute: isPassthroughPrerenderRoute,
|
|
330
|
+
},
|
|
331
|
+
);
|
|
332
|
+
if (!entry) return false;
|
|
333
|
+
yield* yieldFromStore(entry, ctx, state, pipelineStart, handleStoreRef);
|
|
334
|
+
return true;
|
|
335
|
+
}
|
|
336
|
+
|
|
273
337
|
/**
|
|
274
338
|
* Async generator middleware type
|
|
275
339
|
*/
|
|
@@ -314,75 +378,20 @@ export function withCacheLookup<TEnv>(
|
|
|
314
378
|
resolveLoadersOnly,
|
|
315
379
|
} = getRouterContext<TEnv>();
|
|
316
380
|
|
|
317
|
-
// Prerender lookup: check build-time cached data before runtime cache.
|
|
318
|
-
// Prerender data is available regardless of runtime cache configuration.
|
|
319
|
-
// Skip for HMR requests — the dev prerender endpoint reads from a stale
|
|
320
|
-
// RouterRegistry snapshot; rendering fresh ensures edits are visible.
|
|
321
381
|
const isHmr = !!ctx.request.headers.get("X-RSC-HMR");
|
|
322
382
|
if (!ctx.isAction && !isHmr && ctx.matched.pr) {
|
|
323
383
|
await ensurePrerenderDeps();
|
|
324
384
|
if (prerenderStoreInstance) {
|
|
325
|
-
const
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
385
|
+
const served = yield* tryPrerenderLookup(
|
|
386
|
+
ctx,
|
|
387
|
+
state,
|
|
388
|
+
pipelineStart,
|
|
389
|
+
handleStoreRef,
|
|
330
390
|
);
|
|
331
|
-
|
|
332
|
-
if (ctx.isIntercept) {
|
|
333
|
-
// Intercept navigation: try intercept-specific prerender entry
|
|
334
|
-
const entry = await prerenderStoreInstance.get(
|
|
335
|
-
ctx.matched.routeKey,
|
|
336
|
-
paramHash + "/i",
|
|
337
|
-
{
|
|
338
|
-
pathname: ctx.pathname,
|
|
339
|
-
isPassthroughRoute: isPassthroughPrerenderRoute,
|
|
340
|
-
},
|
|
341
|
-
);
|
|
342
|
-
if (entry) {
|
|
343
|
-
yield* yieldFromStore(
|
|
344
|
-
entry,
|
|
345
|
-
ctx,
|
|
346
|
-
state,
|
|
347
|
-
pipelineStart,
|
|
348
|
-
handleStoreRef,
|
|
349
|
-
);
|
|
350
|
-
return;
|
|
351
|
-
}
|
|
352
|
-
// No intercept prerender -- fall through to normal pipeline
|
|
353
|
-
// (skip non-intercept prerender to let intercept-resolution run)
|
|
354
|
-
} else {
|
|
355
|
-
// Normal navigation: existing behavior
|
|
356
|
-
const entry = await prerenderStoreInstance.get(
|
|
357
|
-
ctx.matched.routeKey,
|
|
358
|
-
paramHash,
|
|
359
|
-
{
|
|
360
|
-
pathname: ctx.pathname,
|
|
361
|
-
isPassthroughRoute: isPassthroughPrerenderRoute,
|
|
362
|
-
},
|
|
363
|
-
);
|
|
364
|
-
if (entry) {
|
|
365
|
-
yield* yieldFromStore(
|
|
366
|
-
entry,
|
|
367
|
-
ctx,
|
|
368
|
-
state,
|
|
369
|
-
pipelineStart,
|
|
370
|
-
handleStoreRef,
|
|
371
|
-
);
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
}
|
|
391
|
+
if (served) return;
|
|
375
392
|
}
|
|
376
393
|
}
|
|
377
394
|
|
|
378
|
-
// Dev-mode static handler interception for non-Node.js runtimes.
|
|
379
|
-
// __PRERENDER_DEV_URL is set by the Vite plugin when the RSC environment
|
|
380
|
-
// lacks a Node.js module runner (e.g. workerd, Deno workers). In those
|
|
381
|
-
// runtimes, handlers that depend on Node APIs like node:fs can't run
|
|
382
|
-
// in-process. We redirect them to the /__rsc_prerender endpoint which
|
|
383
|
-
// resolves segments in a Node.js temp server, same as prerender routes.
|
|
384
|
-
// In Node.js dev mode this variable is undefined -- handlers run
|
|
385
|
-
// in-process where Node APIs work, so no interception is needed.
|
|
386
395
|
if (!ctx.isAction && !ctx.matched.pr && globalThis.__PRERENDER_DEV_URL) {
|
|
387
396
|
const hasStatic = ctx.entries.some(
|
|
388
397
|
(e) =>
|
|
@@ -394,60 +403,18 @@ export function withCacheLookup<TEnv>(
|
|
|
394
403
|
if (hasStatic) {
|
|
395
404
|
await ensurePrerenderDeps();
|
|
396
405
|
if (prerenderStoreInstance) {
|
|
397
|
-
const
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
406
|
+
const served = yield* tryPrerenderLookup(
|
|
407
|
+
ctx,
|
|
408
|
+
state,
|
|
409
|
+
pipelineStart,
|
|
410
|
+
handleStoreRef,
|
|
402
411
|
);
|
|
403
|
-
|
|
404
|
-
if (ctx.isIntercept) {
|
|
405
|
-
const entry = await prerenderStoreInstance.get(
|
|
406
|
-
ctx.matched.routeKey,
|
|
407
|
-
paramHash + "/i",
|
|
408
|
-
{
|
|
409
|
-
pathname: ctx.pathname,
|
|
410
|
-
isPassthroughRoute: isPassthroughPrerenderRoute,
|
|
411
|
-
},
|
|
412
|
-
);
|
|
413
|
-
if (entry) {
|
|
414
|
-
yield* yieldFromStore(
|
|
415
|
-
entry,
|
|
416
|
-
ctx,
|
|
417
|
-
state,
|
|
418
|
-
pipelineStart,
|
|
419
|
-
handleStoreRef,
|
|
420
|
-
);
|
|
421
|
-
return;
|
|
422
|
-
}
|
|
423
|
-
// No intercept prerender -- fall through to normal pipeline
|
|
424
|
-
} else {
|
|
425
|
-
const entry = await prerenderStoreInstance.get(
|
|
426
|
-
ctx.matched.routeKey,
|
|
427
|
-
paramHash,
|
|
428
|
-
{
|
|
429
|
-
pathname: ctx.pathname,
|
|
430
|
-
isPassthroughRoute: isPassthroughPrerenderRoute,
|
|
431
|
-
},
|
|
432
|
-
);
|
|
433
|
-
if (entry) {
|
|
434
|
-
yield* yieldFromStore(
|
|
435
|
-
entry,
|
|
436
|
-
ctx,
|
|
437
|
-
state,
|
|
438
|
-
pipelineStart,
|
|
439
|
-
handleStoreRef,
|
|
440
|
-
);
|
|
441
|
-
return;
|
|
442
|
-
}
|
|
443
|
-
}
|
|
412
|
+
if (served) return;
|
|
444
413
|
}
|
|
445
414
|
}
|
|
446
415
|
}
|
|
447
416
|
|
|
448
|
-
// Skip cache during actions
|
|
449
417
|
if (ctx.isAction || !ctx.cacheScope?.enabled) {
|
|
450
|
-
// Cache miss - pass through to segment resolution
|
|
451
418
|
yield* source;
|
|
452
419
|
if (ms) {
|
|
453
420
|
ms.metrics.push({
|
|
@@ -459,7 +426,6 @@ export function withCacheLookup<TEnv>(
|
|
|
459
426
|
return;
|
|
460
427
|
}
|
|
461
428
|
|
|
462
|
-
// Lookup cache
|
|
463
429
|
const cacheResult = await ctx.cacheScope.lookupRoute(
|
|
464
430
|
ctx.pathname,
|
|
465
431
|
ctx.matched.params,
|
|
@@ -467,7 +433,6 @@ export function withCacheLookup<TEnv>(
|
|
|
467
433
|
);
|
|
468
434
|
|
|
469
435
|
if (!cacheResult) {
|
|
470
|
-
// Cache miss - pass through to segment resolution
|
|
471
436
|
yield* source;
|
|
472
437
|
if (ms) {
|
|
473
438
|
ms.metrics.push({
|
|
@@ -479,16 +444,12 @@ export function withCacheLookup<TEnv>(
|
|
|
479
444
|
return;
|
|
480
445
|
}
|
|
481
446
|
|
|
482
|
-
// Cache HIT
|
|
483
447
|
state.cacheHit = true;
|
|
484
448
|
state.cacheSource = "runtime";
|
|
485
449
|
state.shouldRevalidate = cacheResult.shouldRevalidate;
|
|
486
450
|
state.cachedSegments = cacheResult.segments;
|
|
487
451
|
state.cachedMatchedIds = cacheResult.segments.map((s) => s.id);
|
|
488
452
|
|
|
489
|
-
// Apply revalidation to cached segments.
|
|
490
|
-
// For full matches or empty client segment sets, this map is unnecessary:
|
|
491
|
-
// we never run segment-level revalidation and can stream segments directly.
|
|
492
453
|
const canCheckSegmentRevalidation =
|
|
493
454
|
!ctx.isFullMatch &&
|
|
494
455
|
ctx.clientSegmentSet.size > 0 &&
|
|
@@ -498,7 +459,6 @@ export function withCacheLookup<TEnv>(
|
|
|
498
459
|
: undefined;
|
|
499
460
|
|
|
500
461
|
for (const segment of cacheResult.segments) {
|
|
501
|
-
// Skip segments client doesn't have - they need their component
|
|
502
462
|
if (!ctx.clientSegmentSet.has(segment.id)) {
|
|
503
463
|
if (isTraceActive()) {
|
|
504
464
|
pushRevalidationTraceEntry({
|
|
@@ -515,19 +475,13 @@ export function withCacheLookup<TEnv>(
|
|
|
515
475
|
continue;
|
|
516
476
|
}
|
|
517
477
|
|
|
518
|
-
// Skip intercept segments - they're handled separately
|
|
519
478
|
if (segment.namespace?.startsWith("intercept:")) {
|
|
520
479
|
yield segment;
|
|
521
480
|
continue;
|
|
522
481
|
}
|
|
523
482
|
|
|
524
|
-
// Look up revalidation rules for this segment
|
|
525
483
|
const entryInfo = entryRevalidateMap?.get(segment.id);
|
|
526
484
|
|
|
527
|
-
// Even without explicit revalidation rules, route segments and their
|
|
528
|
-
// children must re-render when params or search params change — the
|
|
529
|
-
// handler reads ctx.params/ctx.searchParams so different values produce
|
|
530
|
-
// different content. Matches evaluateRevalidation's default logic.
|
|
531
485
|
const searchChanged = ctx.prevUrl.search !== ctx.url.search;
|
|
532
486
|
const routeParamsChanged = !paramsEqual(
|
|
533
487
|
ctx.matched.params,
|
|
@@ -541,7 +495,6 @@ export function withCacheLookup<TEnv>(
|
|
|
541
495
|
|
|
542
496
|
if (!entryInfo || entryInfo.revalidate.length === 0) {
|
|
543
497
|
if (shouldDefaultRevalidate) {
|
|
544
|
-
// Params or search params changed — must re-render even without custom rules
|
|
545
498
|
if (isTraceActive()) {
|
|
546
499
|
pushRevalidationTraceEntry({
|
|
547
500
|
segmentId: segment.id,
|
|
@@ -558,7 +511,6 @@ export function withCacheLookup<TEnv>(
|
|
|
558
511
|
yield segment;
|
|
559
512
|
continue;
|
|
560
513
|
}
|
|
561
|
-
// No revalidation rules, use default behavior (skip if client has)
|
|
562
514
|
if (isTraceActive()) {
|
|
563
515
|
pushRevalidationTraceEntry({
|
|
564
516
|
segmentId: segment.id,
|
|
@@ -576,7 +528,6 @@ export function withCacheLookup<TEnv>(
|
|
|
576
528
|
continue;
|
|
577
529
|
}
|
|
578
530
|
|
|
579
|
-
// Evaluate revalidation rules
|
|
580
531
|
const shouldRevalidate = await evaluateRevalidation({
|
|
581
532
|
segment,
|
|
582
533
|
prevParams: ctx.prevParams,
|
|
@@ -591,26 +542,20 @@ export function withCacheLookup<TEnv>(
|
|
|
591
542
|
routeKey: ctx.routeKey,
|
|
592
543
|
context: ctx.handlerContext,
|
|
593
544
|
actionContext: ctx.actionContext,
|
|
594
|
-
stale: cacheResult.shouldRevalidate || undefined,
|
|
545
|
+
stale: cacheResult.shouldRevalidate || ctx.stale || undefined,
|
|
595
546
|
traceSource: "cache-hit",
|
|
596
547
|
});
|
|
597
548
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
pathname: ctx.pathname,
|
|
607
|
-
routeKey: ctx.routeKey,
|
|
608
|
-
shouldRevalidate,
|
|
609
|
-
});
|
|
610
|
-
}
|
|
549
|
+
observeEvent({
|
|
550
|
+
type: "revalidation.decision",
|
|
551
|
+
timestamp: performance.now(),
|
|
552
|
+
segmentId: segment.id,
|
|
553
|
+
pathname: ctx.pathname,
|
|
554
|
+
routeKey: ctx.routeKey,
|
|
555
|
+
shouldRevalidate,
|
|
556
|
+
});
|
|
611
557
|
|
|
612
558
|
if (!shouldRevalidate) {
|
|
613
|
-
// Client has it, no revalidation needed
|
|
614
559
|
segment.component = null;
|
|
615
560
|
segment.loading = undefined;
|
|
616
561
|
}
|
|
@@ -618,77 +563,23 @@ export function withCacheLookup<TEnv>(
|
|
|
618
563
|
yield segment;
|
|
619
564
|
}
|
|
620
565
|
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
if (ctx.isFullMatch) {
|
|
627
|
-
// Full match (document request) - simple loader resolution without revalidation
|
|
628
|
-
if (resolveLoadersOnly) {
|
|
629
|
-
const loaderSegments = await Store.run(() =>
|
|
630
|
-
resolveLoadersOnly(ctx.entries, ctx.handlerContext),
|
|
631
|
-
);
|
|
632
|
-
|
|
633
|
-
// Update state - full match doesn't track matchedIds separately
|
|
634
|
-
state.matchedIds = state.cachedMatchedIds!;
|
|
635
|
-
|
|
636
|
-
// Yield fresh loader segments
|
|
637
|
-
for (const segment of loaderSegments) {
|
|
638
|
-
yield segment;
|
|
639
|
-
}
|
|
640
|
-
} else {
|
|
641
|
-
state.matchedIds = state.cachedMatchedIds!;
|
|
642
|
-
}
|
|
643
|
-
} else {
|
|
644
|
-
// Partial match (navigation) - loader resolution with revalidation
|
|
645
|
-
if (resolveLoadersOnlyWithRevalidation) {
|
|
646
|
-
const loaderResult = await Store.run(() =>
|
|
647
|
-
resolveLoadersOnlyWithRevalidation(
|
|
648
|
-
ctx.entries,
|
|
649
|
-
ctx.handlerContext,
|
|
650
|
-
ctx.clientSegmentSet,
|
|
651
|
-
ctx.prevParams,
|
|
652
|
-
ctx.request,
|
|
653
|
-
ctx.prevUrl,
|
|
654
|
-
ctx.url,
|
|
655
|
-
ctx.routeKey,
|
|
656
|
-
ctx.actionContext,
|
|
657
|
-
// Loaders are never cached in the segment cache, so segment
|
|
658
|
-
// staleness (cacheResult.shouldRevalidate) must not propagate.
|
|
659
|
-
// But browser-sent staleness (ctx.stale) — indicating an action
|
|
660
|
-
// happened in this or another tab — must still reach loaders.
|
|
661
|
-
ctx.stale || undefined,
|
|
662
|
-
),
|
|
663
|
-
);
|
|
664
|
-
|
|
665
|
-
// Update state with fresh loader matchedIds
|
|
666
|
-
state.matchedIds = [
|
|
667
|
-
...state.cachedMatchedIds!,
|
|
668
|
-
...loaderResult.matchedIds,
|
|
669
|
-
];
|
|
670
|
-
|
|
671
|
-
// Yield fresh loader segments
|
|
672
|
-
for (const segment of loaderResult.segments) {
|
|
673
|
-
yield segment;
|
|
674
|
-
}
|
|
675
|
-
} else {
|
|
676
|
-
state.matchedIds = state.cachedMatchedIds!;
|
|
566
|
+
const barrierReqCtx = _getRequestContext();
|
|
567
|
+
if (barrierReqCtx) {
|
|
568
|
+
if (barrierReqCtx._treeHasStreaming === undefined) {
|
|
569
|
+
barrierReqCtx._treeHasStreaming = treeHasStreaming(ctx.entries);
|
|
677
570
|
}
|
|
571
|
+
barrierReqCtx._resolveRenderBarrier(cacheResult.segments);
|
|
678
572
|
}
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
startTime: pipelineStart - ms.requestStart,
|
|
691
|
-
});
|
|
692
|
-
}
|
|
573
|
+
|
|
574
|
+
// Resolve loaders fresh (loaders are never cached). Shared with the
|
|
575
|
+
// prerender-store path via resolveFreshLoadersAndYield.
|
|
576
|
+
yield* resolveFreshLoadersAndYield(
|
|
577
|
+
ctx,
|
|
578
|
+
state,
|
|
579
|
+
pipelineStart,
|
|
580
|
+
ms,
|
|
581
|
+
resolveLoadersOnly,
|
|
582
|
+
resolveLoadersOnlyWithRevalidation,
|
|
583
|
+
);
|
|
693
584
|
};
|
|
694
585
|
}
|