@rangojs/router 0.0.0-experimental.eb0645d3 → 0.0.0-experimental.f1468e3c
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 +126 -16
- package/dist/bin/rango.js +319 -95
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +2724 -1053
- 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 +11 -9
- package/skills/hooks/SKILL.md +243 -29
- package/skills/host-router/SKILL.md +83 -23
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +68 -19
- package/skills/layout/SKILL.md +13 -9
- package/skills/links/SKILL.md +190 -23
- package/skills/loader/SKILL.md +235 -9
- package/skills/middleware/SKILL.md +18 -10
- package/skills/migrate-nextjs/SKILL.md +43 -19
- package/skills/migrate-react-router/SKILL.md +8 -2
- package/skills/mime-routes/SKILL.md +28 -1
- package/skills/observability/SKILL.md +172 -0
- package/skills/parallel/SKILL.md +18 -7
- package/skills/prerender/SKILL.md +65 -60
- package/skills/rango/SKILL.md +251 -24
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +115 -48
- package/skills/route/SKILL.md +46 -5
- package/skills/router-setup/SKILL.md +30 -8
- package/skills/scripts/SKILL.md +179 -0
- package/skills/server-actions/SKILL.md +775 -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 +0 -65
- package/src/browser/action-coordinator.ts +53 -36
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/app-shell.ts +39 -0
- package/src/browser/connection-warmup.ts +134 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +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 +94 -25
- package/src/browser/navigation-client.ts +121 -84
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +115 -67
- package/src/browser/navigation-transaction.ts +9 -59
- package/src/browser/network-error-handler.ts +34 -7
- package/src/browser/partial-update.ts +147 -128
- package/src/browser/prefetch/cache.ts +107 -56
- package/src/browser/prefetch/fetch.ts +204 -34
- package/src/browser/prefetch/queue.ts +6 -3
- package/src/browser/rango-state.ts +158 -76
- package/src/browser/react/Link.tsx +30 -7
- package/src/browser/react/NavigationProvider.tsx +283 -118
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- 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 +17 -14
- package/src/browser/react/use-href.tsx +8 -1
- package/src/browser/react/use-link-status.ts +33 -8
- package/src/browser/react/use-navigation.ts +10 -5
- package/src/browser/react/use-params.ts +11 -11
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +25 -3
- package/src/browser/react/use-search-params.ts +0 -5
- package/src/browser/react/use-segments.ts +11 -21
- package/src/browser/response-adapter.ts +99 -8
- package/src/browser/rsc-router.tsx +91 -24
- package/src/browser/scroll-restoration.ts +30 -17
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +214 -55
- package/src/browser/types.ts +80 -9
- package/src/browser/validate-redirect-origin.ts +43 -16
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +60 -35
- package/src/build/generate-route-types.ts +2 -1
- package/src/build/index.ts +8 -2
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +117 -14
- 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 +117 -23
- 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 +55 -28
- package/src/build/route-types/scan-filter.ts +1 -1
- 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 +36 -61
- 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 +31 -23
- 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 +96 -12
- package/src/index.ts +94 -14
- 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 +32 -37
- package/src/prerender.ts +61 -6
- 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 +34 -0
- package/src/reverse.ts +65 -40
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +19 -77
- package/src/route-definition/dsl-helpers.ts +304 -309
- package/src/route-definition/helper-factories.ts +28 -140
- package/src/route-definition/helpers-types.ts +82 -55
- package/src/route-definition/index.ts +1 -2
- package/src/route-definition/redirect.ts +44 -11
- package/src/route-definition/resolve-handler-use.ts +12 -1
- package/src/route-definition/use-item-types.ts +29 -0
- package/src/route-map-builder.ts +0 -16
- package/src/route-types.ts +19 -46
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +73 -25
- package/src/router/error-handling.ts +45 -18
- package/src/router/find-match.ts +44 -23
- package/src/router/handler-context.ts +27 -43
- package/src/router/instrument.ts +350 -0
- package/src/router/intercept-resolution.ts +39 -20
- package/src/router/lazy-includes.ts +10 -47
- package/src/router/loader-resolution.ts +155 -72
- package/src/router/logging.ts +0 -6
- package/src/router/manifest.ts +18 -29
- package/src/router/match-api.ts +9 -24
- 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 +159 -285
- 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 +0 -22
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +44 -74
- package/src/router/metrics.ts +0 -34
- package/src/router/middleware-types.ts +7 -134
- package/src/router/middleware.ts +247 -166
- package/src/router/navigation-snapshot.ts +0 -51
- package/src/router/params-util.ts +23 -0
- package/src/router/pattern-matching.ts +85 -94
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prerender-match.ts +104 -65
- package/src/router/preview-match.ts +3 -1
- package/src/router/request-classification.ts +28 -62
- package/src/router/revalidation.ts +123 -73
- package/src/router/route-snapshot.ts +0 -1
- package/src/router/router-context.ts +3 -28
- package/src/router/router-interfaces.ts +83 -35
- package/src/router/router-options.ts +136 -5
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +97 -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 +272 -320
- 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 +162 -64
- package/src/router/types.ts +9 -63
- package/src/router/url-params.ts +0 -5
- package/src/router.ts +110 -55
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +264 -220
- package/src/rsc/helpers.ts +100 -6
- package/src/rsc/index.ts +2 -5
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +114 -38
- package/src/rsc/manifest-init.ts +28 -41
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +117 -11
- 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 +88 -188
- package/src/rsc/rsc-rendering.ts +98 -76
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +281 -117
- package/src/rsc/ssr-setup.ts +16 -0
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +23 -5
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +35 -30
- package/src/segment-loader-promise.ts +31 -4
- package/src/segment-system.tsx +254 -143
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +163 -51
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +80 -5
- package/src/server/handle-store.ts +21 -38
- package/src/server/loader-registry.ts +33 -42
- package/src/server/request-context.ts +287 -178
- package/src/ssr/index.tsx +21 -16
- package/src/static-handler.ts +10 -13
- 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 +13 -4
- package/src/types/error-types.ts +30 -90
- package/src/types/global-namespace.ts +54 -41
- package/src/types/handler-context.ts +110 -62
- package/src/types/index.ts +3 -10
- package/src/types/loader-types.ts +11 -9
- package/src/types/request-scope.ts +112 -0
- package/src/types/route-config.ts +6 -50
- package/src/types/route-entry.ts +0 -6
- package/src/types/segments.ts +135 -14
- package/src/urls/include-helper.ts +9 -56
- package/src/urls/index.ts +1 -11
- package/src/urls/path-helper-types.ts +29 -12
- package/src/urls/path-helper.ts +17 -106
- package/src/urls/pattern-types.ts +36 -19
- package/src/urls/response-types.ts +22 -29
- package/src/urls/type-extraction.ts +58 -139
- package/src/urls/urls-function.ts +1 -19
- package/src/use-loader.tsx +292 -107
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +8 -7
- package/src/vite/discovery/discover-routers.ts +126 -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 +96 -68
- 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 +44 -0
- package/src/vite/discovery/virtual-module-codegen.ts +14 -34
- package/src/vite/index.ts +2 -0
- package/src/vite/inject-client-debug.ts +36 -0
- package/src/vite/plugin-types.ts +126 -8
- 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-stub.ts +1 -21
- package/src/vite/plugins/expose-action-id.ts +48 -95
- package/src/vite/plugins/expose-id-utils.ts +88 -55
- package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
- package/src/vite/plugins/expose-ids/handler-transform.ts +11 -90
- 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 +505 -486
- package/src/vite/plugins/performance-tracks.ts +26 -25
- package/src/vite/plugins/refresh-cmd.ts +1 -1
- 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 +109 -118
- package/src/vite/router-discovery.ts +718 -119
- 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 +54 -39
- package/src/vite/utils/shared-utils.ts +90 -41
- 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
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
|
|
15
15
|
import type { Plugin } from "vite";
|
|
16
16
|
import { readFile } from "node:fs/promises";
|
|
17
|
+
import { createRangoDebugger, createCounter, NS } from "../debug.js";
|
|
18
|
+
|
|
19
|
+
const debug = createRangoDebugger(NS.transform);
|
|
17
20
|
|
|
18
21
|
const RSDW_PATCH_RE =
|
|
19
22
|
/((?:var|let|const)\s+\w+\s*=\s*root\._children\s*,\s*(\w+)\s*=\s*root\._debugInfo\s*[;,])/;
|
|
@@ -45,44 +48,42 @@ export function patchRsdwClientDebugInfoRecovery(code: string): {
|
|
|
45
48
|
|
|
46
49
|
export function performanceTracksOptimizeDepsPlugin(): {
|
|
47
50
|
name: string;
|
|
48
|
-
|
|
51
|
+
load(id: string): Promise<{ code: string } | null>;
|
|
49
52
|
} {
|
|
53
|
+
const RSDW_CLIENT_RE =
|
|
54
|
+
/react-server-dom-webpack-client\.browser\.(development|production)\.js$/;
|
|
50
55
|
return {
|
|
51
56
|
name: "@rangojs/router:performance-tracks-optimize-deps",
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
async (args: { path: string }) => {
|
|
59
|
-
const code = await readFile(args.path, "utf8");
|
|
60
|
-
const patched = patchRsdwClientDebugInfoRecovery(code);
|
|
61
|
-
return {
|
|
62
|
-
contents: patched.code,
|
|
63
|
-
loader: "js",
|
|
64
|
-
};
|
|
65
|
-
},
|
|
66
|
-
);
|
|
57
|
+
async load(id: string): Promise<{ code: string } | null> {
|
|
58
|
+
const cleanId = id.split("?")[0] ?? id;
|
|
59
|
+
if (!RSDW_CLIENT_RE.test(cleanId)) return null;
|
|
60
|
+
const code = await readFile(cleanId, "utf8");
|
|
61
|
+
const patched = patchRsdwClientDebugInfoRecovery(code);
|
|
62
|
+
return { code: patched.code };
|
|
67
63
|
},
|
|
68
64
|
};
|
|
69
65
|
}
|
|
70
66
|
|
|
71
67
|
export function performanceTracksPlugin(): Plugin {
|
|
68
|
+
const counter = createCounter(debug, "performance-tracks");
|
|
72
69
|
return {
|
|
73
70
|
name: "@rangojs/router:performance-tracks",
|
|
74
71
|
|
|
72
|
+
buildEnd() {
|
|
73
|
+
counter?.flush();
|
|
74
|
+
},
|
|
75
|
+
|
|
75
76
|
transform(code, id) {
|
|
76
77
|
if (!id.includes("react-server-dom") || !id.includes("client")) return;
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
);
|
|
85
|
-
|
|
78
|
+
const start = counter ? performance.now() : 0;
|
|
79
|
+
try {
|
|
80
|
+
const patched = patchRsdwClientDebugInfoRecovery(code);
|
|
81
|
+
if (!patched.debugInfoVar) return;
|
|
82
|
+
debug?.("patched RSDW client (var: %s)", patched.debugInfoVar);
|
|
83
|
+
return patched.code;
|
|
84
|
+
} finally {
|
|
85
|
+
counter?.record(id, performance.now() - start);
|
|
86
|
+
}
|
|
86
87
|
},
|
|
87
88
|
};
|
|
88
89
|
}
|
|
@@ -20,6 +20,9 @@ import type { Plugin } from "vite";
|
|
|
20
20
|
import path from "node:path";
|
|
21
21
|
import MagicString from "magic-string";
|
|
22
22
|
import { normalizePath, hashId } from "./expose-id-utils.js";
|
|
23
|
+
import { createRangoDebugger, createCounter, NS } from "../debug.js";
|
|
24
|
+
|
|
25
|
+
const debug = createRangoDebugger(NS.transform);
|
|
23
26
|
|
|
24
27
|
const CACHE_RUNTIME_IMPORT = "@rangojs/router/cache-runtime";
|
|
25
28
|
|
|
@@ -27,11 +30,14 @@ const CACHE_RUNTIME_IMPORT = "@rangojs/router/cache-runtime";
|
|
|
27
30
|
// and should not be wrapped (children can't be cache-keyed).
|
|
28
31
|
const LAYOUT_TEMPLATE_PATTERN = /\/(layout|template)\.(tsx?|jsx?)$/;
|
|
29
32
|
|
|
33
|
+
export const USE_CACHE_DIRECTIVE_RE: RegExp = /^use cache(:\s*[\w-]+)?$/;
|
|
34
|
+
|
|
30
35
|
export function useCacheTransform(): Plugin {
|
|
31
36
|
let projectRoot = "";
|
|
32
37
|
let isBuild = false;
|
|
33
38
|
let rscTransforms: typeof import("@vitejs/plugin-rsc/transforms") | null =
|
|
34
39
|
null;
|
|
40
|
+
const counter = createCounter(debug, "use-cache");
|
|
35
41
|
|
|
36
42
|
return {
|
|
37
43
|
name: "@rangojs/router:use-cache",
|
|
@@ -42,6 +48,10 @@ export function useCacheTransform(): Plugin {
|
|
|
42
48
|
isBuild = config.command === "build";
|
|
43
49
|
},
|
|
44
50
|
|
|
51
|
+
buildEnd() {
|
|
52
|
+
counter?.flush();
|
|
53
|
+
},
|
|
54
|
+
|
|
45
55
|
async transform(code, id) {
|
|
46
56
|
// Only process in RSC environment
|
|
47
57
|
if (this.environment?.name !== "rsc") return;
|
|
@@ -55,63 +65,60 @@ export function useCacheTransform(): Plugin {
|
|
|
55
65
|
// Only JS/TS files
|
|
56
66
|
if (!/\.(tsx?|jsx?|mjs)$/.test(id)) return;
|
|
57
67
|
|
|
58
|
-
|
|
59
|
-
|
|
68
|
+
const start = counter ? performance.now() : 0;
|
|
69
|
+
try {
|
|
70
|
+
if (!rscTransforms) {
|
|
71
|
+
try {
|
|
72
|
+
rscTransforms = await import("@vitejs/plugin-rsc/transforms");
|
|
73
|
+
} catch {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const {
|
|
79
|
+
hasDirective,
|
|
80
|
+
transformWrapExport,
|
|
81
|
+
transformHoistInlineDirective,
|
|
82
|
+
} = rscTransforms;
|
|
83
|
+
|
|
84
|
+
let ast: any;
|
|
60
85
|
try {
|
|
61
|
-
|
|
86
|
+
const { parseAst } = await import("vite");
|
|
87
|
+
ast = parseAst(code, { lang: "tsx" });
|
|
62
88
|
} catch {
|
|
63
89
|
return;
|
|
64
90
|
}
|
|
65
|
-
}
|
|
66
91
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const filePath = normalizePath(path.relative(projectRoot, id));
|
|
83
|
-
const isLayoutOrTemplate = LAYOUT_TEMPLATE_PATTERN.test(id);
|
|
92
|
+
const filePath = normalizePath(path.relative(projectRoot, id));
|
|
93
|
+
const isLayoutOrTemplate = LAYOUT_TEMPLATE_PATTERN.test(id);
|
|
94
|
+
|
|
95
|
+
if (hasDirective(ast.body, "use cache")) {
|
|
96
|
+
return transformFileLevelUseCache(
|
|
97
|
+
code,
|
|
98
|
+
ast,
|
|
99
|
+
filePath,
|
|
100
|
+
id,
|
|
101
|
+
isBuild,
|
|
102
|
+
isLayoutOrTemplate,
|
|
103
|
+
transformWrapExport,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
84
106
|
|
|
85
|
-
|
|
86
|
-
if (hasDirective(ast.body, "use cache")) {
|
|
87
|
-
return transformFileLevelUseCache(
|
|
107
|
+
const functionResult = transformFunctionLevelUseCache(
|
|
88
108
|
code,
|
|
89
109
|
ast,
|
|
90
110
|
filePath,
|
|
91
111
|
id,
|
|
92
112
|
isBuild,
|
|
93
|
-
|
|
94
|
-
transformWrapExport,
|
|
113
|
+
transformHoistInlineDirective,
|
|
95
114
|
);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Check for function-level "use cache" / "use cache: profileName"
|
|
99
|
-
// (only if there's no file-level directive but code still contains the string)
|
|
100
|
-
const functionResult = transformFunctionLevelUseCache(
|
|
101
|
-
code,
|
|
102
|
-
ast,
|
|
103
|
-
filePath,
|
|
104
|
-
id,
|
|
105
|
-
isBuild,
|
|
106
|
-
transformHoistInlineDirective,
|
|
107
|
-
);
|
|
108
115
|
|
|
109
|
-
|
|
110
|
-
// exist. A file may contain both valid and invalid "use cache" directives
|
|
111
|
-
// in different functions — the invalid ones should still warn.
|
|
112
|
-
warnOnNearMissDirectives(ast, id, this.warn.bind(this));
|
|
116
|
+
warnOnNearMissDirectives(ast, id, this.warn.bind(this));
|
|
113
117
|
|
|
114
|
-
|
|
118
|
+
if (functionResult) return functionResult;
|
|
119
|
+
} finally {
|
|
120
|
+
counter?.record(id, performance.now() - start);
|
|
121
|
+
}
|
|
115
122
|
},
|
|
116
123
|
};
|
|
117
124
|
}
|
|
@@ -125,8 +132,7 @@ function transformFileLevelUseCache(
|
|
|
125
132
|
isLayoutOrTemplate: boolean,
|
|
126
133
|
transformWrapExport: (typeof import("@vitejs/plugin-rsc/transforms"))["transformWrapExport"],
|
|
127
134
|
) {
|
|
128
|
-
|
|
129
|
-
const nonFunctionExports: string[] = [];
|
|
135
|
+
const unconfirmedExports: string[] = [];
|
|
130
136
|
|
|
131
137
|
const { exportNames, output } = transformWrapExport(code, ast, {
|
|
132
138
|
runtime: (value: string, name: string) => {
|
|
@@ -135,30 +141,38 @@ function transformFileLevelUseCache(
|
|
|
135
141
|
},
|
|
136
142
|
rejectNonAsyncFunction: false,
|
|
137
143
|
filter: (name: string, meta: { isFunction?: boolean }) => {
|
|
138
|
-
// Skip default export of layout/template files (they receive children)
|
|
139
144
|
if (name === "default" && isLayoutOrTemplate) return false;
|
|
140
|
-
//
|
|
141
|
-
|
|
142
|
-
|
|
145
|
+
// isFunction is boolean | undefined: true = confirmed function, false =
|
|
146
|
+
// confirmed non-function, undefined = cannot tell statically (e.g. a
|
|
147
|
+
// factory/HOF initializer `const x = makeCached(fn)`). Deliberate policy:
|
|
148
|
+
// require a confirmed function and reject everything else, including
|
|
149
|
+
// indeterminate initializers that may be functions at runtime -- rewrite
|
|
150
|
+
// those as direct async functions. (Pre-#1246 plugin-rsc reported false,
|
|
151
|
+
// not undefined, here, so === false would wrongly wrap them post-bump.)
|
|
152
|
+
if (meta.isFunction !== true) {
|
|
153
|
+
unconfirmedExports.push(name);
|
|
143
154
|
return false;
|
|
144
155
|
}
|
|
145
156
|
return true;
|
|
146
157
|
},
|
|
147
158
|
});
|
|
148
159
|
|
|
149
|
-
if (
|
|
160
|
+
if (unconfirmedExports.length > 0) {
|
|
161
|
+
const plural = unconfirmedExports.length > 1;
|
|
150
162
|
throw new Error(
|
|
151
|
-
`[rango:use-cache] File-level "use cache" in ${sourceId}
|
|
152
|
-
`
|
|
153
|
-
`${
|
|
154
|
-
|
|
155
|
-
`
|
|
156
|
-
`
|
|
163
|
+
`[rango:use-cache] File-level "use cache" in ${sourceId} only wraps ` +
|
|
164
|
+
`exports that are statically-confirmed functions. ` +
|
|
165
|
+
`${plural ? "These exports are" : "This export is"} not: ` +
|
|
166
|
+
`${unconfirmedExports.map((n) => `"${n}"`).join(", ")}. ` +
|
|
167
|
+
`Declare them directly (export async function foo() {} or ` +
|
|
168
|
+
`export const foo = async () => {}). A factory or otherwise ` +
|
|
169
|
+
`statically-indeterminate initializer (export const foo = makeCached(fn)) ` +
|
|
170
|
+
`is rejected even if it returns a function at runtime -- rewrite it as a ` +
|
|
171
|
+
`direct async function, or move non-function exports to a separate module.`,
|
|
157
172
|
);
|
|
158
173
|
}
|
|
159
174
|
|
|
160
175
|
if (exportNames.length === 0) {
|
|
161
|
-
// Even if no exports were wrapped, strip the directive
|
|
162
176
|
const s = new MagicString(code);
|
|
163
177
|
const directive = findFileLevelDirective(ast);
|
|
164
178
|
if (directive) {
|
|
@@ -175,12 +189,10 @@ function transformFileLevelUseCache(
|
|
|
175
189
|
return;
|
|
176
190
|
}
|
|
177
191
|
|
|
178
|
-
// Prepend the import
|
|
179
192
|
output.prepend(
|
|
180
193
|
`import { registerCachedFunction as __rango_registerCachedFunction } from ${JSON.stringify(CACHE_RUNTIME_IMPORT)};\n`,
|
|
181
194
|
);
|
|
182
195
|
|
|
183
|
-
// Replace the directive with a comment
|
|
184
196
|
const directive = findFileLevelDirective(ast);
|
|
185
197
|
if (directive) {
|
|
186
198
|
output.overwrite(
|
|
@@ -206,7 +218,7 @@ function transformFunctionLevelUseCache(
|
|
|
206
218
|
) {
|
|
207
219
|
try {
|
|
208
220
|
const { output, names } = transformHoistInlineDirective(code, ast, {
|
|
209
|
-
directive:
|
|
221
|
+
directive: USE_CACHE_DIRECTIVE_RE,
|
|
210
222
|
runtime: (
|
|
211
223
|
value: string,
|
|
212
224
|
name: string,
|
|
@@ -224,9 +236,6 @@ function transformFunctionLevelUseCache(
|
|
|
224
236
|
|
|
225
237
|
if (names.length === 0) return;
|
|
226
238
|
|
|
227
|
-
// Use a top-level import instead of await import() — the hoisted wrapper
|
|
228
|
-
// may be placed in a non-async context (e.g., inside a synchronous
|
|
229
|
-
// urls() callback) where await is not allowed.
|
|
230
239
|
output.prepend(
|
|
231
240
|
`import { registerCachedFunction as __rango_registerCachedFunction } from ${JSON.stringify(CACHE_RUNTIME_IMPORT)};\n`,
|
|
232
241
|
);
|
|
@@ -241,9 +250,6 @@ function transformFunctionLevelUseCache(
|
|
|
241
250
|
}
|
|
242
251
|
}
|
|
243
252
|
|
|
244
|
-
/**
|
|
245
|
-
* Find the file-level "use cache" directive AST node for removal.
|
|
246
|
-
*/
|
|
247
253
|
function findFileLevelDirective(
|
|
248
254
|
ast: any,
|
|
249
255
|
): { start: number; end: number } | null {
|
|
@@ -260,23 +266,8 @@ function findFileLevelDirective(
|
|
|
260
266
|
return null;
|
|
261
267
|
}
|
|
262
268
|
|
|
263
|
-
/**
|
|
264
|
-
* The valid directive regex (must stay in sync with transformFunctionLevelUseCache).
|
|
265
|
-
*/
|
|
266
|
-
const VALID_DIRECTIVE_RE = /^use cache(:\s*[\w-]+)?$/;
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* Regex for near-miss: starts with "use cache:" but has invalid tokens.
|
|
270
|
-
*/
|
|
271
269
|
const NEAR_MISS_RE = /^use cache:\s*.+$/;
|
|
272
270
|
|
|
273
|
-
/**
|
|
274
|
-
* Walk the AST looking for string literals that look like malformed
|
|
275
|
-
* "use cache" directives and emit a Vite warning for each.
|
|
276
|
-
*
|
|
277
|
-
* This catches cases like `"use cache: bad.name"` or `"use cache: "`
|
|
278
|
-
* that the transform regex silently ignores.
|
|
279
|
-
*/
|
|
280
271
|
function warnOnNearMissDirectives(
|
|
281
272
|
ast: any,
|
|
282
273
|
fileId: string,
|
|
@@ -294,7 +285,7 @@ function warnOnNearMissDirectives(
|
|
|
294
285
|
if (
|
|
295
286
|
value.startsWith("use cache") &&
|
|
296
287
|
NEAR_MISS_RE.test(value) &&
|
|
297
|
-
!
|
|
288
|
+
!USE_CACHE_DIRECTIVE_RE.test(value)
|
|
298
289
|
) {
|
|
299
290
|
const profilePart = value.slice("use cache:".length).trim();
|
|
300
291
|
warn(
|
|
@@ -304,7 +295,6 @@ function warnOnNearMissDirectives(
|
|
|
304
295
|
}
|
|
305
296
|
}
|
|
306
297
|
|
|
307
|
-
// Walk into function bodies where directives appear
|
|
308
298
|
for (const key of Object.keys(node)) {
|
|
309
299
|
const child = node[key];
|
|
310
300
|
if (Array.isArray(child)) {
|
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
import type { Plugin } from "vite";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import * as Vite from "vite";
|
|
4
|
+
import { resolveRscEntryFromConfig } from "../utils/shared-utils.js";
|
|
5
|
+
import { RSC_ENTRY_BOOTSTRAP_IMPORTS } from "./virtual-entries.js";
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
|
-
* Plugin that auto-injects VERSION and
|
|
7
|
-
* If a custom entry.rsc file uses createRSCHandler but
|
|
8
|
-
* this transform adds the import and property
|
|
9
|
-
*
|
|
8
|
+
* Plugin that auto-injects VERSION, routes-manifest, and loader-manifest into
|
|
9
|
+
* custom entry.rsc files. If a custom entry.rsc file uses createRSCHandler but
|
|
10
|
+
* doesn't pass version, this transform adds the import and property
|
|
11
|
+
* automatically. It also ensures the routes-manifest and loader-manifest
|
|
12
|
+
* virtual modules are always imported.
|
|
13
|
+
*
|
|
14
|
+
* The loader-manifest import is what makes fetchable loaders resolvable on a
|
|
15
|
+
* custom worker entry. The virtual RSC entry (getVirtualEntryRSC) imports the
|
|
16
|
+
* loader manifest itself, but a hand-written entry (e.g. a Cloudflare
|
|
17
|
+
* worker.rsc.tsx) does not — so without this injection, setLoaderImports() is
|
|
18
|
+
* never bundled, lazyLoaderImports stays null at runtime, and a fetchable
|
|
19
|
+
* loader that is never imported by the server graph (not registered via
|
|
20
|
+
* loader(), reachable only through a client component) cannot be found by the
|
|
21
|
+
* _rsc_loader endpoint in production. Dev still works because it resolves
|
|
22
|
+
* loaders by parsing their id into a file path; only production relied on the
|
|
23
|
+
* manifest, hence the production-only failure this fixes.
|
|
10
24
|
* @internal
|
|
11
25
|
*/
|
|
12
26
|
export function createVersionInjectorPlugin(
|
|
@@ -20,18 +34,7 @@ export function createVersionInjectorPlugin(
|
|
|
20
34
|
|
|
21
35
|
configResolved(config) {
|
|
22
36
|
let entryPath = rscEntryPath;
|
|
23
|
-
|
|
24
|
-
// The @cloudflare/vite-plugin reads wrangler config (toml/json/jsonc)
|
|
25
|
-
// and sets optimizeDeps.entries on the RSC environment.
|
|
26
|
-
if (!entryPath) {
|
|
27
|
-
const rscEnvConfig = (config.environments as any)?.["rsc"];
|
|
28
|
-
const entries = rscEnvConfig?.optimizeDeps?.entries;
|
|
29
|
-
if (typeof entries === "string") {
|
|
30
|
-
entryPath = entries;
|
|
31
|
-
} else if (Array.isArray(entries) && entries.length > 0) {
|
|
32
|
-
entryPath = entries[0];
|
|
33
|
-
}
|
|
34
|
-
}
|
|
37
|
+
if (!entryPath) entryPath = resolveRscEntryFromConfig(config);
|
|
35
38
|
if (entryPath) {
|
|
36
39
|
resolvedEntryPath = resolve(config.root, entryPath);
|
|
37
40
|
}
|
|
@@ -39,7 +42,6 @@ export function createVersionInjectorPlugin(
|
|
|
39
42
|
|
|
40
43
|
transform(code, id) {
|
|
41
44
|
if (!resolvedEntryPath) return null;
|
|
42
|
-
// Only transform the RSC entry file
|
|
43
45
|
const normalizedId = Vite.normalizePath(id);
|
|
44
46
|
const normalizedEntry = Vite.normalizePath(resolvedEntryPath);
|
|
45
47
|
|
|
@@ -47,16 +49,13 @@ export function createVersionInjectorPlugin(
|
|
|
47
49
|
return null;
|
|
48
50
|
}
|
|
49
51
|
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
const prepend: string[] =
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (!code.includes("virtual:rsc-router/routes-manifest")) {
|
|
56
|
-
prepend.push(`import "virtual:rsc-router/routes-manifest";`);
|
|
57
|
-
}
|
|
52
|
+
// Same startup bootstrap imports the generated virtual RSC entry uses,
|
|
53
|
+
// from the single shared list so the two paths cannot drift.
|
|
54
|
+
const prepend: string[] = RSC_ENTRY_BOOTSTRAP_IMPORTS.map(
|
|
55
|
+
(id) => `import "${id}";`,
|
|
56
|
+
);
|
|
58
57
|
|
|
59
|
-
|
|
58
|
+
let newCode = code;
|
|
60
59
|
const needsVersion =
|
|
61
60
|
code.includes("createRSCHandler") &&
|
|
62
61
|
!code.includes("@rangojs/router:version") &&
|
|
@@ -70,9 +69,21 @@ export function createVersionInjectorPlugin(
|
|
|
70
69
|
);
|
|
71
70
|
}
|
|
72
71
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
const lines = newCode.split("\n");
|
|
73
|
+
let insertAt = 0;
|
|
74
|
+
while (insertAt < lines.length) {
|
|
75
|
+
const trimmed = lines[insertAt]!.trim();
|
|
76
|
+
if (trimmed === "" || /^\/\/\/\s*<reference\b/.test(trimmed)) {
|
|
77
|
+
insertAt++;
|
|
78
|
+
} else {
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
newCode = [
|
|
83
|
+
...lines.slice(0, insertAt),
|
|
84
|
+
...prepend,
|
|
85
|
+
...lines.slice(insertAt),
|
|
86
|
+
].join("\n");
|
|
76
87
|
|
|
77
88
|
return {
|
|
78
89
|
code: newCode,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { parseAst, type Plugin } from "vite";
|
|
2
2
|
import { VIRTUAL_IDS, getVirtualVersionContent } from "./virtual-entries.js";
|
|
3
|
+
import { hasUseClientDirective } from "../utils/directive-prologue.js";
|
|
3
4
|
|
|
4
5
|
interface ClientModuleSignature {
|
|
5
6
|
key: string;
|
|
@@ -16,30 +17,17 @@ function normalizeModuleId(id: string): string {
|
|
|
16
17
|
function getClientModuleSignature(
|
|
17
18
|
source: string,
|
|
18
19
|
): ClientModuleSignature | undefined {
|
|
20
|
+
// Same leading-directive sniff the rango HMR plugin uses (shared helper, so the
|
|
21
|
+
// two agree on what counts as a client module). A parse failure yields false.
|
|
22
|
+
if (!hasUseClientDirective(source)) return undefined;
|
|
23
|
+
|
|
19
24
|
let program: any;
|
|
20
25
|
try {
|
|
21
|
-
program = parseAst(source, {
|
|
26
|
+
program = parseAst(source, { lang: "tsx" });
|
|
22
27
|
} catch {
|
|
23
28
|
return undefined;
|
|
24
29
|
}
|
|
25
30
|
|
|
26
|
-
let isUseClient = false;
|
|
27
|
-
for (const node of program.body ?? []) {
|
|
28
|
-
if (
|
|
29
|
-
node?.type === "ExpressionStatement" &&
|
|
30
|
-
node.expression?.type === "Literal" &&
|
|
31
|
-
typeof node.expression.value === "string"
|
|
32
|
-
) {
|
|
33
|
-
if (node.expression.value === "use client") {
|
|
34
|
-
isUseClient = true;
|
|
35
|
-
}
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
break;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (!isUseClient) return undefined;
|
|
42
|
-
|
|
43
31
|
const exports = new Set<string>();
|
|
44
32
|
let hasDefault = false;
|
|
45
33
|
let hasExportAll = false;
|
|
@@ -133,14 +121,13 @@ export function createVersionPlugin(): Plugin {
|
|
|
133
121
|
let currentVersion = buildVersion;
|
|
134
122
|
let isDev = false;
|
|
135
123
|
let server: any = null;
|
|
124
|
+
let resolvedCacheDir: string | undefined;
|
|
136
125
|
const clientModuleSignatures = new Map<string, ClientModuleSignature>();
|
|
137
126
|
|
|
138
127
|
let versionCounter = 0;
|
|
139
128
|
const bumpVersion = (reason: string) => {
|
|
140
|
-
// Use timestamp + counter to guarantee uniqueness even when multiple
|
|
141
|
-
// bumps happen within the same millisecond (e.g. cascading HMR events).
|
|
142
129
|
currentVersion = Date.now().toString(16) + String(++versionCounter);
|
|
143
|
-
console.log(`[
|
|
130
|
+
console.log(`[rango] ${reason}, version updated: ${currentVersion}`);
|
|
144
131
|
|
|
145
132
|
const rscEnv = server?.environments?.rsc;
|
|
146
133
|
const versionMod = rscEnv?.moduleGraph?.getModuleById(
|
|
@@ -157,6 +144,9 @@ export function createVersionPlugin(): Plugin {
|
|
|
157
144
|
|
|
158
145
|
configResolved(config) {
|
|
159
146
|
isDev = config.command === "serve";
|
|
147
|
+
resolvedCacheDir = config.cacheDir
|
|
148
|
+
? String(config.cacheDir).replace(/\\/g, "/")
|
|
149
|
+
: undefined;
|
|
160
150
|
},
|
|
161
151
|
|
|
162
152
|
configureServer(devServer) {
|
|
@@ -203,19 +193,15 @@ export function createVersionPlugin(): Plugin {
|
|
|
203
193
|
return null;
|
|
204
194
|
},
|
|
205
195
|
|
|
206
|
-
// Track RSC module changes and update version
|
|
207
196
|
async hotUpdate(ctx) {
|
|
208
197
|
if (!isDev) return;
|
|
209
198
|
|
|
210
|
-
// Check if this is an RSC environment update (not client/ssr)
|
|
211
|
-
// RSC modules affect server-rendered content and cached payloads
|
|
212
|
-
// In Vite 6, environment is accessed via `this.environment`
|
|
213
199
|
const isRscModule = this.environment?.name === "rsc";
|
|
214
200
|
|
|
215
201
|
if (!isRscModule) return;
|
|
216
202
|
|
|
217
|
-
|
|
218
|
-
|
|
203
|
+
if (isViteDepCachePath(ctx.file, resolvedCacheDir)) return;
|
|
204
|
+
|
|
219
205
|
if (
|
|
220
206
|
ctx.modules.length === 1 &&
|
|
221
207
|
ctx.modules[0].id === "\0" + VIRTUAL_IDS.version
|
|
@@ -230,9 +216,6 @@ export function createVersionPlugin(): Plugin {
|
|
|
230
216
|
const source = await ctx.read();
|
|
231
217
|
const nextSignature = getClientModuleSignature(source);
|
|
232
218
|
if (nextSignature) {
|
|
233
|
-
// "use client" file — compare export signatures.
|
|
234
|
-
// client-component-hmr may have cleared ctx.modules, so we
|
|
235
|
-
// cannot rely on ctx.modules.length for these files.
|
|
236
219
|
clientModuleSignatures.set(filePath, nextSignature);
|
|
237
220
|
if (
|
|
238
221
|
previousSignature &&
|
|
@@ -243,20 +226,11 @@ export function createVersionPlugin(): Plugin {
|
|
|
243
226
|
} else {
|
|
244
227
|
clientModuleSignatures.delete(filePath);
|
|
245
228
|
if (!previousSignature) {
|
|
246
|
-
// Not and never was "use client" — use module graph check.
|
|
247
|
-
// ctx.modules is reliable for pure server files (only
|
|
248
|
-
// client-component-hmr clears it for "use client" modules).
|
|
249
229
|
if (ctx.modules.length === 0) return;
|
|
250
230
|
}
|
|
251
|
-
// Was "use client" but directive removed — boundary changed,
|
|
252
|
-
// bump below.
|
|
253
231
|
}
|
|
254
|
-
} catch {
|
|
255
|
-
// Fail open: if we can't read or parse the update, invalidate.
|
|
256
|
-
}
|
|
232
|
+
} catch {}
|
|
257
233
|
} else {
|
|
258
|
-
// Non-code file (json, css, etc.) — only bump if it's actually
|
|
259
|
-
// referenced by the RSC module graph.
|
|
260
234
|
if (ctx.modules.length === 0) return;
|
|
261
235
|
}
|
|
262
236
|
|
|
@@ -264,3 +238,26 @@ export function createVersionPlugin(): Plugin {
|
|
|
264
238
|
},
|
|
265
239
|
};
|
|
266
240
|
}
|
|
241
|
+
|
|
242
|
+
export function isViteDepCachePath(
|
|
243
|
+
filePath: string | undefined,
|
|
244
|
+
cacheDir?: string,
|
|
245
|
+
): boolean {
|
|
246
|
+
if (!filePath) return false;
|
|
247
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
248
|
+
|
|
249
|
+
if (cacheDir) {
|
|
250
|
+
const normalizedCacheDir = cacheDir.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
251
|
+
if (
|
|
252
|
+
normalized === normalizedCacheDir ||
|
|
253
|
+
normalized.startsWith(normalizedCacheDir + "/")
|
|
254
|
+
) {
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return (
|
|
260
|
+
/\/node_modules\/\.vite[^/]*\//.test(normalized) ||
|
|
261
|
+
normalized.includes("/.vite-isolated/")
|
|
262
|
+
);
|
|
263
|
+
}
|