@rangojs/router 0.0.0-experimental.14 → 0.0.0-experimental.141
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 +17 -0
- package/README.md +432 -7
- package/dist/bin/rango.js +2073 -213
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +7258 -2714
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +140 -67
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +329 -0
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +487 -0
- package/skills/caching/SKILL.md +357 -25
- 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 +246 -0
- package/skills/css/SKILL.md +76 -0
- package/skills/debug-manifest/SKILL.md +16 -10
- package/skills/document-cache/SKILL.md +87 -62
- package/skills/fonts/SKILL.md +6 -4
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +557 -79
- package/skills/host-router/SKILL.md +320 -0
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +207 -15
- package/skills/layout/SKILL.md +146 -6
- package/skills/links/SKILL.md +304 -25
- package/skills/loader/SKILL.md +616 -54
- package/skills/middleware/SKILL.md +217 -37
- package/skills/migrate-nextjs/SKILL.md +611 -0
- package/skills/migrate-react-router/SKILL.md +927 -0
- package/skills/mime-routes/SKILL.md +42 -11
- package/skills/observability/SKILL.md +194 -0
- package/skills/parallel/SKILL.md +284 -3
- package/skills/ppr/SKILL.md +293 -0
- package/skills/prerender/SKILL.md +437 -52
- package/skills/rango/SKILL.md +369 -22
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +263 -121
- package/skills/route/SKILL.md +350 -21
- package/skills/router-setup/SKILL.md +246 -33
- package/skills/scripts/SKILL.md +179 -0
- package/skills/server-actions/SKILL.md +775 -0
- package/skills/shell-manifest/SKILL.md +185 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/tailwind/SKILL.md +27 -3
- package/skills/testing/SKILL.md +126 -222
- 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 +9 -8
- package/skills/typesafety/SKILL.md +532 -103
- package/skills/use-cache/SKILL.md +367 -0
- 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 +77 -44
- package/src/bin/rango.ts +312 -15
- package/src/browser/action-coordinator.ts +114 -0
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/app-shell.ts +39 -0
- package/src/browser/app-version.ts +14 -0
- package/src/browser/connection-warmup.ts +134 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +293 -202
- package/src/browser/history-state.ts +101 -0
- package/src/browser/index.ts +3 -3
- package/src/browser/intercept-utils.ts +52 -0
- package/src/browser/invalidate-client-cache.ts +52 -0
- package/src/browser/link-interceptor.ts +24 -4
- package/src/browser/logging.ts +11 -0
- package/src/browser/merge-segment-loaders.ts +20 -12
- package/src/browser/navigation-bridge.ts +385 -576
- package/src/browser/navigation-client.ts +245 -75
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +184 -118
- package/src/browser/navigation-transaction.ts +247 -0
- package/src/browser/network-error-handler.ts +88 -0
- package/src/browser/partial-update.ts +412 -364
- package/src/browser/prefetch/cache.ts +359 -0
- package/src/browser/prefetch/fetch.ts +452 -0
- package/src/browser/prefetch/observer.ts +65 -0
- package/src/browser/prefetch/policy.ts +48 -0
- package/src/browser/prefetch/queue.ts +209 -0
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +194 -0
- package/src/browser/react/Link.tsx +275 -68
- package/src/browser/react/NavigationProvider.tsx +265 -109
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/context.ts +11 -0
- package/src/browser/react/filter-segment-order.ts +70 -0
- package/src/browser/react/index.ts +0 -48
- package/src/browser/react/location-state-shared.ts +272 -60
- package/src/browser/react/location-state.ts +90 -20
- package/src/browser/react/mount-context.ts +6 -1
- package/src/browser/react/nonce-context.ts +23 -0
- package/src/browser/react/shallow-equal.ts +27 -0
- package/src/browser/react/use-action.ts +35 -66
- package/src/browser/react/use-handle.ts +39 -126
- package/src/browser/react/use-href.tsx +8 -1
- package/src/browser/react/use-link-status.ts +39 -13
- package/src/browser/react/use-navigation.ts +53 -69
- package/src/browser/react/use-params.ts +75 -0
- package/src/browser/react/use-pathname.ts +47 -0
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +98 -0
- package/src/browser/react/use-search-params.ts +51 -0
- package/src/browser/react/use-segments.ts +72 -99
- package/src/browser/response-adapter.ts +164 -0
- package/src/browser/rsc-router.tsx +300 -72
- package/src/browser/scroll-restoration.ts +138 -50
- package/src/browser/segment-reconciler.ts +243 -0
- package/src/browser/segment-structure-assert.ts +17 -1
- package/src/browser/server-action-bridge.ts +668 -613
- package/src/browser/types.ts +223 -51
- package/src/browser/validate-redirect-origin.ts +56 -0
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +252 -161
- package/src/build/generate-route-types.ts +41 -1038
- package/src/build/index.ts +12 -7
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +225 -42
- package/src/build/route-types/ast-helpers.ts +25 -0
- package/src/build/route-types/ast-route-extraction.ts +105 -0
- package/src/build/route-types/codegen.ts +113 -0
- package/src/build/route-types/include-resolution.ts +812 -0
- package/src/build/route-types/param-extraction.ts +51 -0
- package/src/build/route-types/per-module-writer.ts +144 -0
- package/src/build/route-types/router-processing.ts +695 -0
- package/src/build/route-types/scan-filter.ts +85 -0
- package/src/build/route-types/source-scan.ts +216 -0
- package/src/build/runtime-discovery.ts +223 -0
- package/src/cache/background-task.ts +34 -0
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-key-utils.ts +60 -0
- package/src/cache/cache-policy.ts +199 -0
- package/src/cache/cache-runtime.ts +525 -0
- package/src/cache/cache-scope.ts +298 -332
- package/src/cache/cache-tag.ts +103 -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 +2508 -158
- 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 +17 -17
- package/src/cache/document-cache.ts +199 -92
- package/src/cache/handle-capture.ts +81 -0
- package/src/cache/handle-snapshot.ts +111 -0
- package/src/cache/index.ts +24 -35
- package/src/cache/memory-segment-store.ts +363 -30
- package/src/cache/profile-registry.ts +88 -0
- package/src/cache/read-through-swr.ts +178 -0
- package/src/cache/segment-codec.ts +248 -0
- package/src/cache/shell-snapshot.ts +368 -0
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/taint.ts +153 -0
- package/src/cache/types.ts +222 -211
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +1113 -0
- package/src/client.rsc.tsx +43 -21
- package/src/client.tsx +131 -347
- package/src/cloudflare/index.ts +11 -0
- package/src/cloudflare/tracing.ts +109 -0
- package/src/component-utils.ts +23 -4
- package/src/components/DefaultDocument.tsx +13 -3
- package/src/context-var.ts +168 -0
- package/src/debug.ts +19 -9
- 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 +106 -10
- package/src/escape-script.ts +52 -0
- package/src/handle.ts +110 -35
- package/src/handles/MetaTags.tsx +83 -59
- package/src/handles/Scripts.tsx +183 -0
- package/src/handles/breadcrumbs.ts +93 -0
- package/src/handles/deferred-resolution.ts +127 -0
- package/src/handles/is-thenable.ts +18 -0
- package/src/handles/meta.ts +44 -53
- package/src/handles/script.ts +244 -0
- package/src/host/cookie-handler.ts +20 -65
- package/src/host/errors.ts +21 -30
- package/src/host/index.ts +13 -9
- package/src/host/pattern-matcher.ts +50 -79
- package/src/host/router.ts +151 -121
- package/src/host/testing.ts +45 -32
- package/src/host/types.ts +52 -11
- package/src/host/utils.ts +2 -2
- package/src/href-client.ts +192 -57
- package/src/index.rsc.ts +173 -35
- package/src/index.ts +241 -73
- package/src/internal-debug.ts +9 -2
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +31 -99
- package/src/loader.ts +30 -12
- package/src/missing-id-error.ts +68 -0
- package/src/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +41 -0
- package/src/prerender/param-hash.ts +16 -14
- package/src/prerender/store.ts +121 -21
- package/src/prerender.ts +460 -26
- package/src/redirect-origin.ts +100 -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 +198 -128
- package/src/root-error-boundary.tsx +42 -48
- package/src/route-content-wrapper.tsx +22 -77
- package/src/route-definition/dsl-helpers.ts +1116 -0
- package/src/route-definition/helper-factories.ts +88 -0
- package/src/route-definition/helpers-types.ts +505 -0
- package/src/route-definition/index.ts +54 -0
- package/src/route-definition/redirect.ts +134 -0
- package/src/route-definition/resolve-handler-use.ts +160 -0
- package/src/route-definition/use-item-types.ts +29 -0
- package/src/route-definition.ts +1 -1481
- package/src/route-map-builder.ts +82 -144
- package/src/route-name.ts +53 -0
- package/src/route-types.ts +71 -45
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +263 -0
- package/src/router/debug-manifest.ts +72 -0
- package/src/router/error-handling.ts +54 -27
- package/src/router/find-match.ts +245 -0
- package/src/router/handler-context.ts +377 -125
- package/src/router/instrument.ts +350 -0
- package/src/router/intercept-resolution.ts +59 -28
- package/src/router/lazy-includes.ts +254 -0
- package/src/router/loader-resolution.ts +421 -157
- package/src/router/logging.ts +106 -6
- package/src/router/manifest.ts +131 -57
- package/src/router/match-api.ts +167 -246
- package/src/router/match-context.ts +4 -24
- package/src/router/match-handlers.ts +440 -0
- package/src/router/match-middleware/background-revalidation.ts +117 -93
- package/src/router/match-middleware/cache-lookup.ts +297 -150
- package/src/router/match-middleware/cache-store.ts +123 -51
- package/src/router/match-middleware/intercept-resolution.ts +44 -43
- package/src/router/match-middleware/segment-resolution.ts +64 -22
- package/src/router/match-pipelines.ts +11 -87
- package/src/router/match-result.ts +121 -50
- package/src/router/metrics.ts +219 -28
- package/src/router/middleware-types.ts +93 -0
- package/src/router/middleware.ts +505 -441
- 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 +311 -142
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prefetch-limits.ts +37 -0
- package/src/router/prerender-match.ts +547 -0
- package/src/router/preview-match.ts +102 -0
- package/src/router/request-classification.ts +278 -0
- package/src/router/revalidation.ts +203 -62
- package/src/router/route-snapshot.ts +246 -0
- package/src/router/router-context.ts +45 -48
- package/src/router/router-interfaces.ts +554 -0
- package/src/router/router-options.ts +779 -0
- package/src/router/router-registry.ts +21 -0
- package/src/router/segment-resolution/fresh.ts +772 -0
- package/src/router/segment-resolution/helpers.ts +348 -0
- package/src/router/segment-resolution/loader-cache.ts +250 -0
- package/src/router/segment-resolution/loader-mask.ts +44 -0
- package/src/router/segment-resolution/revalidation.ts +1331 -0
- package/src/router/segment-resolution/static-store.ts +81 -0
- 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 +25 -1354
- package/src/router/segment-wrappers.ts +292 -0
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/substitute-pattern-params.ts +75 -0
- package/src/router/telemetry-otel.ts +261 -0
- package/src/router/telemetry.ts +377 -0
- package/src/router/timeout.ts +128 -0
- package/src/router/tracing.ts +206 -0
- package/src/router/trie-matching.ts +240 -61
- package/src/router/types.ts +23 -70
- package/src/router/url-params.ts +57 -0
- package/src/router.ts +781 -2378
- package/src/rsc/full-payload.ts +70 -0
- package/src/rsc/handler-context.ts +46 -0
- package/src/rsc/handler.ts +905 -1142
- package/src/rsc/helpers.ts +275 -19
- package/src/rsc/index.ts +2 -25
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +305 -0
- package/src/rsc/manifest-init.ts +77 -0
- package/src/rsc/nonce.ts +14 -0
- package/src/rsc/origin-guard.ts +155 -0
- package/src/rsc/progressive-enhancement.ts +502 -0
- package/src/rsc/redirect-guard.ts +99 -0
- package/src/rsc/response-cache-serve.ts +238 -0
- package/src/rsc/response-error.ts +104 -0
- package/src/rsc/response-route-handler.ts +257 -0
- package/src/rsc/rsc-rendering.ts +527 -0
- package/src/rsc/runtime-warnings.ts +55 -0
- package/src/rsc/server-action.ts +522 -0
- package/src/rsc/shell-capture.ts +897 -0
- package/src/rsc/shell-serve.ts +124 -0
- package/src/rsc/ssr-setup.ts +144 -0
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +95 -12
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +99 -82
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +149 -0
- package/src/segment-system.tsx +349 -134
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +459 -85
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +310 -0
- package/src/server/fetchable-loader-store.ts +11 -6
- package/src/server/handle-store.ts +123 -42
- package/src/server/loader-registry.ts +51 -100
- package/src/server/request-context.ts +848 -157
- package/src/server.ts +15 -8
- package/src/ssr/index.tsx +443 -135
- package/src/ssr/ssr-root.tsx +228 -0
- package/src/static-handler.ts +45 -18
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +46 -0
- package/src/testing/dispatch.ts +701 -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 +76 -98
- package/src/theme/ThemeScript.tsx +12 -14
- package/src/theme/constants.ts +57 -15
- package/src/theme/index.ts +3 -20
- package/src/theme/theme-context.ts +5 -35
- package/src/theme/theme-script.ts +43 -39
- package/src/theme/use-theme.ts +0 -3
- package/src/types/boundaries.ts +123 -0
- package/src/types/cache-types.ts +207 -0
- package/src/types/error-types.ts +132 -0
- package/src/types/global-namespace.ts +113 -0
- package/src/types/handler-context.ts +839 -0
- package/src/types/index.ts +81 -0
- package/src/types/loader-types.ts +212 -0
- package/src/types/request-scope.ts +112 -0
- package/src/types/route-config.ts +138 -0
- package/src/types/route-entry.ts +114 -0
- package/src/types/segments.ts +271 -0
- package/src/types.ts +1 -1795
- package/src/urls/include-helper.ts +162 -0
- package/src/urls/include-provider.ts +71 -0
- package/src/urls/index.ts +44 -0
- package/src/urls/path-helper-types.ts +413 -0
- package/src/urls/path-helper.ts +280 -0
- package/src/urls/pattern-types.ts +160 -0
- package/src/urls/response-types.ts +109 -0
- package/src/urls/type-extraction.ts +316 -0
- package/src/urls/urls-function.ts +80 -0
- package/src/urls.ts +1 -1341
- package/src/use-loader.tsx +406 -141
- 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 +182 -0
- package/src/vite/discovery/discover-routers.ts +389 -0
- 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 +467 -0
- package/src/vite/discovery/route-types-writer.ts +214 -0
- package/src/vite/discovery/self-gen-tracking.ts +73 -0
- package/src/vite/discovery/state.ts +161 -0
- package/src/vite/discovery/virtual-module-codegen.ts +183 -0
- package/src/vite/index.ts +23 -2255
- package/src/vite/inject-client-debug.ts +36 -0
- package/src/vite/plugin-types.ts +303 -0
- package/src/vite/plugins/cjs-to-esm.ts +90 -0
- package/src/vite/plugins/client-ref-dedup.ts +120 -0
- package/src/vite/plugins/client-ref-hashing.ts +118 -0
- 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/{expose-action-id.ts → plugins/expose-action-id.ts} +88 -110
- package/src/vite/{expose-id-utils.ts → plugins/expose-id-utils.ts} +89 -79
- package/src/vite/plugins/expose-ids/export-analysis.ts +363 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +130 -0
- package/src/vite/plugins/expose-ids/loader-transform.ts +64 -0
- package/src/vite/plugins/expose-ids/router-transform.ts +199 -0
- package/src/vite/plugins/expose-ids/types.ts +45 -0
- package/src/vite/plugins/expose-internal-ids.ts +805 -0
- package/src/vite/plugins/performance-tracks.ts +89 -0
- package/src/vite/plugins/refresh-cmd.ts +127 -0
- package/src/vite/plugins/use-cache-transform.ts +313 -0
- package/src/vite/plugins/vercel-output.ts +384 -0
- package/src/vite/plugins/version-injector.ts +94 -0
- package/src/vite/plugins/version-plugin.ts +263 -0
- package/src/vite/plugins/virtual-entries.ts +234 -0
- package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
- package/src/vite/rango.ts +560 -0
- package/src/vite/router-discovery.ts +1638 -0
- package/src/vite/{ast-handler-extract.ts → utils/ast-handler-extract.ts} +200 -37
- package/src/vite/utils/banner.ts +36 -0
- package/src/vite/utils/bundle-analysis.ts +132 -0
- 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 +15 -0
- package/src/vite/utils/package-resolution.ts +89 -0
- package/src/vite/utils/prerender-utils.ts +249 -0
- package/src/vite/utils/shared-utils.ts +269 -0
- package/CLAUDE.md +0 -43
- package/dist/vite/index.named-routes.gen.ts +0 -103
- package/src/browser/lru-cache.ts +0 -69
- package/src/browser/react/use-client-cache.ts +0 -56
- package/src/browser/request-controller.ts +0 -164
- package/src/browser/shallow.ts +0 -35
- package/src/cache/memory-store.ts +0 -253
- package/src/handles/index.ts +0 -6
- package/src/href-context.ts +0 -33
- package/src/network-error-thrower.tsx +0 -21
- package/src/router.gen.ts +0 -6
- package/src/static-handler.gen.ts +0 -5
- package/src/urls.gen.ts +0 -8
- package/src/vite/expose-internal-ids.ts +0 -1167
- package/src/vite/package-resolution.ts +0 -125
- package/src/vite/virtual-entries.ts +0 -114
- /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
|
@@ -70,9 +70,11 @@
|
|
|
70
70
|
* - No segments yielded from this middleware
|
|
71
71
|
*
|
|
72
72
|
* Loaders:
|
|
73
|
-
* - NEVER cached
|
|
73
|
+
* - NEVER cached in the segment cache
|
|
74
74
|
* - Always resolved fresh on every request
|
|
75
75
|
* - Ensures data freshness even with cached UI components
|
|
76
|
+
* - Segment cache staleness does NOT propagate to loader revalidation;
|
|
77
|
+
* loaders use their own revalidation rules (actionId, user-defined)
|
|
76
78
|
*
|
|
77
79
|
*
|
|
78
80
|
* REVALIDATION RULES
|
|
@@ -91,28 +93,52 @@
|
|
|
91
93
|
*/
|
|
92
94
|
import type { ResolvedSegment } from "../../types.js";
|
|
93
95
|
import type { MatchContext, MatchPipelineState } from "../match-context.js";
|
|
94
|
-
import { getRouterContext } from "../router-context.js";
|
|
96
|
+
import { getRouterContext, type RouterContext } from "../router-context.js";
|
|
97
|
+
import { observeEvent } from "../instrument.js";
|
|
98
|
+
import { pushRevalidationTraceEntry, isTraceActive } from "../logging.js";
|
|
99
|
+
import { treeHasStreaming } from "./segment-resolution.js";
|
|
95
100
|
import type { PrerenderStore, PrerenderEntry } from "../../prerender/store.js";
|
|
101
|
+
import type { HandleStore } from "../../server/handle-store.js";
|
|
102
|
+
import {
|
|
103
|
+
getRequestContext,
|
|
104
|
+
_getRequestContext,
|
|
105
|
+
} from "../../server/request-context.js";
|
|
106
|
+
import { paramsEqual } from "../params-util.js";
|
|
96
107
|
|
|
97
108
|
// Lazily initialized prerender store singleton and dynamically imported deps.
|
|
98
109
|
// Dynamic imports prevent pulling in @vitejs/plugin-rsc/rsc virtual module at
|
|
99
110
|
// top-level, which breaks vitest (only URLs with file:, data:, node: schemes).
|
|
100
111
|
let prerenderStoreInstance: PrerenderStore | null | undefined;
|
|
101
|
-
let _deserializeSegments:
|
|
102
|
-
|
|
103
|
-
|
|
112
|
+
let _deserializeSegments:
|
|
113
|
+
| typeof import("../../cache/segment-codec.js").deserializeSegments
|
|
114
|
+
| undefined;
|
|
115
|
+
let _restoreHandles:
|
|
116
|
+
| typeof import("../../cache/handle-snapshot.js").restoreHandles
|
|
117
|
+
| undefined;
|
|
118
|
+
let _decodeHandles:
|
|
119
|
+
| typeof import("../../cache/handle-snapshot.js").decodeHandles
|
|
120
|
+
| undefined;
|
|
121
|
+
let _hashParams:
|
|
122
|
+
| typeof import("../../prerender/param-hash.js").hashParams
|
|
123
|
+
| undefined;
|
|
124
|
+
let _lazyGetRequestContext:
|
|
125
|
+
| typeof import("../../server/request-context.js").getRequestContext
|
|
126
|
+
| undefined;
|
|
104
127
|
|
|
105
128
|
async function ensurePrerenderDeps() {
|
|
106
129
|
if (!_deserializeSegments) {
|
|
107
|
-
const [
|
|
108
|
-
import("../../cache/
|
|
130
|
+
const [codec, snapshot, paramHash, reqCtx, store] = await Promise.all([
|
|
131
|
+
import("../../cache/segment-codec.js"),
|
|
132
|
+
import("../../cache/handle-snapshot.js"),
|
|
109
133
|
import("../../prerender/param-hash.js"),
|
|
110
134
|
import("../../server/request-context.js"),
|
|
111
135
|
import("../../prerender/store.js"),
|
|
112
136
|
]);
|
|
113
|
-
_deserializeSegments =
|
|
137
|
+
_deserializeSegments = codec.deserializeSegments;
|
|
138
|
+
_restoreHandles = snapshot.restoreHandles;
|
|
139
|
+
_decodeHandles = snapshot.decodeHandles;
|
|
114
140
|
_hashParams = paramHash.hashParams;
|
|
115
|
-
|
|
141
|
+
_lazyGetRequestContext = reqCtx.getRequestContext;
|
|
116
142
|
if (prerenderStoreInstance === undefined) {
|
|
117
143
|
prerenderStoreInstance = store.createPrerenderStore();
|
|
118
144
|
}
|
|
@@ -124,52 +150,23 @@ async function ensurePrerenderDeps() {
|
|
|
124
150
|
* Deserializes segments, replays handle data, yields segments with partial
|
|
125
151
|
* navigation nullification, and resolves fresh loaders.
|
|
126
152
|
*/
|
|
127
|
-
|
|
128
|
-
|
|
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>(
|
|
129
161
|
ctx: MatchContext<TEnv>,
|
|
130
162
|
state: MatchPipelineState,
|
|
131
163
|
pipelineStart: number,
|
|
164
|
+
ms: MatchContext<TEnv>["metricsStore"],
|
|
165
|
+
resolveLoadersOnly: RouterContext<TEnv>["resolveLoadersOnly"],
|
|
166
|
+
resolveLoadersOnlyWithRevalidation: RouterContext<TEnv>["resolveLoadersOnlyWithRevalidation"],
|
|
132
167
|
): AsyncGenerator<ResolvedSegment> {
|
|
133
|
-
const
|
|
134
|
-
resolveLoadersOnlyWithRevalidation,
|
|
135
|
-
resolveLoadersOnly,
|
|
136
|
-
} = getRouterContext<TEnv>();
|
|
137
|
-
|
|
138
|
-
if (!_deserializeSegments || !_hashParams || !_getRequestContext) {
|
|
139
|
-
throw new Error("yieldFromStore called before ensurePrerenderDeps");
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const segments = await _deserializeSegments(entry.segments);
|
|
143
|
-
|
|
144
|
-
// Replay handle data (same as runtime cache hit path)
|
|
145
|
-
const handleStore = _getRequestContext()?._handleStore;
|
|
146
|
-
if (handleStore) {
|
|
147
|
-
for (const [segId, segHandles] of Object.entries(entry.handles)) {
|
|
148
|
-
if (Object.keys(segHandles).length > 0) {
|
|
149
|
-
handleStore.replaySegmentData(segId, segHandles);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
state.cacheHit = true;
|
|
155
|
-
state.cachedSegments = segments;
|
|
156
|
-
state.cachedMatchedIds = segments.map((s) => s.id);
|
|
157
|
-
|
|
158
|
-
// For partial navigation, nullify components the client already has
|
|
159
|
-
// so parent layouts stay live (client keeps its existing versions).
|
|
160
|
-
// When params changed (e.g., different guide slug), the segments have
|
|
161
|
-
// different content, so we must NOT nullify.
|
|
162
|
-
const paramsChanged = !ctx.isFullMatch &&
|
|
163
|
-
JSON.stringify(ctx.matched.params) !== JSON.stringify(ctx.prevParams);
|
|
164
|
-
for (const segment of segments) {
|
|
165
|
-
if (!ctx.isFullMatch && !paramsChanged && ctx.clientSegmentSet.has(segment.id)) {
|
|
166
|
-
segment.component = null;
|
|
167
|
-
segment.loading = undefined;
|
|
168
|
-
}
|
|
169
|
-
yield segment;
|
|
170
|
-
}
|
|
168
|
+
const loaderStart = performance.now();
|
|
171
169
|
|
|
172
|
-
// Resolve loaders fresh (loaders are never pre-rendered/cached)
|
|
173
170
|
if (ctx.isFullMatch) {
|
|
174
171
|
if (resolveLoadersOnly) {
|
|
175
172
|
const loaderSegments = await ctx.Store.run(() =>
|
|
@@ -195,6 +192,9 @@ async function* yieldFromStore<TEnv>(
|
|
|
195
192
|
ctx.url,
|
|
196
193
|
ctx.routeKey,
|
|
197
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,
|
|
198
198
|
),
|
|
199
199
|
);
|
|
200
200
|
state.matchedIds = [
|
|
@@ -209,17 +209,136 @@ async function* yieldFromStore<TEnv>(
|
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
-
const ms = ctx.metricsStore;
|
|
213
212
|
if (ms) {
|
|
214
|
-
|
|
213
|
+
const loaderEnd = performance.now();
|
|
214
|
+
ms.metrics.push({
|
|
215
|
+
label: "pipeline:loader-resolve",
|
|
216
|
+
duration: loaderEnd - loaderStart,
|
|
217
|
+
startTime: loaderStart - ms.requestStart,
|
|
218
|
+
depth: 1,
|
|
219
|
+
});
|
|
220
|
+
ms.metrics.push({
|
|
221
|
+
label: "pipeline:cache-hit",
|
|
222
|
+
duration: loaderEnd - pipelineStart,
|
|
223
|
+
startTime: pipelineStart - ms.requestStart,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
|
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;
|
|
215
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;
|
|
216
335
|
}
|
|
217
336
|
|
|
218
337
|
/**
|
|
219
338
|
* Async generator middleware type
|
|
220
339
|
*/
|
|
221
340
|
export type GeneratorMiddleware<T> = (
|
|
222
|
-
source: AsyncGenerator<T
|
|
341
|
+
source: AsyncGenerator<T>,
|
|
223
342
|
) => AsyncGenerator<T>;
|
|
224
343
|
|
|
225
344
|
/**
|
|
@@ -237,14 +356,21 @@ export type GeneratorMiddleware<T> = (
|
|
|
237
356
|
*/
|
|
238
357
|
export function withCacheLookup<TEnv>(
|
|
239
358
|
ctx: MatchContext<TEnv>,
|
|
240
|
-
state: MatchPipelineState
|
|
359
|
+
state: MatchPipelineState,
|
|
241
360
|
): GeneratorMiddleware<ResolvedSegment> {
|
|
242
361
|
return async function* (
|
|
243
|
-
source: AsyncGenerator<ResolvedSegment
|
|
362
|
+
source: AsyncGenerator<ResolvedSegment>,
|
|
244
363
|
): AsyncGenerator<ResolvedSegment> {
|
|
245
364
|
const pipelineStart = performance.now();
|
|
246
365
|
const ms = ctx.metricsStore;
|
|
247
366
|
|
|
367
|
+
// Eagerly capture the HandleStore before any async operations.
|
|
368
|
+
// In workerd/Cloudflare, dynamic imports and fetch() inside the pipeline
|
|
369
|
+
// can disrupt AsyncLocalStorage, causing getRequestContext() to return
|
|
370
|
+
// undefined afterward. Capturing the reference early ensures handle replay
|
|
371
|
+
// and handler handle-push work regardless of ALS state.
|
|
372
|
+
const handleStoreRef = _getRequestContext()?._handleStore;
|
|
373
|
+
|
|
248
374
|
const {
|
|
249
375
|
evaluateRevalidation,
|
|
250
376
|
buildEntryRevalidateMap,
|
|
@@ -252,108 +378,156 @@ export function withCacheLookup<TEnv>(
|
|
|
252
378
|
resolveLoadersOnly,
|
|
253
379
|
} = getRouterContext<TEnv>();
|
|
254
380
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
if (!ctx.isAction && ctx.matched.pr) {
|
|
381
|
+
const isHmr = !!ctx.request.headers.get("X-RSC-HMR");
|
|
382
|
+
if (!ctx.isAction && !isHmr && ctx.matched.pr) {
|
|
258
383
|
await ensurePrerenderDeps();
|
|
259
384
|
if (prerenderStoreInstance) {
|
|
260
|
-
const
|
|
261
|
-
|
|
262
|
-
|
|
385
|
+
const served = yield* tryPrerenderLookup(
|
|
386
|
+
ctx,
|
|
387
|
+
state,
|
|
388
|
+
pipelineStart,
|
|
389
|
+
handleStoreRef,
|
|
263
390
|
);
|
|
264
|
-
if (
|
|
265
|
-
yield* yieldFromStore(entry, ctx, state, pipelineStart);
|
|
266
|
-
return;
|
|
267
|
-
}
|
|
391
|
+
if (served) return;
|
|
268
392
|
}
|
|
269
393
|
}
|
|
270
394
|
|
|
271
|
-
// Dev-mode static handler interception for non-Node.js runtimes.
|
|
272
|
-
// __PRERENDER_DEV_URL is set by the Vite plugin when the RSC environment
|
|
273
|
-
// lacks a Node.js module runner (e.g. workerd, Deno workers). In those
|
|
274
|
-
// runtimes, handlers that depend on Node APIs like node:fs can't run
|
|
275
|
-
// in-process. We redirect them to the /__rsc_prerender endpoint which
|
|
276
|
-
// resolves segments in a Node.js temp server, same as prerender routes.
|
|
277
|
-
// In Node.js dev mode this variable is undefined -- handlers run
|
|
278
|
-
// in-process where Node APIs work, so no interception is needed.
|
|
279
395
|
if (!ctx.isAction && !ctx.matched.pr && globalThis.__PRERENDER_DEV_URL) {
|
|
280
396
|
const hasStatic = ctx.entries.some(
|
|
281
|
-
(e) =>
|
|
397
|
+
(e) =>
|
|
398
|
+
(e.type === "layout" ||
|
|
399
|
+
e.type === "route" ||
|
|
400
|
+
e.type === "parallel") &&
|
|
401
|
+
e.isStaticPrerender,
|
|
282
402
|
);
|
|
283
403
|
if (hasStatic) {
|
|
284
404
|
await ensurePrerenderDeps();
|
|
285
405
|
if (prerenderStoreInstance) {
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
406
|
+
const served = yield* tryPrerenderLookup(
|
|
407
|
+
ctx,
|
|
408
|
+
state,
|
|
409
|
+
pipelineStart,
|
|
410
|
+
handleStoreRef,
|
|
289
411
|
);
|
|
290
|
-
if (
|
|
291
|
-
yield* yieldFromStore(entry, ctx, state, pipelineStart);
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
412
|
+
if (served) return;
|
|
294
413
|
}
|
|
295
414
|
}
|
|
296
415
|
}
|
|
297
416
|
|
|
298
|
-
// Skip cache during actions
|
|
299
417
|
if (ctx.isAction || !ctx.cacheScope?.enabled) {
|
|
300
|
-
// Cache miss - pass through to segment resolution
|
|
301
418
|
yield* source;
|
|
302
419
|
if (ms) {
|
|
303
|
-
ms.metrics.push({
|
|
420
|
+
ms.metrics.push({
|
|
421
|
+
label: "pipeline:cache-miss",
|
|
422
|
+
duration: performance.now() - pipelineStart,
|
|
423
|
+
startTime: pipelineStart - ms.requestStart,
|
|
424
|
+
});
|
|
304
425
|
}
|
|
305
426
|
return;
|
|
306
427
|
}
|
|
307
428
|
|
|
308
|
-
// Lookup cache
|
|
309
429
|
const cacheResult = await ctx.cacheScope.lookupRoute(
|
|
310
430
|
ctx.pathname,
|
|
311
431
|
ctx.matched.params,
|
|
312
|
-
ctx.isIntercept
|
|
432
|
+
ctx.isIntercept,
|
|
313
433
|
);
|
|
314
434
|
|
|
315
435
|
if (!cacheResult) {
|
|
316
|
-
// Cache miss - pass through to segment resolution
|
|
317
436
|
yield* source;
|
|
318
437
|
if (ms) {
|
|
319
|
-
ms.metrics.push({
|
|
438
|
+
ms.metrics.push({
|
|
439
|
+
label: "pipeline:cache-miss",
|
|
440
|
+
duration: performance.now() - pipelineStart,
|
|
441
|
+
startTime: pipelineStart - ms.requestStart,
|
|
442
|
+
});
|
|
320
443
|
}
|
|
321
444
|
return;
|
|
322
445
|
}
|
|
323
446
|
|
|
324
|
-
// Cache HIT
|
|
325
447
|
state.cacheHit = true;
|
|
448
|
+
state.cacheSource = "runtime";
|
|
326
449
|
state.shouldRevalidate = cacheResult.shouldRevalidate;
|
|
327
450
|
state.cachedSegments = cacheResult.segments;
|
|
328
451
|
state.cachedMatchedIds = cacheResult.segments.map((s) => s.id);
|
|
329
452
|
|
|
330
|
-
|
|
331
|
-
|
|
453
|
+
const canCheckSegmentRevalidation =
|
|
454
|
+
!ctx.isFullMatch &&
|
|
455
|
+
ctx.clientSegmentSet.size > 0 &&
|
|
456
|
+
!!buildEntryRevalidateMap;
|
|
457
|
+
const entryRevalidateMap = canCheckSegmentRevalidation
|
|
458
|
+
? buildEntryRevalidateMap(ctx.entries)
|
|
459
|
+
: undefined;
|
|
332
460
|
|
|
333
461
|
for (const segment of cacheResult.segments) {
|
|
334
|
-
// Skip segments client doesn't have - they need their component
|
|
335
462
|
if (!ctx.clientSegmentSet.has(segment.id)) {
|
|
463
|
+
if (isTraceActive()) {
|
|
464
|
+
pushRevalidationTraceEntry({
|
|
465
|
+
segmentId: segment.id,
|
|
466
|
+
segmentType: segment.type,
|
|
467
|
+
belongsToRoute: segment.belongsToRoute ?? false,
|
|
468
|
+
source: "cache-hit",
|
|
469
|
+
defaultShouldRevalidate: true,
|
|
470
|
+
finalShouldRevalidate: true,
|
|
471
|
+
reason: "new-segment",
|
|
472
|
+
});
|
|
473
|
+
}
|
|
336
474
|
yield segment;
|
|
337
475
|
continue;
|
|
338
476
|
}
|
|
339
477
|
|
|
340
|
-
// Skip intercept segments - they're handled separately
|
|
341
478
|
if (segment.namespace?.startsWith("intercept:")) {
|
|
342
479
|
yield segment;
|
|
343
480
|
continue;
|
|
344
481
|
}
|
|
345
482
|
|
|
346
|
-
// Look up revalidation rules for this segment
|
|
347
483
|
const entryInfo = entryRevalidateMap?.get(segment.id);
|
|
484
|
+
|
|
485
|
+
const searchChanged = ctx.prevUrl.search !== ctx.url.search;
|
|
486
|
+
const routeParamsChanged = !paramsEqual(
|
|
487
|
+
ctx.matched.params,
|
|
488
|
+
ctx.prevParams,
|
|
489
|
+
);
|
|
490
|
+
const shouldDefaultRevalidate =
|
|
491
|
+
(searchChanged || routeParamsChanged) &&
|
|
492
|
+
(segment.type === "route" ||
|
|
493
|
+
(segment.belongsToRoute &&
|
|
494
|
+
(segment.type === "layout" || segment.type === "parallel")));
|
|
495
|
+
|
|
348
496
|
if (!entryInfo || entryInfo.revalidate.length === 0) {
|
|
349
|
-
|
|
497
|
+
if (shouldDefaultRevalidate) {
|
|
498
|
+
if (isTraceActive()) {
|
|
499
|
+
pushRevalidationTraceEntry({
|
|
500
|
+
segmentId: segment.id,
|
|
501
|
+
segmentType: segment.type,
|
|
502
|
+
belongsToRoute: segment.belongsToRoute ?? false,
|
|
503
|
+
source: "cache-hit",
|
|
504
|
+
defaultShouldRevalidate: true,
|
|
505
|
+
finalShouldRevalidate: true,
|
|
506
|
+
reason: routeParamsChanged
|
|
507
|
+
? "cached-params-changed"
|
|
508
|
+
: "cached-search-changed",
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
yield segment;
|
|
512
|
+
continue;
|
|
513
|
+
}
|
|
514
|
+
if (isTraceActive()) {
|
|
515
|
+
pushRevalidationTraceEntry({
|
|
516
|
+
segmentId: segment.id,
|
|
517
|
+
segmentType: segment.type,
|
|
518
|
+
belongsToRoute: segment.belongsToRoute ?? false,
|
|
519
|
+
source: "cache-hit",
|
|
520
|
+
defaultShouldRevalidate: false,
|
|
521
|
+
finalShouldRevalidate: false,
|
|
522
|
+
reason: "cached-no-rules",
|
|
523
|
+
});
|
|
524
|
+
}
|
|
350
525
|
segment.component = null;
|
|
351
526
|
segment.loading = undefined;
|
|
352
527
|
yield segment;
|
|
353
528
|
continue;
|
|
354
529
|
}
|
|
355
530
|
|
|
356
|
-
// Evaluate revalidation rules
|
|
357
531
|
const shouldRevalidate = await evaluateRevalidation({
|
|
358
532
|
segment,
|
|
359
533
|
prevParams: ctx.prevParams,
|
|
@@ -368,10 +542,20 @@ export function withCacheLookup<TEnv>(
|
|
|
368
542
|
routeKey: ctx.routeKey,
|
|
369
543
|
context: ctx.handlerContext,
|
|
370
544
|
actionContext: ctx.actionContext,
|
|
545
|
+
stale: cacheResult.shouldRevalidate || ctx.stale || undefined,
|
|
546
|
+
traceSource: "cache-hit",
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
observeEvent({
|
|
550
|
+
type: "revalidation.decision",
|
|
551
|
+
timestamp: performance.now(),
|
|
552
|
+
segmentId: segment.id,
|
|
553
|
+
pathname: ctx.pathname,
|
|
554
|
+
routeKey: ctx.routeKey,
|
|
555
|
+
shouldRevalidate,
|
|
371
556
|
});
|
|
372
557
|
|
|
373
558
|
if (!shouldRevalidate) {
|
|
374
|
-
// Client has it, no revalidation needed
|
|
375
559
|
segment.component = null;
|
|
376
560
|
segment.loading = undefined;
|
|
377
561
|
}
|
|
@@ -379,60 +563,23 @@ export function withCacheLookup<TEnv>(
|
|
|
379
563
|
yield segment;
|
|
380
564
|
}
|
|
381
565
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
if (ctx.isFullMatch) {
|
|
387
|
-
// Full match (document request) - simple loader resolution without revalidation
|
|
388
|
-
if (resolveLoadersOnly) {
|
|
389
|
-
const loaderSegments = await Store.run(() =>
|
|
390
|
-
resolveLoadersOnly(ctx.entries, ctx.handlerContext)
|
|
391
|
-
);
|
|
392
|
-
|
|
393
|
-
// Update state - full match doesn't track matchedIds separately
|
|
394
|
-
state.matchedIds = state.cachedMatchedIds!;
|
|
395
|
-
|
|
396
|
-
// Yield fresh loader segments
|
|
397
|
-
for (const segment of loaderSegments) {
|
|
398
|
-
yield segment;
|
|
399
|
-
}
|
|
400
|
-
} else {
|
|
401
|
-
state.matchedIds = state.cachedMatchedIds!;
|
|
402
|
-
}
|
|
403
|
-
} else {
|
|
404
|
-
// Partial match (navigation) - loader resolution with revalidation
|
|
405
|
-
if (resolveLoadersOnlyWithRevalidation) {
|
|
406
|
-
const loaderResult = await Store.run(() =>
|
|
407
|
-
resolveLoadersOnlyWithRevalidation(
|
|
408
|
-
ctx.entries,
|
|
409
|
-
ctx.handlerContext,
|
|
410
|
-
ctx.clientSegmentSet,
|
|
411
|
-
ctx.prevParams,
|
|
412
|
-
ctx.request,
|
|
413
|
-
ctx.prevUrl,
|
|
414
|
-
ctx.url,
|
|
415
|
-
ctx.routeKey,
|
|
416
|
-
ctx.actionContext
|
|
417
|
-
)
|
|
418
|
-
);
|
|
419
|
-
|
|
420
|
-
// Update state with fresh loader matchedIds
|
|
421
|
-
state.matchedIds = [
|
|
422
|
-
...state.cachedMatchedIds!,
|
|
423
|
-
...loaderResult.matchedIds,
|
|
424
|
-
];
|
|
425
|
-
|
|
426
|
-
// Yield fresh loader segments
|
|
427
|
-
for (const segment of loaderResult.segments) {
|
|
428
|
-
yield segment;
|
|
429
|
-
}
|
|
430
|
-
} else {
|
|
431
|
-
state.matchedIds = state.cachedMatchedIds!;
|
|
566
|
+
const barrierReqCtx = _getRequestContext();
|
|
567
|
+
if (barrierReqCtx) {
|
|
568
|
+
if (barrierReqCtx._treeHasStreaming === undefined) {
|
|
569
|
+
barrierReqCtx._treeHasStreaming = treeHasStreaming(ctx.entries);
|
|
432
570
|
}
|
|
571
|
+
barrierReqCtx._resolveRenderBarrier(cacheResult.segments);
|
|
433
572
|
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
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
|
+
);
|
|
437
584
|
};
|
|
438
585
|
}
|