@rangojs/router 0.0.0-experimental.b9cb8739 → 0.0.0-experimental.bd6e11bc
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/README.md +196 -43
- package/dist/bin/rango.js +277 -99
- package/dist/testing/vitest.js +48 -0
- package/dist/vite/index.js +2779 -1064
- package/dist/vite/index.js.bak +5448 -0
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +57 -11
- package/skills/breadcrumbs/SKILL.md +3 -1
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +243 -21
- package/skills/caching/SKILL.md +155 -6
- package/skills/composability/SKILL.md +27 -2
- package/skills/document-cache/SKILL.md +78 -55
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +229 -20
- package/skills/host-router/SKILL.md +45 -20
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +46 -4
- package/skills/layout/SKILL.md +28 -7
- package/skills/links/SKILL.md +249 -17
- package/skills/loader/SKILL.md +273 -53
- package/skills/middleware/SKILL.md +49 -12
- package/skills/migrate-nextjs/SKILL.md +562 -0
- package/skills/migrate-react-router/SKILL.md +769 -0
- package/skills/mime-routes/SKILL.md +27 -0
- package/skills/observability/SKILL.md +137 -0
- package/skills/parallel/SKILL.md +197 -6
- package/skills/prerender/SKILL.md +123 -100
- package/skills/rango/SKILL.md +242 -22
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +66 -9
- package/skills/route/SKILL.md +88 -4
- package/skills/router-setup/SKILL.md +90 -5
- package/skills/server-actions/SKILL.md +751 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/testing/SKILL.md +716 -0
- package/skills/typesafety/SKILL.md +329 -27
- package/skills/use-cache/SKILL.md +34 -5
- package/skills/view-transitions/SKILL.md +294 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +117 -0
- package/src/__internal.ts +1 -1
- package/src/browser/action-coordinator.ts +53 -36
- package/src/browser/app-shell.ts +52 -0
- package/src/browser/app-version.ts +14 -0
- package/src/browser/event-controller.ts +91 -70
- package/src/browser/history-state.ts +21 -0
- package/src/browser/index.ts +3 -3
- package/src/browser/navigation-bridge.ts +102 -16
- package/src/browser/navigation-client.ts +164 -59
- package/src/browser/navigation-store.ts +75 -17
- package/src/browser/navigation-transaction.ts +21 -37
- package/src/browser/partial-update.ts +139 -38
- package/src/browser/prefetch/cache.ts +175 -15
- package/src/browser/prefetch/fetch.ts +180 -33
- package/src/browser/prefetch/queue.ts +123 -20
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +53 -13
- package/src/browser/react/Link.tsx +81 -9
- package/src/browser/react/NavigationProvider.tsx +110 -33
- package/src/browser/react/context.ts +7 -2
- package/src/browser/react/filter-segment-order.ts +51 -7
- package/src/browser/react/index.ts +3 -0
- package/src/browser/react/location-state-shared.ts +175 -4
- package/src/browser/react/location-state.ts +39 -13
- package/src/browser/react/use-handle.ts +23 -64
- package/src/browser/react/use-navigation.ts +22 -2
- package/src/browser/react/use-params.ts +20 -8
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +43 -10
- package/src/browser/react/use-segments.ts +11 -8
- package/src/browser/response-adapter.ts +25 -0
- package/src/browser/rsc-router.tsx +191 -74
- package/src/browser/scroll-restoration.ts +41 -14
- package/src/browser/segment-reconciler.ts +36 -9
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +31 -36
- package/src/browser/types.ts +57 -5
- 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 -0
- package/src/build/index.ts +2 -0
- package/src/build/route-trie.ts +52 -25
- package/src/build/route-types/codegen.ts +4 -4
- package/src/build/route-types/include-resolution.ts +9 -2
- package/src/build/route-types/per-module-writer.ts +7 -4
- package/src/build/route-types/router-processing.ts +278 -88
- package/src/build/route-types/scan-filter.ts +9 -2
- package/src/build/route-types/source-scan.ts +118 -0
- package/src/build/runtime-discovery.ts +9 -20
- package/src/cache/cache-runtime.ts +15 -11
- package/src/cache/cache-scope.ts +76 -49
- package/src/cache/cf/cf-cache-store.ts +501 -18
- package/src/cache/cf/index.ts +5 -1
- package/src/cache/document-cache.ts +17 -7
- package/src/cache/index.ts +1 -0
- package/src/cache/taint.ts +55 -0
- package/src/client.rsc.tsx +3 -0
- package/src/client.tsx +94 -238
- package/src/context-var.ts +72 -2
- package/src/debug.ts +2 -2
- package/src/decode-loader-results.ts +36 -0
- package/src/errors.ts +30 -1
- package/src/handle.ts +65 -12
- package/src/host/index.ts +2 -2
- package/src/host/router.ts +129 -57
- package/src/host/types.ts +31 -2
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +140 -20
- package/src/index.rsc.ts +12 -5
- package/src/index.ts +61 -11
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +2 -5
- package/src/loader.ts +3 -10
- package/src/missing-id-error.ts +68 -0
- package/src/outlet-context.ts +1 -1
- package/src/prerender/store.ts +5 -4
- package/src/prerender.ts +141 -80
- package/src/response-utils.ts +37 -0
- package/src/reverse.ts +65 -15
- package/src/route-content-wrapper.tsx +6 -28
- package/src/route-definition/dsl-helpers.ts +435 -260
- package/src/route-definition/helper-factories.ts +29 -139
- package/src/route-definition/helpers-types.ts +110 -34
- package/src/route-definition/index.ts +3 -0
- package/src/route-definition/redirect.ts +11 -3
- package/src/route-definition/resolve-handler-use.ts +155 -0
- package/src/route-definition/use-item-types.ts +32 -0
- package/src/route-map-builder.ts +7 -1
- package/src/route-types.ts +37 -41
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +113 -1
- package/src/router/error-handling.ts +1 -1
- package/src/router/find-match.ts +4 -2
- package/src/router/handler-context.ts +77 -38
- package/src/router/intercept-resolution.ts +15 -22
- package/src/router/lazy-includes.ts +12 -9
- package/src/router/loader-resolution.ts +174 -22
- package/src/router/logging.ts +5 -2
- package/src/router/manifest.ts +31 -16
- package/src/router/match-api.ts +128 -192
- package/src/router/match-handlers.ts +63 -20
- package/src/router/match-middleware/background-revalidation.ts +30 -2
- package/src/router/match-middleware/cache-lookup.ts +136 -106
- package/src/router/match-middleware/cache-store.ts +54 -10
- package/src/router/match-middleware/intercept-resolution.ts +9 -7
- package/src/router/match-middleware/segment-resolution.ts +61 -5
- package/src/router/match-result.ts +125 -10
- package/src/router/metrics.ts +7 -2
- package/src/router/middleware-types.ts +21 -34
- package/src/router/middleware.ts +103 -90
- package/src/router/navigation-snapshot.ts +182 -0
- package/src/router/pattern-matching.ts +101 -17
- package/src/router/prerender-match.ts +110 -10
- package/src/router/preview-match.ts +32 -102
- package/src/router/request-classification.ts +286 -0
- package/src/router/revalidation.ts +58 -2
- package/src/router/route-snapshot.ts +245 -0
- package/src/router/router-context.ts +6 -1
- package/src/router/router-interfaces.ts +77 -28
- package/src/router/router-options.ts +76 -11
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +223 -24
- package/src/router/segment-resolution/helpers.ts +29 -24
- package/src/router/segment-resolution/loader-cache.ts +1 -0
- package/src/router/segment-resolution/revalidation.ts +466 -285
- package/src/router/segment-resolution/view-transition-default.ts +36 -0
- package/src/router/segment-wrappers.ts +2 -0
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/telemetry.ts +99 -0
- package/src/router/trie-matching.ts +18 -13
- package/src/router/types.ts +9 -0
- package/src/router/url-params.ts +49 -0
- package/src/router.ts +91 -23
- package/src/rsc/handler-context.ts +2 -2
- package/src/rsc/handler.ts +440 -381
- package/src/rsc/helpers.ts +91 -43
- package/src/rsc/index.ts +1 -1
- package/src/rsc/loader-fetch.ts +23 -3
- package/src/rsc/manifest-init.ts +5 -1
- package/src/rsc/origin-guard.ts +28 -10
- package/src/rsc/progressive-enhancement.ts +18 -2
- package/src/rsc/response-route-handler.ts +46 -53
- package/src/rsc/rsc-rendering.ts +41 -48
- package/src/rsc/runtime-warnings.ts +9 -10
- package/src/rsc/server-action.ts +25 -37
- package/src/rsc/ssr-setup.ts +18 -2
- package/src/rsc/types.ts +17 -3
- package/src/search-params.ts +4 -4
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +122 -0
- package/src/segment-system.tsx +219 -67
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +277 -61
- package/src/server/cookie-store.ts +28 -4
- package/src/server/handle-store.ts +19 -0
- package/src/server/loader-registry.ts +9 -8
- package/src/server/request-context.ts +204 -60
- package/src/ssr/index.tsx +9 -1
- package/src/static-handler.ts +19 -7
- package/src/testing/cache-status.ts +166 -0
- package/src/testing/collect-handle.ts +63 -0
- package/src/testing/dispatch.ts +440 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +154 -0
- package/src/testing/e2e/index.ts +149 -0
- package/src/testing/e2e/matchers.ts +51 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +306 -0
- package/src/testing/e2e/server.ts +183 -0
- package/src/testing/flight-matchers.ts +104 -0
- package/src/testing/flight-runtime.d.ts +21 -0
- package/src/testing/flight.entry.ts +22 -0
- package/src/testing/flight.ts +182 -0
- package/src/testing/generated-routes.ts +223 -0
- package/src/testing/index.ts +106 -0
- package/src/testing/internal/context.ts +255 -0
- package/src/testing/render-route.tsx +565 -0
- package/src/testing/run-loader.ts +296 -0
- package/src/testing/run-middleware.ts +179 -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 +183 -0
- package/src/types/cache-types.ts +4 -4
- package/src/types/global-namespace.ts +39 -26
- package/src/types/handler-context.ts +194 -72
- package/src/types/index.ts +1 -0
- package/src/types/loader-types.ts +41 -15
- package/src/types/request-scope.ts +126 -0
- package/src/types/route-entry.ts +19 -1
- package/src/types/segments.ts +37 -1
- package/src/urls/include-helper.ts +34 -67
- package/src/urls/index.ts +0 -3
- package/src/urls/path-helper-types.ts +50 -9
- package/src/urls/path-helper.ts +63 -63
- package/src/urls/pattern-types.ts +48 -19
- package/src/urls/response-types.ts +25 -22
- package/src/urls/type-extraction.ts +26 -116
- package/src/urls/urls-function.ts +1 -5
- package/src/use-loader.tsx +487 -44
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +34 -37
- package/src/vite/discovery/discover-routers.ts +105 -51
- 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 +188 -93
- 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 +46 -6
- package/src/vite/discovery/virtual-module-codegen.ts +13 -23
- package/src/vite/index.ts +6 -0
- package/src/vite/plugin-types.ts +111 -72
- package/src/vite/plugins/cjs-to-esm.ts +8 -7
- package/src/vite/plugins/client-ref-dedup.ts +16 -0
- package/src/vite/plugins/client-ref-hashing.ts +28 -5
- 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 +214 -0
- package/src/vite/plugins/expose-action-id.ts +55 -33
- package/src/vite/plugins/expose-id-utils.ts +24 -8
- package/src/vite/plugins/expose-ids/export-analysis.ts +100 -20
- package/src/vite/plugins/expose-ids/handler-transform.ts +12 -35
- package/src/vite/plugins/expose-ids/loader-transform.ts +3 -5
- package/src/vite/plugins/expose-ids/router-transform.ts +20 -3
- package/src/vite/plugins/expose-internal-ids.ts +544 -317
- package/src/vite/plugins/performance-tracks.ts +92 -0
- package/src/vite/plugins/refresh-cmd.ts +88 -26
- package/src/vite/plugins/use-cache-transform.ts +65 -50
- package/src/vite/plugins/version-injector.ts +39 -23
- package/src/vite/plugins/version-plugin.ts +72 -3
- package/src/vite/plugins/virtual-entries.ts +2 -2
- package/src/vite/rango.ts +265 -226
- package/src/vite/router-discovery.ts +920 -137
- package/src/vite/utils/ast-handler-extract.ts +15 -15
- package/src/vite/utils/banner.ts +4 -4
- package/src/vite/utils/bundle-analysis.ts +4 -2
- package/src/vite/utils/client-chunks.ts +190 -0
- package/src/vite/utils/forward-user-plugins.ts +193 -0
- package/src/vite/utils/manifest-utils.ts +21 -5
- package/src/vite/utils/package-resolution.ts +41 -1
- package/src/vite/utils/prerender-utils.ts +38 -5
- package/src/vite/utils/shared-utils.ts +109 -27
- package/src/browser/action-response-classifier.ts +0 -99
package/src/vite/rango.ts
CHANGED
|
@@ -12,27 +12,30 @@ import { VIRTUAL_IDS } from "./plugins/virtual-entries.js";
|
|
|
12
12
|
import {
|
|
13
13
|
getExcludeDeps,
|
|
14
14
|
getPackageAliases,
|
|
15
|
+
getPublishedPackageName,
|
|
16
|
+
getVendorAliases,
|
|
15
17
|
} from "./utils/package-resolution.js";
|
|
16
|
-
import {
|
|
17
|
-
createScanFilter,
|
|
18
|
-
findRouterFiles,
|
|
19
|
-
} from "../build/generate-route-types.js";
|
|
18
|
+
import { findRouterFiles } from "../build/generate-route-types.js";
|
|
20
19
|
import { createVersionPlugin } from "./plugins/version-plugin.js";
|
|
21
20
|
import {
|
|
22
|
-
|
|
21
|
+
sharedRolldownOptions,
|
|
23
22
|
createVirtualEntriesPlugin,
|
|
24
23
|
onwarn,
|
|
25
24
|
getManualChunks,
|
|
26
25
|
} from "./utils/shared-utils.js";
|
|
27
|
-
import
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
} from "./plugin-types.js";
|
|
26
|
+
import {
|
|
27
|
+
resolveClientChunks,
|
|
28
|
+
type ClientChunkContext,
|
|
29
|
+
} from "./utils/client-chunks.js";
|
|
30
|
+
import type { RangoOptions } from "./plugin-types.js";
|
|
32
31
|
import { printBanner, rangoVersion } from "./utils/banner.js";
|
|
33
32
|
import { createVersionInjectorPlugin } from "./plugins/version-injector.js";
|
|
34
33
|
import { createCjsToEsmPlugin } from "./plugins/cjs-to-esm.js";
|
|
35
34
|
import { createRouterDiscoveryPlugin } from "./router-discovery.js";
|
|
35
|
+
import { performanceTracksPlugin } from "./plugins/performance-tracks.js";
|
|
36
|
+
import { createRangoDebugger, NS } from "./debug.js";
|
|
37
|
+
|
|
38
|
+
const debugConfig = createRangoDebugger(NS.config);
|
|
36
39
|
|
|
37
40
|
/**
|
|
38
41
|
* Vite plugin for @rangojs/router.
|
|
@@ -43,7 +46,7 @@ import { createRouterDiscoveryPlugin } from "./router-discovery.js";
|
|
|
43
46
|
* @example Node.js (default)
|
|
44
47
|
* ```ts
|
|
45
48
|
* export default defineConfig({
|
|
46
|
-
* plugins: [react(), rango(
|
|
49
|
+
* plugins: [react(), rango()],
|
|
47
50
|
* });
|
|
48
51
|
* ```
|
|
49
52
|
*
|
|
@@ -59,18 +62,57 @@ import { createRouterDiscoveryPlugin } from "./router-discovery.js";
|
|
|
59
62
|
* ```
|
|
60
63
|
*/
|
|
61
64
|
export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
65
|
+
const rangoStart = performance.now();
|
|
62
66
|
const resolvedOptions: RangoOptions = options ?? { preset: "node" };
|
|
63
67
|
const preset = resolvedOptions.preset ?? "node";
|
|
64
68
|
const showBanner = resolvedOptions.banner ?? true;
|
|
69
|
+
// Client-chunking strategy (per-route/per-feature splitting of the browser
|
|
70
|
+
// bundle). Defaults to the built-in directory strategy (`true`) pre-1.0; pass
|
|
71
|
+
// `clientChunks: false` to opt out. Resolved once and forwarded to
|
|
72
|
+
// @vitejs/plugin-rsc in both presets. The built-in strategy only splits where it
|
|
73
|
+
// recognizes a route structure, so this default is a no-op for flat / host-split
|
|
74
|
+
// apps and never duplicates the shared runtime.
|
|
75
|
+
const clientChunksOption = resolvedOptions.clientChunks ?? true;
|
|
76
|
+
// Shared context the built-in strategy reads at build time: the production
|
|
77
|
+
// hashes of registered error/notFound fallback modules (-> app-fallback).
|
|
78
|
+
// Populated by the discovery plugin in buildStart, before the client build
|
|
79
|
+
// invokes the strategy. Only wired when the built-in strategy is active; a
|
|
80
|
+
// custom function owns its own grouping.
|
|
81
|
+
const useBuiltInClientChunks = clientChunksOption === true;
|
|
82
|
+
const clientChunkCtx: ClientChunkContext | undefined = useBuiltInClientChunks
|
|
83
|
+
? { fallbackRefs: new Set<string>() }
|
|
84
|
+
: undefined;
|
|
85
|
+
const clientChunks = resolveClientChunks(clientChunksOption, clientChunkCtx);
|
|
86
|
+
debugConfig?.("rango(%s) setup start", preset);
|
|
65
87
|
|
|
66
88
|
const plugins: PluginOption[] = [];
|
|
67
89
|
|
|
68
|
-
// Get package resolution info (workspace vs npm install)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
//
|
|
73
|
-
|
|
90
|
+
// Get package resolution info (workspace vs npm install).
|
|
91
|
+
// Vendor aliases redirect the bare plugin-rsc vendor specs (which plugin-rsc
|
|
92
|
+
// itself injects into optimizeDeps.include) to absolute paths resolved from
|
|
93
|
+
// this package — so strict-pnpm consumers don't hit "Failed to resolve
|
|
94
|
+
// dependency" warnings when those deps aren't hoisted to their app root.
|
|
95
|
+
const rangoAliases = { ...getPackageAliases(), ...getVendorAliases() };
|
|
96
|
+
const excludeDeps = [
|
|
97
|
+
...getExcludeDeps(),
|
|
98
|
+
// plugin-rsc itself injects these into the client env's
|
|
99
|
+
// optimizeDeps.include, which overrides exclude for the dep's own
|
|
100
|
+
// pre-bundle entry. What exclude still controls is how *other*
|
|
101
|
+
// pre-bundled deps treat imports of these specs (external vs inlined)
|
|
102
|
+
// via esbuildCjsExternalPlugin. The cjs-to-esm transform in
|
|
103
|
+
// plugins/cjs-to-esm.ts is the fallback for strict-pnpm consumers,
|
|
104
|
+
// where client.browser's bare include fails to resolve and Vite ends up
|
|
105
|
+
// serving the raw CJS file at dev-serve time.
|
|
106
|
+
"@vitejs/plugin-rsc/browser",
|
|
107
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.browser",
|
|
108
|
+
];
|
|
109
|
+
|
|
110
|
+
// Vite supports a nested `A > B` syntax in optimizeDeps.include that resolves
|
|
111
|
+
// B from A's location. We anchor transitive deps (rsc-html-stream,
|
|
112
|
+
// @vitejs/plugin-rsc/vendor/*) to @rangojs/router so pnpm consumers — where
|
|
113
|
+
// these aren't visible at the app root — can still pre-bundle them.
|
|
114
|
+
const pkg = getPublishedPackageName();
|
|
115
|
+
const nested = (spec: string) => `${pkg} > ${spec}`;
|
|
74
116
|
|
|
75
117
|
// Mutable ref for router path (node preset only).
|
|
76
118
|
// Set immediately when user-specified, or populated by the auto-discover
|
|
@@ -106,10 +148,18 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
106
148
|
// This ensures the same Context instance is used by both browser entry and RSC proxy modules
|
|
107
149
|
optimizeDeps: {
|
|
108
150
|
exclude: excludeDeps,
|
|
109
|
-
|
|
151
|
+
rolldownOptions: sharedRolldownOptions,
|
|
110
152
|
},
|
|
111
153
|
resolve: {
|
|
112
154
|
alias: rangoAliases,
|
|
155
|
+
// Force a single React/React-DOM copy across all three RSC
|
|
156
|
+
// environments. RSC requires exactly one react/react-dom instance
|
|
157
|
+
// per environment runtime; consumer install topologies (pnpm
|
|
158
|
+
// strict layout, experimental React pins, third-party "use client"
|
|
159
|
+
// packages) can otherwise resolve duplicate copies, causing
|
|
160
|
+
// "Invalid hook call" / lost context. Child environments inherit
|
|
161
|
+
// this root dedupe, and Vite merges it with any consumer dedupe.
|
|
162
|
+
dedupe: ["react", "react-dom"],
|
|
113
163
|
},
|
|
114
164
|
build: {
|
|
115
165
|
rollupOptions: { onwarn },
|
|
@@ -118,6 +168,14 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
118
168
|
client: {
|
|
119
169
|
build: {
|
|
120
170
|
rollupOptions: {
|
|
171
|
+
// FILE_NAME_CONFLICT (and any other client-build warning) is
|
|
172
|
+
// emitted by the CLIENT environment build, which consults THIS
|
|
173
|
+
// env's onwarn -- Vite 8's environment builds do NOT propagate
|
|
174
|
+
// the top-level build.rollupOptions.onwarn into the client env.
|
|
175
|
+
// Wire it here so the suppression runs where the conflicts
|
|
176
|
+
// originate (the top-level handler is invoked 0x for these; the
|
|
177
|
+
// client-env handler is invoked for all of them).
|
|
178
|
+
onwarn,
|
|
121
179
|
output: {
|
|
122
180
|
manualChunks: getManualChunks,
|
|
123
181
|
},
|
|
@@ -126,9 +184,9 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
126
184
|
// Pre-bundle rsc-html-stream to prevent discovery during first request
|
|
127
185
|
// Exclude rsc-router modules to ensure same Context instance
|
|
128
186
|
optimizeDeps: {
|
|
129
|
-
include: ["rsc-html-stream/client"],
|
|
187
|
+
include: [nested("rsc-html-stream/client")],
|
|
130
188
|
exclude: excludeDeps,
|
|
131
|
-
|
|
189
|
+
rolldownOptions: sharedRolldownOptions,
|
|
132
190
|
},
|
|
133
191
|
},
|
|
134
192
|
ssr: {
|
|
@@ -136,10 +194,6 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
136
194
|
build: {
|
|
137
195
|
outDir: "./dist/rsc/ssr",
|
|
138
196
|
},
|
|
139
|
-
resolve: {
|
|
140
|
-
// Ensure single React instance in SSR child environment
|
|
141
|
-
dedupe: ["react", "react-dom"],
|
|
142
|
-
},
|
|
143
197
|
// Pre-bundle SSR entry and React for proper module linking with childEnvironments
|
|
144
198
|
// All deps must be listed to avoid late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
|
|
145
199
|
optimizeDeps: {
|
|
@@ -151,11 +205,13 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
151
205
|
"react-dom/static.edge",
|
|
152
206
|
"react/jsx-runtime",
|
|
153
207
|
"react/jsx-dev-runtime",
|
|
154
|
-
"rsc-html-stream/server",
|
|
155
|
-
|
|
208
|
+
nested("rsc-html-stream/server"),
|
|
209
|
+
nested(
|
|
210
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
|
|
211
|
+
),
|
|
156
212
|
],
|
|
157
213
|
exclude: excludeDeps,
|
|
158
|
-
|
|
214
|
+
rolldownOptions: sharedRolldownOptions,
|
|
159
215
|
},
|
|
160
216
|
},
|
|
161
217
|
rsc: {
|
|
@@ -167,10 +223,12 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
167
223
|
"react",
|
|
168
224
|
"react/jsx-runtime",
|
|
169
225
|
"react/jsx-dev-runtime",
|
|
170
|
-
|
|
226
|
+
nested(
|
|
227
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge",
|
|
228
|
+
),
|
|
171
229
|
],
|
|
172
230
|
exclude: excludeDeps,
|
|
173
|
-
|
|
231
|
+
rolldownOptions: sharedRolldownOptions,
|
|
174
232
|
},
|
|
175
233
|
},
|
|
176
234
|
},
|
|
@@ -192,6 +250,9 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
192
250
|
|
|
193
251
|
plugins.push(createVirtualEntriesPlugin(finalEntries));
|
|
194
252
|
|
|
253
|
+
// Dev-only: RSDW client patch for React Performance Tracks
|
|
254
|
+
plugins.push(performanceTracksPlugin());
|
|
255
|
+
|
|
195
256
|
// Add RSC plugin with cloudflare-specific options
|
|
196
257
|
// Note: loadModuleDevProxy should NOT be used with childEnvironments
|
|
197
258
|
// since SSR runs in workerd alongside RSC
|
|
@@ -199,6 +260,7 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
199
260
|
rsc({
|
|
200
261
|
entries: finalEntries,
|
|
201
262
|
serverHandler: false,
|
|
263
|
+
clientChunks,
|
|
202
264
|
}) as PluginOption,
|
|
203
265
|
);
|
|
204
266
|
|
|
@@ -207,198 +269,172 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
207
269
|
// packages that are also imported directly by client components.
|
|
208
270
|
plugins.push(clientRefDedup());
|
|
209
271
|
} else {
|
|
210
|
-
//
|
|
211
|
-
|
|
272
|
+
// Auto-discover router using Vite's resolved root (not process.cwd())
|
|
273
|
+
plugins.push({
|
|
274
|
+
name: "@rangojs/router:auto-discover",
|
|
275
|
+
config(userConfig) {
|
|
276
|
+
if (routerRef.path) return;
|
|
277
|
+
const root = userConfig.root
|
|
278
|
+
? resolve(process.cwd(), userConfig.root)
|
|
279
|
+
: process.cwd();
|
|
280
|
+
const candidates = findRouterFiles(root);
|
|
281
|
+
if (candidates.length === 1) {
|
|
282
|
+
const abs = candidates[0];
|
|
283
|
+
routerRef.path = (
|
|
284
|
+
abs.startsWith(root) ? "./" + abs.slice(root.length + 1) : abs
|
|
285
|
+
).replaceAll("\\", "/");
|
|
286
|
+
} else if (candidates.length > 1) {
|
|
287
|
+
const list = candidates
|
|
288
|
+
.map(
|
|
289
|
+
(f) =>
|
|
290
|
+
" - " + (f.startsWith(root) ? f.slice(root.length + 1) : f),
|
|
291
|
+
)
|
|
292
|
+
.join("\n");
|
|
293
|
+
throw new Error(`[rango] Multiple routers found:\n${list}`);
|
|
294
|
+
}
|
|
295
|
+
// 0 found: routerRef.path stays undefined, warn at startup via discovery plugin
|
|
296
|
+
},
|
|
297
|
+
});
|
|
212
298
|
|
|
213
|
-
|
|
299
|
+
// Always use virtual entries for client, ssr, and rsc
|
|
300
|
+
const finalEntries = {
|
|
301
|
+
client: VIRTUAL_IDS.browser,
|
|
302
|
+
ssr: VIRTUAL_IDS.ssr,
|
|
303
|
+
rsc: VIRTUAL_IDS.rsc,
|
|
304
|
+
};
|
|
214
305
|
|
|
215
|
-
//
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
const userEntries =
|
|
259
|
-
typeof rscOption === "boolean" ? {} : rscOption.entries || {};
|
|
260
|
-
const finalEntries = {
|
|
261
|
-
client: userEntries.client ?? VIRTUAL_IDS.browser,
|
|
262
|
-
ssr: userEntries.ssr ?? VIRTUAL_IDS.ssr,
|
|
263
|
-
rsc: userEntries.rsc ?? VIRTUAL_IDS.rsc,
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
// Track RSC entry for version injection (only if custom entry provided)
|
|
267
|
-
rscEntryPath = userEntries.rsc ?? null;
|
|
268
|
-
|
|
269
|
-
// Create wrapper plugin that checks for duplicates
|
|
270
|
-
let hasWarnedDuplicate = false;
|
|
271
|
-
|
|
272
|
-
plugins.push({
|
|
273
|
-
name: "@rangojs/router:rsc-integration",
|
|
274
|
-
enforce: "pre",
|
|
275
|
-
|
|
276
|
-
config() {
|
|
277
|
-
// Configure environments for RSC
|
|
278
|
-
// When using virtual entries, we need to explicitly configure optimizeDeps
|
|
279
|
-
// so Vite pre-bundles React before processing the virtual modules.
|
|
280
|
-
// Without this, the dep optimizer may run multiple times with different hashes,
|
|
281
|
-
// causing React instance mismatches.
|
|
282
|
-
const useVirtualClient = finalEntries.client === VIRTUAL_IDS.browser;
|
|
283
|
-
const useVirtualSSR = finalEntries.ssr === VIRTUAL_IDS.ssr;
|
|
284
|
-
const useVirtualRSC = finalEntries.rsc === VIRTUAL_IDS.rsc;
|
|
285
|
-
|
|
286
|
-
return {
|
|
287
|
-
// Exclude rsc-router modules from optimization to prevent module duplication
|
|
288
|
-
// This ensures the same Context instance is used by both browser entry and RSC proxy modules
|
|
289
|
-
optimizeDeps: {
|
|
290
|
-
exclude: excludeDeps,
|
|
291
|
-
esbuildOptions: sharedEsbuildOptions,
|
|
292
|
-
},
|
|
293
|
-
build: {
|
|
294
|
-
rollupOptions: { onwarn },
|
|
295
|
-
},
|
|
296
|
-
resolve: {
|
|
297
|
-
alias: rangoAliases,
|
|
298
|
-
},
|
|
299
|
-
environments: {
|
|
300
|
-
client: {
|
|
301
|
-
build: {
|
|
302
|
-
rollupOptions: {
|
|
303
|
-
output: {
|
|
304
|
-
manualChunks: getManualChunks,
|
|
305
|
-
},
|
|
306
|
+
// Dynamically import @vitejs/plugin-rsc
|
|
307
|
+
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
308
|
+
|
|
309
|
+
let hasWarnedDuplicate = false;
|
|
310
|
+
|
|
311
|
+
plugins.push({
|
|
312
|
+
name: "@rangojs/router:rsc-integration",
|
|
313
|
+
enforce: "pre",
|
|
314
|
+
|
|
315
|
+
config() {
|
|
316
|
+
return {
|
|
317
|
+
optimizeDeps: {
|
|
318
|
+
exclude: excludeDeps,
|
|
319
|
+
rolldownOptions: sharedRolldownOptions,
|
|
320
|
+
},
|
|
321
|
+
build: {
|
|
322
|
+
rollupOptions: { onwarn },
|
|
323
|
+
},
|
|
324
|
+
resolve: {
|
|
325
|
+
alias: rangoAliases,
|
|
326
|
+
// Force a single React/React-DOM copy across all three RSC
|
|
327
|
+
// environments. RSC requires exactly one react/react-dom instance
|
|
328
|
+
// per environment runtime; consumer install topologies (pnpm
|
|
329
|
+
// strict layout, experimental React pins, third-party "use client"
|
|
330
|
+
// packages) can otherwise resolve duplicate copies, causing
|
|
331
|
+
// "Invalid hook call" / lost context. Child environments inherit
|
|
332
|
+
// this root dedupe, and Vite merges it with any consumer dedupe.
|
|
333
|
+
dedupe: ["react", "react-dom"],
|
|
334
|
+
},
|
|
335
|
+
environments: {
|
|
336
|
+
client: {
|
|
337
|
+
build: {
|
|
338
|
+
rollupOptions: {
|
|
339
|
+
// FILE_NAME_CONFLICT (and any other client-build warning) is
|
|
340
|
+
// emitted by the CLIENT environment build, which consults THIS
|
|
341
|
+
// env's onwarn -- Vite 8's environment builds do NOT propagate
|
|
342
|
+
// the top-level build.rollupOptions.onwarn into the client env.
|
|
343
|
+
// Wire it here so the suppression runs where the conflicts
|
|
344
|
+
// originate (the top-level handler is invoked 0x for these; the
|
|
345
|
+
// client-env handler is invoked for all of them).
|
|
346
|
+
onwarn,
|
|
347
|
+
output: {
|
|
348
|
+
manualChunks: getManualChunks,
|
|
306
349
|
},
|
|
307
350
|
},
|
|
308
|
-
// Always exclude rsc-router modules, conditionally add virtual entry
|
|
309
|
-
optimizeDeps: {
|
|
310
|
-
// Pre-bundle React and rsc-html-stream to prevent late discovery
|
|
311
|
-
// triggering ERR_OUTDATED_OPTIMIZED_DEP on cold starts
|
|
312
|
-
include: [
|
|
313
|
-
"react",
|
|
314
|
-
"react-dom",
|
|
315
|
-
"react/jsx-runtime",
|
|
316
|
-
"react/jsx-dev-runtime",
|
|
317
|
-
"rsc-html-stream/client",
|
|
318
|
-
],
|
|
319
|
-
exclude: excludeDeps,
|
|
320
|
-
esbuildOptions: sharedEsbuildOptions,
|
|
321
|
-
...(useVirtualClient && {
|
|
322
|
-
// Tell Vite to scan the virtual entry for dependencies
|
|
323
|
-
entries: [VIRTUAL_IDS.browser],
|
|
324
|
-
}),
|
|
325
|
-
},
|
|
326
351
|
},
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
|
|
340
|
-
],
|
|
341
|
-
exclude: excludeDeps,
|
|
342
|
-
esbuildOptions: sharedEsbuildOptions,
|
|
343
|
-
},
|
|
344
|
-
},
|
|
345
|
-
}),
|
|
346
|
-
...(useVirtualRSC && {
|
|
347
|
-
rsc: {
|
|
348
|
-
optimizeDeps: {
|
|
349
|
-
entries: [VIRTUAL_IDS.rsc],
|
|
350
|
-
// Pre-bundle all RSC deps to prevent late discovery triggering ERR_OUTDATED_OPTIMIZED_DEP
|
|
351
|
-
include: [
|
|
352
|
-
"react",
|
|
353
|
-
"react/jsx-runtime",
|
|
354
|
-
"react/jsx-dev-runtime",
|
|
355
|
-
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge",
|
|
356
|
-
],
|
|
357
|
-
esbuildOptions: sharedEsbuildOptions,
|
|
358
|
-
},
|
|
359
|
-
},
|
|
360
|
-
}),
|
|
352
|
+
optimizeDeps: {
|
|
353
|
+
include: [
|
|
354
|
+
"react",
|
|
355
|
+
"react-dom",
|
|
356
|
+
"react/jsx-runtime",
|
|
357
|
+
"react/jsx-dev-runtime",
|
|
358
|
+
nested("rsc-html-stream/client"),
|
|
359
|
+
],
|
|
360
|
+
exclude: excludeDeps,
|
|
361
|
+
rolldownOptions: sharedRolldownOptions,
|
|
362
|
+
entries: [VIRTUAL_IDS.browser],
|
|
363
|
+
},
|
|
361
364
|
},
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
365
|
+
ssr: {
|
|
366
|
+
optimizeDeps: {
|
|
367
|
+
entries: [VIRTUAL_IDS.ssr],
|
|
368
|
+
include: [
|
|
369
|
+
"react",
|
|
370
|
+
"react-dom",
|
|
371
|
+
"react-dom/server.edge",
|
|
372
|
+
"react-dom/static.edge",
|
|
373
|
+
"react/jsx-runtime",
|
|
374
|
+
"react/jsx-dev-runtime",
|
|
375
|
+
nested(
|
|
376
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
|
|
377
|
+
),
|
|
378
|
+
],
|
|
379
|
+
exclude: excludeDeps,
|
|
380
|
+
rolldownOptions: sharedRolldownOptions,
|
|
381
|
+
},
|
|
382
|
+
},
|
|
383
|
+
rsc: {
|
|
384
|
+
optimizeDeps: {
|
|
385
|
+
entries: [VIRTUAL_IDS.rsc],
|
|
386
|
+
include: [
|
|
387
|
+
"react",
|
|
388
|
+
"react/jsx-runtime",
|
|
389
|
+
"react/jsx-dev-runtime",
|
|
390
|
+
nested(
|
|
391
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge",
|
|
392
|
+
),
|
|
393
|
+
],
|
|
394
|
+
rolldownOptions: sharedRolldownOptions,
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
},
|
|
398
|
+
};
|
|
399
|
+
},
|
|
400
|
+
|
|
401
|
+
configResolved(config) {
|
|
402
|
+
if (showBanner) {
|
|
403
|
+
const mode =
|
|
404
|
+
config.command === "serve"
|
|
405
|
+
? process.argv.includes("preview")
|
|
406
|
+
? "preview"
|
|
407
|
+
: "dev"
|
|
408
|
+
: "build";
|
|
409
|
+
printBanner(mode, "node", rangoVersion);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const rscMinimalCount = config.plugins.filter(
|
|
413
|
+
(p) => p.name === "rsc:minimal",
|
|
414
|
+
).length;
|
|
415
|
+
|
|
416
|
+
if (rscMinimalCount > 1 && !hasWarnedDuplicate) {
|
|
417
|
+
hasWarnedDuplicate = true;
|
|
418
|
+
console.warn(
|
|
419
|
+
"[rango] Duplicate @vitejs/plugin-rsc detected. " +
|
|
420
|
+
"Remove rsc() from your vite config — rango() includes it automatically.",
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
},
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
// Add virtual entries plugin (RSC entry generated lazily from routerRef)
|
|
427
|
+
plugins.push(createVirtualEntriesPlugin(finalEntries, routerRef));
|
|
428
|
+
|
|
429
|
+
// Dev-only: RSDW client patch for React Performance Tracks
|
|
430
|
+
plugins.push(performanceTracksPlugin());
|
|
431
|
+
|
|
432
|
+
plugins.push(
|
|
433
|
+
rsc({
|
|
434
|
+
entries: finalEntries,
|
|
435
|
+
clientChunks,
|
|
436
|
+
}) as PluginOption,
|
|
437
|
+
);
|
|
402
438
|
|
|
403
439
|
// Deduplicate client references from third-party packages in dev mode.
|
|
404
440
|
// Prevents module duplication when server components import "use client"
|
|
@@ -479,14 +515,11 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
479
515
|
// Ref for deferred auto-discovery (node preset only, undefined for cloudflare)
|
|
480
516
|
const discoveryRouterRef = preset !== "cloudflare" ? routerRef : undefined;
|
|
481
517
|
|
|
482
|
-
// Version injector: auto-injects VERSION and routes-manifest into
|
|
483
|
-
//
|
|
484
|
-
//
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
rscEntryPath ?? (preset === "cloudflare" ? undefined : null);
|
|
488
|
-
if (injectorEntryPath !== null) {
|
|
489
|
-
plugins.push(createVersionInjectorPlugin(injectorEntryPath));
|
|
518
|
+
// Version injector: auto-injects VERSION and routes-manifest into the RSC entry.
|
|
519
|
+
// For cloudflare preset, the entry is resolved lazily in configResolved.
|
|
520
|
+
// For node preset, the virtual entry already includes these imports.
|
|
521
|
+
if (preset === "cloudflare") {
|
|
522
|
+
plugins.push(createVersionInjectorPlugin(undefined));
|
|
490
523
|
}
|
|
491
524
|
|
|
492
525
|
// Transform CJS vendor files to ESM for browser compatibility
|
|
@@ -500,11 +533,17 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
500
533
|
createRouterDiscoveryPlugin(discoveryEntryPath, {
|
|
501
534
|
routerPathRef: discoveryRouterRef,
|
|
502
535
|
enableBuildPrerender: prerenderEnabled,
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
536
|
+
buildEnv: options?.buildEnv,
|
|
537
|
+
preset,
|
|
538
|
+
clientChunkCtx,
|
|
506
539
|
}),
|
|
507
540
|
);
|
|
508
541
|
|
|
542
|
+
debugConfig?.(
|
|
543
|
+
"rango(%s) setup done: %d plugin(s) (%sms)",
|
|
544
|
+
preset,
|
|
545
|
+
plugins.length,
|
|
546
|
+
(performance.now() - rangoStart).toFixed(1),
|
|
547
|
+
);
|
|
509
548
|
return plugins;
|
|
510
549
|
}
|