@rangojs/router 0.0.0-experimental.135c6902 → 0.0.0-experimental.136
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 -0
- package/README.md +245 -49
- package/dist/bin/rango.js +440 -133
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +3386 -1111
- package/dist/vite/index.js.bak +5448 -0
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +78 -25
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +64 -2
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +247 -23
- package/skills/caching/SKILL.md +281 -11
- package/skills/composability/SKILL.md +27 -3
- package/skills/css/SKILL.md +76 -0
- package/skills/debug-manifest/SKILL.md +4 -2
- package/skills/document-cache/SKILL.md +78 -55
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +250 -30
- package/skills/host-router/SKILL.md +83 -23
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +87 -18
- package/skills/layout/SKILL.md +35 -9
- package/skills/links/SKILL.md +249 -17
- package/skills/loader/SKILL.md +289 -53
- package/skills/middleware/SKILL.md +52 -13
- package/skills/migrate-nextjs/SKILL.md +584 -0
- package/skills/migrate-react-router/SKILL.md +914 -0
- package/skills/mime-routes/SKILL.md +28 -1
- package/skills/observability/SKILL.md +172 -0
- package/skills/parallel/SKILL.md +144 -7
- package/skills/prerender/SKILL.md +172 -125
- package/skills/rango/SKILL.md +251 -22
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +123 -48
- package/skills/route/SKILL.md +101 -5
- package/skills/router-setup/SKILL.md +117 -10
- package/skills/scripts/SKILL.md +179 -0
- package/skills/server-actions/SKILL.md +775 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/tailwind/SKILL.md +27 -3
- 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 +129 -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 +84 -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/typesafety/SKILL.md +332 -29
- package/skills/use-cache/SKILL.md +57 -14
- 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/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 +192 -150
- 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/navigation-bridge.ts +131 -30
- package/src/browser/navigation-client.ts +199 -86
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +157 -74
- package/src/browser/navigation-transaction.ts +9 -59
- package/src/browser/network-error-handler.ts +34 -7
- package/src/browser/partial-update.ts +174 -109
- package/src/browser/prefetch/cache.ts +222 -69
- package/src/browser/prefetch/fetch.ts +347 -39
- package/src/browser/prefetch/queue.ts +113 -32
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +158 -76
- package/src/browser/react/Link.tsx +102 -15
- package/src/browser/react/NavigationProvider.tsx +300 -122
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/context.ts +7 -2
- package/src/browser/react/deferred-handle-resolution.ts +75 -0
- 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 +46 -11
- 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 +125 -28
- package/src/browser/scroll-restoration.ts +37 -22
- package/src/browser/segment-reconciler.ts +36 -14
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +222 -61
- package/src/browser/types.ts +115 -12
- package/src/browser/validate-redirect-origin.ts +43 -16
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +65 -40
- package/src/build/generate-route-types.ts +5 -1
- package/src/build/index.ts +8 -2
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +165 -36
- 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 +125 -24
- 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 +260 -94
- 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 +9 -20
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-key-utils.ts +29 -13
- package/src/cache/cache-policy.ts +108 -34
- package/src/cache/cache-runtime.ts +239 -52
- package/src/cache/cache-scope.ts +234 -87
- 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 +1989 -378
- 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 +89 -21
- package/src/cache/handle-snapshot.ts +70 -0
- package/src/cache/index.ts +10 -20
- package/src/cache/memory-segment-store.ts +136 -37
- package/src/cache/profile-registry.ts +46 -31
- package/src/cache/read-through-swr.ts +56 -12
- package/src/cache/segment-codec.ts +9 -17
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/taint.ts +55 -0
- package/src/cache/types.ts +37 -100
- package/src/client.rsc.tsx +44 -21
- package/src/client.tsx +119 -290
- package/src/cloudflare/index.ts +11 -0
- package/src/cloudflare/tracing.ts +109 -0
- package/src/component-utils.ts +19 -0
- package/src/components/DefaultDocument.tsx +8 -2
- package/src/context-var.ts +84 -2
- package/src/decode-loader-results.ts +52 -0
- package/src/defer.ts +196 -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 +70 -22
- package/src/handles/MetaTags.tsx +62 -19
- package/src/handles/Scripts.tsx +183 -0
- package/src/handles/breadcrumbs.ts +37 -8
- package/src/handles/is-thenable.ts +19 -0
- package/src/handles/meta.ts +51 -40
- package/src/handles/script.ts +244 -0
- package/src/host/cookie-handler.ts +9 -60
- package/src/host/errors.ts +0 -24
- package/src/host/index.ts +8 -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 +99 -13
- package/src/index.ts +139 -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 +198 -82
- 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 +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 +149 -74
- package/src/route-definition/index.ts +4 -2
- package/src/route-definition/redirect.ts +51 -10
- 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 +0 -16
- 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 +44 -23
- package/src/router/handler-context.ts +83 -39
- package/src/router/instrument.ts +350 -0
- package/src/router/intercept-resolution.ts +48 -24
- package/src/router/lazy-includes.ts +15 -52
- package/src/router/loader-resolution.ts +274 -56
- package/src/router/logging.ts +0 -6
- package/src/router/manifest.ts +40 -42
- package/src/router/match-api.ts +124 -204
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +58 -58
- package/src/router/match-middleware/background-revalidation.ts +54 -25
- package/src/router/match-middleware/cache-lookup.ts +205 -271
- package/src/router/match-middleware/cache-store.ts +81 -50
- 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 +93 -39
- package/src/router/metrics.ts +5 -34
- package/src/router/middleware-types.ts +13 -142
- package/src/router/middleware.ts +268 -171
- package/src/router/navigation-snapshot.ts +131 -0
- package/src/router/params-util.ts +23 -0
- package/src/router/pattern-matching.ts +132 -90
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prefetch-limits.ts +37 -0
- package/src/router/prerender-match.ts +195 -56
- package/src/router/preview-match.ts +32 -102
- package/src/router/request-classification.ts +276 -0
- package/src/router/revalidation.ts +123 -73
- package/src/router/route-snapshot.ts +244 -0
- package/src/router/router-context.ts +3 -27
- package/src/router/router-interfaces.ts +129 -35
- package/src/router/router-options.ts +202 -15
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +197 -92
- package/src/router/segment-resolution/helpers.ts +115 -30
- package/src/router/segment-resolution/loader-cache.ts +76 -39
- package/src/router/segment-resolution/revalidation.ts +392 -338
- 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 +56 -0
- package/src/router/telemetry-otel.ts +161 -199
- package/src/router/telemetry.ts +96 -19
- package/src/router/timeout.ts +0 -20
- package/src/router/tracing.ts +206 -0
- package/src/router/trie-matching.ts +163 -59
- package/src/router/types.ts +10 -63
- package/src/router/url-params.ts +44 -0
- package/src/router.ts +174 -54
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +660 -518
- 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 +33 -42
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +133 -13
- package/src/rsc/redirect-guard.ts +99 -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 +115 -73
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +287 -113
- package/src/rsc/ssr-setup.ts +18 -2
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +36 -6
- 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 +149 -0
- package/src/segment-system.tsx +269 -202
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +235 -51
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +80 -5
- package/src/server/handle-store.ts +40 -38
- package/src/server/loader-registry.ts +38 -46
- package/src/server/request-context.ts +442 -173
- package/src/ssr/index.tsx +24 -16
- package/src/static-handler.ts +27 -18
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +40 -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 +183 -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 +581 -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 +20 -58
- 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 +17 -8
- package/src/types/error-types.ts +30 -90
- package/src/types/global-namespace.ts +54 -41
- package/src/types/handler-context.ts +234 -82
- package/src/types/index.ts +3 -10
- package/src/types/loader-types.ts +44 -15
- package/src/types/request-scope.ts +112 -0
- package/src/types/route-config.ts +6 -50
- package/src/types/route-entry.ts +12 -7
- package/src/types/segments.ts +136 -15
- package/src/urls/include-helper.ts +33 -70
- package/src/urls/index.ts +1 -11
- package/src/urls/path-helper-types.ts +68 -18
- package/src/urls/path-helper.ts +57 -111
- package/src/urls/pattern-types.ts +48 -19
- package/src/urls/response-types.ts +25 -22
- package/src/urls/type-extraction.ts +58 -139
- package/src/urls/urls-function.ts +1 -19
- package/src/use-loader.tsx +346 -89
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +36 -38
- package/src/vite/discovery/discover-routers.ts +130 -85
- package/src/vite/discovery/discovery-errors.ts +194 -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 +6 -0
- package/src/vite/inject-client-debug.ts +36 -0
- package/src/vite/plugin-types.ts +178 -5
- 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 +89 -0
- package/src/vite/plugins/refresh-cmd.ts +89 -27
- package/src/vite/plugins/use-cache-transform.ts +73 -83
- 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 +39 -25
- package/src/vite/rango.ts +119 -111
- package/src/vite/router-discovery.ts +941 -142
- 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 +81 -34
- package/src/vite/utils/shared-utils.ts +92 -42
- 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
|
@@ -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,15 +93,17 @@
|
|
|
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";
|
|
95
|
-
import {
|
|
96
|
+
import { getRouterContext, type RouterContext } from "../router-context.js";
|
|
97
|
+
import { observeEvent } from "../instrument.js";
|
|
96
98
|
import { pushRevalidationTraceEntry, isTraceActive } from "../logging.js";
|
|
99
|
+
import { treeHasStreaming } from "./segment-resolution.js";
|
|
97
100
|
import type { PrerenderStore, PrerenderEntry } from "../../prerender/store.js";
|
|
98
101
|
import type { HandleStore } from "../../server/handle-store.js";
|
|
99
102
|
import {
|
|
100
103
|
getRequestContext,
|
|
101
104
|
_getRequestContext,
|
|
102
105
|
} from "../../server/request-context.js";
|
|
106
|
+
import { paramsEqual } from "../params-util.js";
|
|
103
107
|
|
|
104
108
|
// Lazily initialized prerender store singleton and dynamically imported deps.
|
|
105
109
|
// Dynamic imports prevent pulling in @vitejs/plugin-rsc/rsc virtual module at
|
|
@@ -111,6 +115,9 @@ let _deserializeSegments:
|
|
|
111
115
|
let _restoreHandles:
|
|
112
116
|
| typeof import("../../cache/handle-snapshot.js").restoreHandles
|
|
113
117
|
| undefined;
|
|
118
|
+
let _decodeHandles:
|
|
119
|
+
| typeof import("../../cache/handle-snapshot.js").decodeHandles
|
|
120
|
+
| undefined;
|
|
114
121
|
let _hashParams:
|
|
115
122
|
| typeof import("../../prerender/param-hash.js").hashParams
|
|
116
123
|
| undefined;
|
|
@@ -118,22 +125,6 @@ let _lazyGetRequestContext:
|
|
|
118
125
|
| typeof import("../../server/request-context.js").getRequestContext
|
|
119
126
|
| undefined;
|
|
120
127
|
|
|
121
|
-
function paramsEqual(
|
|
122
|
-
a: Record<string, string>,
|
|
123
|
-
b: Record<string, string>,
|
|
124
|
-
): boolean {
|
|
125
|
-
if (a === b) return true;
|
|
126
|
-
|
|
127
|
-
const keysA = Object.keys(a);
|
|
128
|
-
if (keysA.length !== Object.keys(b).length) return false;
|
|
129
|
-
|
|
130
|
-
for (const key of keysA) {
|
|
131
|
-
if (a[key] !== b[key]) return false;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return true;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
128
|
async function ensurePrerenderDeps() {
|
|
138
129
|
if (!_deserializeSegments) {
|
|
139
130
|
const [codec, snapshot, paramHash, reqCtx, store] = await Promise.all([
|
|
@@ -145,6 +136,7 @@ async function ensurePrerenderDeps() {
|
|
|
145
136
|
]);
|
|
146
137
|
_deserializeSegments = codec.deserializeSegments;
|
|
147
138
|
_restoreHandles = snapshot.restoreHandles;
|
|
139
|
+
_decodeHandles = snapshot.decodeHandles;
|
|
148
140
|
_hashParams = paramHash.hashParams;
|
|
149
141
|
_lazyGetRequestContext = reqCtx.getRequestContext;
|
|
150
142
|
if (prerenderStoreInstance === undefined) {
|
|
@@ -158,59 +150,21 @@ async function ensurePrerenderDeps() {
|
|
|
158
150
|
* Deserializes segments, replays handle data, yields segments with partial
|
|
159
151
|
* navigation nullification, and resolves fresh loaders.
|
|
160
152
|
*/
|
|
161
|
-
|
|
162
|
-
|
|
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>(
|
|
163
161
|
ctx: MatchContext<TEnv>,
|
|
164
162
|
state: MatchPipelineState,
|
|
165
163
|
pipelineStart: number,
|
|
166
|
-
|
|
164
|
+
ms: MatchContext<TEnv>["metricsStore"],
|
|
165
|
+
resolveLoadersOnly: RouterContext<TEnv>["resolveLoadersOnly"],
|
|
166
|
+
resolveLoadersOnlyWithRevalidation: RouterContext<TEnv>["resolveLoadersOnlyWithRevalidation"],
|
|
167
167
|
): AsyncGenerator<ResolvedSegment> {
|
|
168
|
-
const { resolveLoadersOnlyWithRevalidation, resolveLoadersOnly } =
|
|
169
|
-
getRouterContext<TEnv>();
|
|
170
|
-
|
|
171
|
-
if (
|
|
172
|
-
!_deserializeSegments ||
|
|
173
|
-
!_restoreHandles ||
|
|
174
|
-
!_hashParams ||
|
|
175
|
-
!_lazyGetRequestContext
|
|
176
|
-
) {
|
|
177
|
-
throw new Error("yieldFromStore called before ensurePrerenderDeps");
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const segments = await _deserializeSegments(entry.segments);
|
|
181
|
-
|
|
182
|
-
// Replay handle data (same as runtime cache hit path).
|
|
183
|
-
// Prefer the eagerly-captured handleStoreRef to avoid ALS disruption in workerd.
|
|
184
|
-
const handleStore = handleStoreRef ?? _lazyGetRequestContext()?._handleStore;
|
|
185
|
-
if (handleStore) {
|
|
186
|
-
_restoreHandles(entry.handles, handleStore);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
state.cacheHit = true;
|
|
190
|
-
state.cacheSource = "prerender";
|
|
191
|
-
state.cachedSegments = segments;
|
|
192
|
-
state.cachedMatchedIds = segments.map((s) => s.id);
|
|
193
|
-
|
|
194
|
-
// For partial navigation, nullify components the client already has
|
|
195
|
-
// so parent layouts stay live (client keeps its existing versions).
|
|
196
|
-
// When params changed (e.g., different guide slug), the segments have
|
|
197
|
-
// different content, so we must NOT nullify.
|
|
198
|
-
const paramsChanged =
|
|
199
|
-
!ctx.isFullMatch && !paramsEqual(ctx.matched.params, ctx.prevParams);
|
|
200
|
-
for (const segment of segments) {
|
|
201
|
-
if (
|
|
202
|
-
!ctx.isFullMatch &&
|
|
203
|
-
!paramsChanged &&
|
|
204
|
-
ctx.clientSegmentSet.has(segment.id)
|
|
205
|
-
) {
|
|
206
|
-
segment.component = null;
|
|
207
|
-
segment.loading = undefined;
|
|
208
|
-
}
|
|
209
|
-
yield segment;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// Resolve loaders fresh (loaders are never pre-rendered/cached)
|
|
213
|
-
const ms = ctx.metricsStore;
|
|
214
168
|
const loaderStart = performance.now();
|
|
215
169
|
|
|
216
170
|
if (ctx.isFullMatch) {
|
|
@@ -238,6 +192,9 @@ async function* yieldFromStore<TEnv>(
|
|
|
238
192
|
ctx.url,
|
|
239
193
|
ctx.routeKey,
|
|
240
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,
|
|
241
198
|
),
|
|
242
199
|
);
|
|
243
200
|
state.matchedIds = [
|
|
@@ -261,13 +218,122 @@ async function* yieldFromStore<TEnv>(
|
|
|
261
218
|
depth: 1,
|
|
262
219
|
});
|
|
263
220
|
ms.metrics.push({
|
|
264
|
-
label: "pipeline:cache-
|
|
221
|
+
label: "pipeline:cache-hit",
|
|
265
222
|
duration: loaderEnd - pipelineStart,
|
|
266
223
|
startTime: pipelineStart - ms.requestStart,
|
|
267
224
|
});
|
|
268
225
|
}
|
|
269
226
|
}
|
|
270
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
|
+
|
|
271
337
|
/**
|
|
272
338
|
* Async generator middleware type
|
|
273
339
|
*/
|
|
@@ -312,72 +378,20 @@ export function withCacheLookup<TEnv>(
|
|
|
312
378
|
resolveLoadersOnly,
|
|
313
379
|
} = getRouterContext<TEnv>();
|
|
314
380
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if (!ctx.isAction && ctx.matched.pr) {
|
|
381
|
+
const isHmr = !!ctx.request.headers.get("X-RSC-HMR");
|
|
382
|
+
if (!ctx.isAction && !isHmr && ctx.matched.pr) {
|
|
318
383
|
await ensurePrerenderDeps();
|
|
319
384
|
if (prerenderStoreInstance) {
|
|
320
|
-
const
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
385
|
+
const served = yield* tryPrerenderLookup(
|
|
386
|
+
ctx,
|
|
387
|
+
state,
|
|
388
|
+
pipelineStart,
|
|
389
|
+
handleStoreRef,
|
|
325
390
|
);
|
|
326
|
-
|
|
327
|
-
if (ctx.isIntercept) {
|
|
328
|
-
// Intercept navigation: try intercept-specific prerender entry
|
|
329
|
-
const entry = await prerenderStoreInstance.get(
|
|
330
|
-
ctx.matched.routeKey,
|
|
331
|
-
paramHash + "/i",
|
|
332
|
-
{
|
|
333
|
-
pathname: ctx.pathname,
|
|
334
|
-
isPassthroughRoute: isPassthroughPrerenderRoute,
|
|
335
|
-
},
|
|
336
|
-
);
|
|
337
|
-
if (entry) {
|
|
338
|
-
yield* yieldFromStore(
|
|
339
|
-
entry,
|
|
340
|
-
ctx,
|
|
341
|
-
state,
|
|
342
|
-
pipelineStart,
|
|
343
|
-
handleStoreRef,
|
|
344
|
-
);
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
|
-
// No intercept prerender -- fall through to normal pipeline
|
|
348
|
-
// (skip non-intercept prerender to let intercept-resolution run)
|
|
349
|
-
} else {
|
|
350
|
-
// Normal navigation: existing behavior
|
|
351
|
-
const entry = await prerenderStoreInstance.get(
|
|
352
|
-
ctx.matched.routeKey,
|
|
353
|
-
paramHash,
|
|
354
|
-
{
|
|
355
|
-
pathname: ctx.pathname,
|
|
356
|
-
isPassthroughRoute: isPassthroughPrerenderRoute,
|
|
357
|
-
},
|
|
358
|
-
);
|
|
359
|
-
if (entry) {
|
|
360
|
-
yield* yieldFromStore(
|
|
361
|
-
entry,
|
|
362
|
-
ctx,
|
|
363
|
-
state,
|
|
364
|
-
pipelineStart,
|
|
365
|
-
handleStoreRef,
|
|
366
|
-
);
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
391
|
+
if (served) return;
|
|
370
392
|
}
|
|
371
393
|
}
|
|
372
394
|
|
|
373
|
-
// Dev-mode static handler interception for non-Node.js runtimes.
|
|
374
|
-
// __PRERENDER_DEV_URL is set by the Vite plugin when the RSC environment
|
|
375
|
-
// lacks a Node.js module runner (e.g. workerd, Deno workers). In those
|
|
376
|
-
// runtimes, handlers that depend on Node APIs like node:fs can't run
|
|
377
|
-
// in-process. We redirect them to the /__rsc_prerender endpoint which
|
|
378
|
-
// resolves segments in a Node.js temp server, same as prerender routes.
|
|
379
|
-
// In Node.js dev mode this variable is undefined -- handlers run
|
|
380
|
-
// in-process where Node APIs work, so no interception is needed.
|
|
381
395
|
if (!ctx.isAction && !ctx.matched.pr && globalThis.__PRERENDER_DEV_URL) {
|
|
382
396
|
const hasStatic = ctx.entries.some(
|
|
383
397
|
(e) =>
|
|
@@ -389,64 +403,22 @@ export function withCacheLookup<TEnv>(
|
|
|
389
403
|
if (hasStatic) {
|
|
390
404
|
await ensurePrerenderDeps();
|
|
391
405
|
if (prerenderStoreInstance) {
|
|
392
|
-
const
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
406
|
+
const served = yield* tryPrerenderLookup(
|
|
407
|
+
ctx,
|
|
408
|
+
state,
|
|
409
|
+
pipelineStart,
|
|
410
|
+
handleStoreRef,
|
|
397
411
|
);
|
|
398
|
-
|
|
399
|
-
if (ctx.isIntercept) {
|
|
400
|
-
const entry = await prerenderStoreInstance.get(
|
|
401
|
-
ctx.matched.routeKey,
|
|
402
|
-
paramHash + "/i",
|
|
403
|
-
{
|
|
404
|
-
pathname: ctx.pathname,
|
|
405
|
-
isPassthroughRoute: isPassthroughPrerenderRoute,
|
|
406
|
-
},
|
|
407
|
-
);
|
|
408
|
-
if (entry) {
|
|
409
|
-
yield* yieldFromStore(
|
|
410
|
-
entry,
|
|
411
|
-
ctx,
|
|
412
|
-
state,
|
|
413
|
-
pipelineStart,
|
|
414
|
-
handleStoreRef,
|
|
415
|
-
);
|
|
416
|
-
return;
|
|
417
|
-
}
|
|
418
|
-
// No intercept prerender -- fall through to normal pipeline
|
|
419
|
-
} else {
|
|
420
|
-
const entry = await prerenderStoreInstance.get(
|
|
421
|
-
ctx.matched.routeKey,
|
|
422
|
-
paramHash,
|
|
423
|
-
{
|
|
424
|
-
pathname: ctx.pathname,
|
|
425
|
-
isPassthroughRoute: isPassthroughPrerenderRoute,
|
|
426
|
-
},
|
|
427
|
-
);
|
|
428
|
-
if (entry) {
|
|
429
|
-
yield* yieldFromStore(
|
|
430
|
-
entry,
|
|
431
|
-
ctx,
|
|
432
|
-
state,
|
|
433
|
-
pipelineStart,
|
|
434
|
-
handleStoreRef,
|
|
435
|
-
);
|
|
436
|
-
return;
|
|
437
|
-
}
|
|
438
|
-
}
|
|
412
|
+
if (served) return;
|
|
439
413
|
}
|
|
440
414
|
}
|
|
441
415
|
}
|
|
442
416
|
|
|
443
|
-
// Skip cache during actions
|
|
444
417
|
if (ctx.isAction || !ctx.cacheScope?.enabled) {
|
|
445
|
-
// Cache miss - pass through to segment resolution
|
|
446
418
|
yield* source;
|
|
447
419
|
if (ms) {
|
|
448
420
|
ms.metrics.push({
|
|
449
|
-
label: "pipeline:cache-
|
|
421
|
+
label: "pipeline:cache-miss",
|
|
450
422
|
duration: performance.now() - pipelineStart,
|
|
451
423
|
startTime: pipelineStart - ms.requestStart,
|
|
452
424
|
});
|
|
@@ -454,7 +426,6 @@ export function withCacheLookup<TEnv>(
|
|
|
454
426
|
return;
|
|
455
427
|
}
|
|
456
428
|
|
|
457
|
-
// Lookup cache
|
|
458
429
|
const cacheResult = await ctx.cacheScope.lookupRoute(
|
|
459
430
|
ctx.pathname,
|
|
460
431
|
ctx.matched.params,
|
|
@@ -462,11 +433,10 @@ export function withCacheLookup<TEnv>(
|
|
|
462
433
|
);
|
|
463
434
|
|
|
464
435
|
if (!cacheResult) {
|
|
465
|
-
// Cache miss - pass through to segment resolution
|
|
466
436
|
yield* source;
|
|
467
437
|
if (ms) {
|
|
468
438
|
ms.metrics.push({
|
|
469
|
-
label: "pipeline:cache-
|
|
439
|
+
label: "pipeline:cache-miss",
|
|
470
440
|
duration: performance.now() - pipelineStart,
|
|
471
441
|
startTime: pipelineStart - ms.requestStart,
|
|
472
442
|
});
|
|
@@ -474,16 +444,12 @@ export function withCacheLookup<TEnv>(
|
|
|
474
444
|
return;
|
|
475
445
|
}
|
|
476
446
|
|
|
477
|
-
// Cache HIT
|
|
478
447
|
state.cacheHit = true;
|
|
479
448
|
state.cacheSource = "runtime";
|
|
480
449
|
state.shouldRevalidate = cacheResult.shouldRevalidate;
|
|
481
450
|
state.cachedSegments = cacheResult.segments;
|
|
482
451
|
state.cachedMatchedIds = cacheResult.segments.map((s) => s.id);
|
|
483
452
|
|
|
484
|
-
// Apply revalidation to cached segments.
|
|
485
|
-
// For full matches or empty client segment sets, this map is unnecessary:
|
|
486
|
-
// we never run segment-level revalidation and can stream segments directly.
|
|
487
453
|
const canCheckSegmentRevalidation =
|
|
488
454
|
!ctx.isFullMatch &&
|
|
489
455
|
ctx.clientSegmentSet.size > 0 &&
|
|
@@ -493,7 +459,6 @@ export function withCacheLookup<TEnv>(
|
|
|
493
459
|
: undefined;
|
|
494
460
|
|
|
495
461
|
for (const segment of cacheResult.segments) {
|
|
496
|
-
// Skip segments client doesn't have - they need their component
|
|
497
462
|
if (!ctx.clientSegmentSet.has(segment.id)) {
|
|
498
463
|
if (isTraceActive()) {
|
|
499
464
|
pushRevalidationTraceEntry({
|
|
@@ -510,16 +475,42 @@ export function withCacheLookup<TEnv>(
|
|
|
510
475
|
continue;
|
|
511
476
|
}
|
|
512
477
|
|
|
513
|
-
// Skip intercept segments - they're handled separately
|
|
514
478
|
if (segment.namespace?.startsWith("intercept:")) {
|
|
515
479
|
yield segment;
|
|
516
480
|
continue;
|
|
517
481
|
}
|
|
518
482
|
|
|
519
|
-
// Look up revalidation rules for this segment
|
|
520
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
|
+
|
|
521
496
|
if (!entryInfo || entryInfo.revalidate.length === 0) {
|
|
522
|
-
|
|
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
|
+
}
|
|
523
514
|
if (isTraceActive()) {
|
|
524
515
|
pushRevalidationTraceEntry({
|
|
525
516
|
segmentId: segment.id,
|
|
@@ -537,7 +528,6 @@ export function withCacheLookup<TEnv>(
|
|
|
537
528
|
continue;
|
|
538
529
|
}
|
|
539
530
|
|
|
540
|
-
// Evaluate revalidation rules
|
|
541
531
|
const shouldRevalidate = await evaluateRevalidation({
|
|
542
532
|
segment,
|
|
543
533
|
prevParams: ctx.prevParams,
|
|
@@ -552,26 +542,20 @@ export function withCacheLookup<TEnv>(
|
|
|
552
542
|
routeKey: ctx.routeKey,
|
|
553
543
|
context: ctx.handlerContext,
|
|
554
544
|
actionContext: ctx.actionContext,
|
|
555
|
-
stale: cacheResult.shouldRevalidate || undefined,
|
|
545
|
+
stale: cacheResult.shouldRevalidate || ctx.stale || undefined,
|
|
556
546
|
traceSource: "cache-hit",
|
|
557
547
|
});
|
|
558
548
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
pathname: ctx.pathname,
|
|
568
|
-
routeKey: ctx.routeKey,
|
|
569
|
-
shouldRevalidate,
|
|
570
|
-
});
|
|
571
|
-
}
|
|
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
|
+
});
|
|
572
557
|
|
|
573
558
|
if (!shouldRevalidate) {
|
|
574
|
-
// Client has it, no revalidation needed
|
|
575
559
|
segment.component = null;
|
|
576
560
|
segment.loading = undefined;
|
|
577
561
|
}
|
|
@@ -579,73 +563,23 @@ export function withCacheLookup<TEnv>(
|
|
|
579
563
|
yield segment;
|
|
580
564
|
}
|
|
581
565
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
if (ctx.isFullMatch) {
|
|
588
|
-
// Full match (document request) - simple loader resolution without revalidation
|
|
589
|
-
if (resolveLoadersOnly) {
|
|
590
|
-
const loaderSegments = await Store.run(() =>
|
|
591
|
-
resolveLoadersOnly(ctx.entries, ctx.handlerContext),
|
|
592
|
-
);
|
|
593
|
-
|
|
594
|
-
// Update state - full match doesn't track matchedIds separately
|
|
595
|
-
state.matchedIds = state.cachedMatchedIds!;
|
|
596
|
-
|
|
597
|
-
// Yield fresh loader segments
|
|
598
|
-
for (const segment of loaderSegments) {
|
|
599
|
-
yield segment;
|
|
600
|
-
}
|
|
601
|
-
} else {
|
|
602
|
-
state.matchedIds = state.cachedMatchedIds!;
|
|
603
|
-
}
|
|
604
|
-
} else {
|
|
605
|
-
// Partial match (navigation) - loader resolution with revalidation
|
|
606
|
-
if (resolveLoadersOnlyWithRevalidation) {
|
|
607
|
-
const loaderResult = await Store.run(() =>
|
|
608
|
-
resolveLoadersOnlyWithRevalidation(
|
|
609
|
-
ctx.entries,
|
|
610
|
-
ctx.handlerContext,
|
|
611
|
-
ctx.clientSegmentSet,
|
|
612
|
-
ctx.prevParams,
|
|
613
|
-
ctx.request,
|
|
614
|
-
ctx.prevUrl,
|
|
615
|
-
ctx.url,
|
|
616
|
-
ctx.routeKey,
|
|
617
|
-
ctx.actionContext,
|
|
618
|
-
cacheResult.shouldRevalidate || undefined,
|
|
619
|
-
),
|
|
620
|
-
);
|
|
621
|
-
|
|
622
|
-
// Update state with fresh loader matchedIds
|
|
623
|
-
state.matchedIds = [
|
|
624
|
-
...state.cachedMatchedIds!,
|
|
625
|
-
...loaderResult.matchedIds,
|
|
626
|
-
];
|
|
627
|
-
|
|
628
|
-
// Yield fresh loader segments
|
|
629
|
-
for (const segment of loaderResult.segments) {
|
|
630
|
-
yield segment;
|
|
631
|
-
}
|
|
632
|
-
} else {
|
|
633
|
-
state.matchedIds = state.cachedMatchedIds!;
|
|
566
|
+
const barrierReqCtx = _getRequestContext();
|
|
567
|
+
if (barrierReqCtx) {
|
|
568
|
+
if (barrierReqCtx._treeHasStreaming === undefined) {
|
|
569
|
+
barrierReqCtx._treeHasStreaming = treeHasStreaming(ctx.entries);
|
|
634
570
|
}
|
|
571
|
+
barrierReqCtx._resolveRenderBarrier(cacheResult.segments);
|
|
635
572
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
startTime: pipelineStart - ms.requestStart,
|
|
648
|
-
});
|
|
649
|
-
}
|
|
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
|
+
);
|
|
650
584
|
};
|
|
651
585
|
}
|