@rangojs/router 0.0.0-experimental.9c9afef3 → 0.0.0-experimental.a014d2b7
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 +3373 -1176
- package/dist/vite/index.js.bak +5448 -0
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +68 -14
- 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 +224 -32
- package/skills/caching/SKILL.md +279 -17
- 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 +235 -9
- package/skills/middleware/SKILL.md +52 -13
- package/skills/migrate-nextjs/SKILL.md +584 -0
- package/skills/migrate-react-router/SKILL.md +771 -0
- package/skills/mime-routes/SKILL.md +28 -1
- package/skills/observability/SKILL.md +172 -0
- package/skills/parallel/SKILL.md +77 -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 +70 -5
- package/skills/router-setup/SKILL.md +65 -8
- 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 +322 -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 +186 -100
- 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 +165 -112
- package/src/browser/prefetch/cache.ts +205 -62
- package/src/browser/prefetch/fetch.ts +347 -39
- package/src/browser/prefetch/queue.ts +42 -8
- package/src/browser/rango-state.ts +158 -76
- package/src/browser/react/Link.tsx +102 -15
- package/src/browser/react/NavigationProvider.tsx +295 -119
- 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 +114 -24
- 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 -72
- package/src/browser/types.ts +102 -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 +224 -41
- package/src/cache/cache-scope.ts +188 -82
- 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/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 +18 -6
- 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 +143 -69
- 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 +52 -31
- 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 +268 -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 +40 -24
- package/src/router/match-middleware/cache-lookup.ts +170 -276
- 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 +87 -39
- package/src/router/metrics.ts +0 -34
- package/src/router/middleware-types.ts +7 -140
- package/src/router/middleware.ts +266 -169
- 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/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 -28
- package/src/router/router-interfaces.ts +115 -35
- package/src/router/router-options.ts +172 -15
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +162 -84
- package/src/router/segment-resolution/helpers.ts +86 -6
- package/src/router/segment-resolution/loader-cache.ts +76 -39
- package/src/router/segment-resolution/revalidation.ts +351 -321
- 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 +9 -63
- package/src/router/url-params.ts +44 -0
- package/src/router.ts +157 -54
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +655 -529
- 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 +122 -31
- package/src/rsc/manifest-init.ts +33 -42
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +131 -14
- 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 +109 -74
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +287 -115
- package/src/rsc/ssr-setup.ts +18 -2
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +29 -9
- 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 +236 -202
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +224 -52
- 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 +401 -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 +125 -71
- package/src/types/index.ts +3 -10
- package/src/types/loader-types.ts +40 -11
- 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 +64 -170
- 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 +118 -114
- 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/debug-channel.ts +0 -93
- 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,72 +378,20 @@ export function withCacheLookup<TEnv>(
|
|
|
314
378
|
resolveLoadersOnly,
|
|
315
379
|
} = getRouterContext<TEnv>();
|
|
316
380
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
if (!ctx.isAction && ctx.matched.pr) {
|
|
381
|
+
const isHmr = !!ctx.request.headers.get("X-RSC-HMR");
|
|
382
|
+
if (!ctx.isAction && !isHmr && ctx.matched.pr) {
|
|
320
383
|
await ensurePrerenderDeps();
|
|
321
384
|
if (prerenderStoreInstance) {
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
385
|
+
const served = yield* tryPrerenderLookup(
|
|
386
|
+
ctx,
|
|
387
|
+
state,
|
|
388
|
+
pipelineStart,
|
|
389
|
+
handleStoreRef,
|
|
327
390
|
);
|
|
328
|
-
|
|
329
|
-
if (ctx.isIntercept) {
|
|
330
|
-
// Intercept navigation: try intercept-specific prerender entry
|
|
331
|
-
const entry = await prerenderStoreInstance.get(
|
|
332
|
-
ctx.matched.routeKey,
|
|
333
|
-
paramHash + "/i",
|
|
334
|
-
{
|
|
335
|
-
pathname: ctx.pathname,
|
|
336
|
-
isPassthroughRoute: isPassthroughPrerenderRoute,
|
|
337
|
-
},
|
|
338
|
-
);
|
|
339
|
-
if (entry) {
|
|
340
|
-
yield* yieldFromStore(
|
|
341
|
-
entry,
|
|
342
|
-
ctx,
|
|
343
|
-
state,
|
|
344
|
-
pipelineStart,
|
|
345
|
-
handleStoreRef,
|
|
346
|
-
);
|
|
347
|
-
return;
|
|
348
|
-
}
|
|
349
|
-
// No intercept prerender -- fall through to normal pipeline
|
|
350
|
-
// (skip non-intercept prerender to let intercept-resolution run)
|
|
351
|
-
} else {
|
|
352
|
-
// Normal navigation: existing behavior
|
|
353
|
-
const entry = await prerenderStoreInstance.get(
|
|
354
|
-
ctx.matched.routeKey,
|
|
355
|
-
paramHash,
|
|
356
|
-
{
|
|
357
|
-
pathname: ctx.pathname,
|
|
358
|
-
isPassthroughRoute: isPassthroughPrerenderRoute,
|
|
359
|
-
},
|
|
360
|
-
);
|
|
361
|
-
if (entry) {
|
|
362
|
-
yield* yieldFromStore(
|
|
363
|
-
entry,
|
|
364
|
-
ctx,
|
|
365
|
-
state,
|
|
366
|
-
pipelineStart,
|
|
367
|
-
handleStoreRef,
|
|
368
|
-
);
|
|
369
|
-
return;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
391
|
+
if (served) return;
|
|
372
392
|
}
|
|
373
393
|
}
|
|
374
394
|
|
|
375
|
-
// Dev-mode static handler interception for non-Node.js runtimes.
|
|
376
|
-
// __PRERENDER_DEV_URL is set by the Vite plugin when the RSC environment
|
|
377
|
-
// lacks a Node.js module runner (e.g. workerd, Deno workers). In those
|
|
378
|
-
// runtimes, handlers that depend on Node APIs like node:fs can't run
|
|
379
|
-
// in-process. We redirect them to the /__rsc_prerender endpoint which
|
|
380
|
-
// resolves segments in a Node.js temp server, same as prerender routes.
|
|
381
|
-
// In Node.js dev mode this variable is undefined -- handlers run
|
|
382
|
-
// in-process where Node APIs work, so no interception is needed.
|
|
383
395
|
if (!ctx.isAction && !ctx.matched.pr && globalThis.__PRERENDER_DEV_URL) {
|
|
384
396
|
const hasStatic = ctx.entries.some(
|
|
385
397
|
(e) =>
|
|
@@ -391,60 +403,18 @@ export function withCacheLookup<TEnv>(
|
|
|
391
403
|
if (hasStatic) {
|
|
392
404
|
await ensurePrerenderDeps();
|
|
393
405
|
if (prerenderStoreInstance) {
|
|
394
|
-
const
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
406
|
+
const served = yield* tryPrerenderLookup(
|
|
407
|
+
ctx,
|
|
408
|
+
state,
|
|
409
|
+
pipelineStart,
|
|
410
|
+
handleStoreRef,
|
|
399
411
|
);
|
|
400
|
-
|
|
401
|
-
if (ctx.isIntercept) {
|
|
402
|
-
const entry = await prerenderStoreInstance.get(
|
|
403
|
-
ctx.matched.routeKey,
|
|
404
|
-
paramHash + "/i",
|
|
405
|
-
{
|
|
406
|
-
pathname: ctx.pathname,
|
|
407
|
-
isPassthroughRoute: isPassthroughPrerenderRoute,
|
|
408
|
-
},
|
|
409
|
-
);
|
|
410
|
-
if (entry) {
|
|
411
|
-
yield* yieldFromStore(
|
|
412
|
-
entry,
|
|
413
|
-
ctx,
|
|
414
|
-
state,
|
|
415
|
-
pipelineStart,
|
|
416
|
-
handleStoreRef,
|
|
417
|
-
);
|
|
418
|
-
return;
|
|
419
|
-
}
|
|
420
|
-
// No intercept prerender -- fall through to normal pipeline
|
|
421
|
-
} else {
|
|
422
|
-
const entry = await prerenderStoreInstance.get(
|
|
423
|
-
ctx.matched.routeKey,
|
|
424
|
-
paramHash,
|
|
425
|
-
{
|
|
426
|
-
pathname: ctx.pathname,
|
|
427
|
-
isPassthroughRoute: isPassthroughPrerenderRoute,
|
|
428
|
-
},
|
|
429
|
-
);
|
|
430
|
-
if (entry) {
|
|
431
|
-
yield* yieldFromStore(
|
|
432
|
-
entry,
|
|
433
|
-
ctx,
|
|
434
|
-
state,
|
|
435
|
-
pipelineStart,
|
|
436
|
-
handleStoreRef,
|
|
437
|
-
);
|
|
438
|
-
return;
|
|
439
|
-
}
|
|
440
|
-
}
|
|
412
|
+
if (served) return;
|
|
441
413
|
}
|
|
442
414
|
}
|
|
443
415
|
}
|
|
444
416
|
|
|
445
|
-
// Skip cache during actions
|
|
446
417
|
if (ctx.isAction || !ctx.cacheScope?.enabled) {
|
|
447
|
-
// Cache miss - pass through to segment resolution
|
|
448
418
|
yield* source;
|
|
449
419
|
if (ms) {
|
|
450
420
|
ms.metrics.push({
|
|
@@ -456,7 +426,6 @@ export function withCacheLookup<TEnv>(
|
|
|
456
426
|
return;
|
|
457
427
|
}
|
|
458
428
|
|
|
459
|
-
// Lookup cache
|
|
460
429
|
const cacheResult = await ctx.cacheScope.lookupRoute(
|
|
461
430
|
ctx.pathname,
|
|
462
431
|
ctx.matched.params,
|
|
@@ -464,7 +433,6 @@ export function withCacheLookup<TEnv>(
|
|
|
464
433
|
);
|
|
465
434
|
|
|
466
435
|
if (!cacheResult) {
|
|
467
|
-
// Cache miss - pass through to segment resolution
|
|
468
436
|
yield* source;
|
|
469
437
|
if (ms) {
|
|
470
438
|
ms.metrics.push({
|
|
@@ -476,16 +444,12 @@ export function withCacheLookup<TEnv>(
|
|
|
476
444
|
return;
|
|
477
445
|
}
|
|
478
446
|
|
|
479
|
-
// Cache HIT
|
|
480
447
|
state.cacheHit = true;
|
|
481
448
|
state.cacheSource = "runtime";
|
|
482
449
|
state.shouldRevalidate = cacheResult.shouldRevalidate;
|
|
483
450
|
state.cachedSegments = cacheResult.segments;
|
|
484
451
|
state.cachedMatchedIds = cacheResult.segments.map((s) => s.id);
|
|
485
452
|
|
|
486
|
-
// Apply revalidation to cached segments.
|
|
487
|
-
// For full matches or empty client segment sets, this map is unnecessary:
|
|
488
|
-
// we never run segment-level revalidation and can stream segments directly.
|
|
489
453
|
const canCheckSegmentRevalidation =
|
|
490
454
|
!ctx.isFullMatch &&
|
|
491
455
|
ctx.clientSegmentSet.size > 0 &&
|
|
@@ -495,7 +459,6 @@ export function withCacheLookup<TEnv>(
|
|
|
495
459
|
: undefined;
|
|
496
460
|
|
|
497
461
|
for (const segment of cacheResult.segments) {
|
|
498
|
-
// Skip segments client doesn't have - they need their component
|
|
499
462
|
if (!ctx.clientSegmentSet.has(segment.id)) {
|
|
500
463
|
if (isTraceActive()) {
|
|
501
464
|
pushRevalidationTraceEntry({
|
|
@@ -512,19 +475,13 @@ export function withCacheLookup<TEnv>(
|
|
|
512
475
|
continue;
|
|
513
476
|
}
|
|
514
477
|
|
|
515
|
-
// Skip intercept segments - they're handled separately
|
|
516
478
|
if (segment.namespace?.startsWith("intercept:")) {
|
|
517
479
|
yield segment;
|
|
518
480
|
continue;
|
|
519
481
|
}
|
|
520
482
|
|
|
521
|
-
// Look up revalidation rules for this segment
|
|
522
483
|
const entryInfo = entryRevalidateMap?.get(segment.id);
|
|
523
484
|
|
|
524
|
-
// Even without explicit revalidation rules, route segments and their
|
|
525
|
-
// children must re-render when params or search params change — the
|
|
526
|
-
// handler reads ctx.params/ctx.searchParams so different values produce
|
|
527
|
-
// different content. Matches evaluateRevalidation's default logic.
|
|
528
485
|
const searchChanged = ctx.prevUrl.search !== ctx.url.search;
|
|
529
486
|
const routeParamsChanged = !paramsEqual(
|
|
530
487
|
ctx.matched.params,
|
|
@@ -538,7 +495,6 @@ export function withCacheLookup<TEnv>(
|
|
|
538
495
|
|
|
539
496
|
if (!entryInfo || entryInfo.revalidate.length === 0) {
|
|
540
497
|
if (shouldDefaultRevalidate) {
|
|
541
|
-
// Params or search params changed — must re-render even without custom rules
|
|
542
498
|
if (isTraceActive()) {
|
|
543
499
|
pushRevalidationTraceEntry({
|
|
544
500
|
segmentId: segment.id,
|
|
@@ -555,7 +511,6 @@ export function withCacheLookup<TEnv>(
|
|
|
555
511
|
yield segment;
|
|
556
512
|
continue;
|
|
557
513
|
}
|
|
558
|
-
// No revalidation rules, use default behavior (skip if client has)
|
|
559
514
|
if (isTraceActive()) {
|
|
560
515
|
pushRevalidationTraceEntry({
|
|
561
516
|
segmentId: segment.id,
|
|
@@ -573,7 +528,6 @@ export function withCacheLookup<TEnv>(
|
|
|
573
528
|
continue;
|
|
574
529
|
}
|
|
575
530
|
|
|
576
|
-
// Evaluate revalidation rules
|
|
577
531
|
const shouldRevalidate = await evaluateRevalidation({
|
|
578
532
|
segment,
|
|
579
533
|
prevParams: ctx.prevParams,
|
|
@@ -588,26 +542,20 @@ export function withCacheLookup<TEnv>(
|
|
|
588
542
|
routeKey: ctx.routeKey,
|
|
589
543
|
context: ctx.handlerContext,
|
|
590
544
|
actionContext: ctx.actionContext,
|
|
591
|
-
stale: cacheResult.shouldRevalidate || undefined,
|
|
545
|
+
stale: cacheResult.shouldRevalidate || ctx.stale || undefined,
|
|
592
546
|
traceSource: "cache-hit",
|
|
593
547
|
});
|
|
594
548
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
pathname: ctx.pathname,
|
|
604
|
-
routeKey: ctx.routeKey,
|
|
605
|
-
shouldRevalidate,
|
|
606
|
-
});
|
|
607
|
-
}
|
|
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
|
+
});
|
|
608
557
|
|
|
609
558
|
if (!shouldRevalidate) {
|
|
610
|
-
// Client has it, no revalidation needed
|
|
611
559
|
segment.component = null;
|
|
612
560
|
segment.loading = undefined;
|
|
613
561
|
}
|
|
@@ -615,77 +563,23 @@ export function withCacheLookup<TEnv>(
|
|
|
615
563
|
yield segment;
|
|
616
564
|
}
|
|
617
565
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
if (ctx.isFullMatch) {
|
|
624
|
-
// Full match (document request) - simple loader resolution without revalidation
|
|
625
|
-
if (resolveLoadersOnly) {
|
|
626
|
-
const loaderSegments = await Store.run(() =>
|
|
627
|
-
resolveLoadersOnly(ctx.entries, ctx.handlerContext),
|
|
628
|
-
);
|
|
629
|
-
|
|
630
|
-
// Update state - full match doesn't track matchedIds separately
|
|
631
|
-
state.matchedIds = state.cachedMatchedIds!;
|
|
632
|
-
|
|
633
|
-
// Yield fresh loader segments
|
|
634
|
-
for (const segment of loaderSegments) {
|
|
635
|
-
yield segment;
|
|
636
|
-
}
|
|
637
|
-
} else {
|
|
638
|
-
state.matchedIds = state.cachedMatchedIds!;
|
|
639
|
-
}
|
|
640
|
-
} else {
|
|
641
|
-
// Partial match (navigation) - loader resolution with revalidation
|
|
642
|
-
if (resolveLoadersOnlyWithRevalidation) {
|
|
643
|
-
const loaderResult = await Store.run(() =>
|
|
644
|
-
resolveLoadersOnlyWithRevalidation(
|
|
645
|
-
ctx.entries,
|
|
646
|
-
ctx.handlerContext,
|
|
647
|
-
ctx.clientSegmentSet,
|
|
648
|
-
ctx.prevParams,
|
|
649
|
-
ctx.request,
|
|
650
|
-
ctx.prevUrl,
|
|
651
|
-
ctx.url,
|
|
652
|
-
ctx.routeKey,
|
|
653
|
-
ctx.actionContext,
|
|
654
|
-
// Loaders are never cached in the segment cache, so segment
|
|
655
|
-
// staleness (cacheResult.shouldRevalidate) must not propagate.
|
|
656
|
-
// But browser-sent staleness (ctx.stale) — indicating an action
|
|
657
|
-
// happened in this or another tab — must still reach loaders.
|
|
658
|
-
ctx.stale || undefined,
|
|
659
|
-
),
|
|
660
|
-
);
|
|
661
|
-
|
|
662
|
-
// Update state with fresh loader matchedIds
|
|
663
|
-
state.matchedIds = [
|
|
664
|
-
...state.cachedMatchedIds!,
|
|
665
|
-
...loaderResult.matchedIds,
|
|
666
|
-
];
|
|
667
|
-
|
|
668
|
-
// Yield fresh loader segments
|
|
669
|
-
for (const segment of loaderResult.segments) {
|
|
670
|
-
yield segment;
|
|
671
|
-
}
|
|
672
|
-
} else {
|
|
673
|
-
state.matchedIds = state.cachedMatchedIds!;
|
|
566
|
+
const barrierReqCtx = _getRequestContext();
|
|
567
|
+
if (barrierReqCtx) {
|
|
568
|
+
if (barrierReqCtx._treeHasStreaming === undefined) {
|
|
569
|
+
barrierReqCtx._treeHasStreaming = treeHasStreaming(ctx.entries);
|
|
674
570
|
}
|
|
571
|
+
barrierReqCtx._resolveRenderBarrier(cacheResult.segments);
|
|
675
572
|
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
startTime: pipelineStart - ms.requestStart,
|
|
688
|
-
});
|
|
689
|
-
}
|
|
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
|
+
);
|
|
690
584
|
};
|
|
691
585
|
}
|