@rangojs/router 0.0.0-experimental.ede38110 → 0.0.0-experimental.f2d1a2f1
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 +50 -20
- package/dist/vite/index.js +353 -49
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +5 -3
- package/skills/breadcrumbs/SKILL.md +3 -1
- package/skills/hooks/SKILL.md +28 -20
- package/skills/links/SKILL.md +88 -16
- package/skills/loader/SKILL.md +35 -2
- package/skills/migrate-react-router/SKILL.md +1 -0
- package/skills/response-routes/SKILL.md +8 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/typesafety/SKILL.md +3 -1
- package/src/browser/app-shell.ts +52 -0
- package/src/browser/navigation-bridge.ts +51 -2
- package/src/browser/navigation-client.ts +33 -10
- package/src/browser/navigation-store.ts +25 -1
- package/src/browser/partial-update.ts +20 -1
- package/src/browser/prefetch/cache.ts +124 -26
- package/src/browser/prefetch/fetch.ts +114 -38
- package/src/browser/prefetch/queue.ts +36 -5
- package/src/browser/rango-state.ts +53 -13
- package/src/browser/react/Link.tsx +18 -13
- package/src/browser/react/NavigationProvider.tsx +50 -11
- package/src/browser/react/use-navigation.ts +30 -11
- package/src/browser/react/use-params.ts +11 -1
- package/src/browser/react/use-router.ts +8 -1
- package/src/browser/rsc-router.tsx +34 -6
- package/src/browser/types.ts +13 -0
- package/src/cache/cf/cf-cache-store.ts +5 -7
- package/src/index.rsc.ts +3 -0
- package/src/index.ts +3 -0
- package/src/outlet-context.ts +1 -1
- package/src/response-utils.ts +28 -0
- package/src/reverse.ts +3 -2
- package/src/route-definition/dsl-helpers.ts +16 -3
- package/src/route-definition/resolve-handler-use.ts +6 -0
- package/src/router/handler-context.ts +20 -3
- package/src/router/lazy-includes.ts +1 -1
- package/src/router/loader-resolution.ts +3 -0
- package/src/router/match-api.ts +3 -3
- package/src/router/middleware-types.ts +2 -22
- package/src/router/middleware.ts +32 -4
- package/src/router/pattern-matching.ts +60 -9
- package/src/router/trie-matching.ts +10 -4
- package/src/router/url-params.ts +49 -0
- package/src/router.ts +1 -2
- package/src/rsc/handler.ts +8 -4
- package/src/rsc/helpers.ts +69 -41
- package/src/rsc/progressive-enhancement.ts +2 -0
- package/src/rsc/response-route-handler.ts +14 -1
- package/src/rsc/rsc-rendering.ts +7 -0
- package/src/rsc/server-action.ts +2 -0
- package/src/server/request-context.ts +10 -42
- package/src/types/handler-context.ts +2 -34
- package/src/types/loader-types.ts +5 -6
- package/src/types/request-scope.ts +126 -0
- package/src/urls/response-types.ts +2 -10
- package/src/vite/debug.ts +86 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/src/vite/plugins/cloudflare-protocol-stub.ts +214 -0
- package/src/vite/plugins/performance-tracks.ts +4 -6
- package/src/vite/rango.ts +49 -14
- package/src/vite/router-discovery.ts +161 -23
- package/src/vite/utils/banner.ts +1 -1
- package/src/vite/utils/package-resolution.ts +41 -1
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
|
|
3
|
+
const VIRTUAL_PREFIX = "virtual:rango-cloudflare-stub-";
|
|
4
|
+
const NULL_PREFIX = "\0" + VIRTUAL_PREFIX;
|
|
5
|
+
const CF_PREFIX = "cloudflare:";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* `globalThis` key the `cloudflare:workers` stub reads to populate its
|
|
9
|
+
* `env` export. Router discovery sets this to the resolved `buildEnv`
|
|
10
|
+
* proxy (from `wrangler.getPlatformProxy()` when `buildEnv: "auto"` is
|
|
11
|
+
* configured, or a user-supplied object otherwise) before importing the
|
|
12
|
+
* worker entry, and clears it after discovery disposes the proxy. When
|
|
13
|
+
* unset, the stub's `env` falls back to `{}`.
|
|
14
|
+
*
|
|
15
|
+
* Using `globalThis` is the only cross-module bridge that works here:
|
|
16
|
+
* the stub's `load` hook returns source text, not a live closure, but
|
|
17
|
+
* the stub module is evaluated in the same Node process as the
|
|
18
|
+
* discovery plugin — so reading a global at module-evaluation time
|
|
19
|
+
* reaches whatever the plugin assigned there. A symbol key would be
|
|
20
|
+
* cleaner in-process but awkward to name from the stub source.
|
|
21
|
+
*
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export const BUILD_ENV_GLOBAL_KEY = "__rango_build_env__";
|
|
25
|
+
|
|
26
|
+
const SOURCE_EXT_RE = /\.[mc]?[jt]sx?$/;
|
|
27
|
+
|
|
28
|
+
const IMPORT_NODE_TYPES = new Set([
|
|
29
|
+
"ImportDeclaration",
|
|
30
|
+
"ImportExpression",
|
|
31
|
+
"ExportNamedDeclaration",
|
|
32
|
+
"ExportAllDeclaration",
|
|
33
|
+
]);
|
|
34
|
+
|
|
35
|
+
// Keep in sync with `STUBS` in cloudflare-protocol-loader-hook.mjs —
|
|
36
|
+
// both paths (Vite transform and Node loader) need to hand out the same
|
|
37
|
+
// classes. Unknown `cloudflare:*` modules fall back to an empty default
|
|
38
|
+
// export so third-party packages (e.g. the Cloudflare Agents SDK) can
|
|
39
|
+
// pull them into the graph without crashing discovery. Discovery only
|
|
40
|
+
// evaluates module top-level code — no handlers run — so missing named
|
|
41
|
+
// exports only fail if something does `class X extends Missing {}` at
|
|
42
|
+
// module scope, which is rare outside the already-stubbed classes.
|
|
43
|
+
const STUBS: Record<string, string> = {
|
|
44
|
+
"cloudflare:workers": `
|
|
45
|
+
export class DurableObject { constructor(_ctx, _env) {} }
|
|
46
|
+
export class WorkerEntrypoint { constructor(_ctx, _env) {} }
|
|
47
|
+
export class WorkflowEntrypoint { constructor(_ctx, _env) {} }
|
|
48
|
+
export class RpcTarget {}
|
|
49
|
+
export const env = globalThis[${JSON.stringify(BUILD_ENV_GLOBAL_KEY)}] ?? {};
|
|
50
|
+
export default {};
|
|
51
|
+
`,
|
|
52
|
+
"cloudflare:email": `
|
|
53
|
+
export class EmailMessage { constructor(_from, _to, _raw) {} }
|
|
54
|
+
export default {};
|
|
55
|
+
`,
|
|
56
|
+
"cloudflare:sockets": `
|
|
57
|
+
export function connect() { return {}; }
|
|
58
|
+
export default {};
|
|
59
|
+
`,
|
|
60
|
+
"cloudflare:workflows": `
|
|
61
|
+
export class NonRetryableError extends Error {
|
|
62
|
+
constructor(message, name) { super(message); this.name = name ?? "NonRetryableError"; }
|
|
63
|
+
}
|
|
64
|
+
export default {};
|
|
65
|
+
`,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// Policy: unknown `cloudflare:*` specifiers resolve permissively (empty
|
|
69
|
+
// default export) rather than throwing. We prioritize dependency-graph
|
|
70
|
+
// resilience over strict validation of user imports because third-party
|
|
71
|
+
// packages can pull `cloudflare:*` modules we haven't curated, and
|
|
72
|
+
// discovery should not fail just because those modules appear in the graph.
|
|
73
|
+
// Tradeoff: unsupported user-authored `cloudflare:*` imports may fail later
|
|
74
|
+
// with a generic JS/module error instead of a tailored rango-branded hint.
|
|
75
|
+
// The test below pins this behavior so dependency compatibility is not
|
|
76
|
+
// regressed accidentally.
|
|
77
|
+
const FALLBACK_STUB = `export default {};\n`;
|
|
78
|
+
|
|
79
|
+
interface AstNode {
|
|
80
|
+
type: string;
|
|
81
|
+
start?: number;
|
|
82
|
+
end?: number;
|
|
83
|
+
source?: AstNode | null;
|
|
84
|
+
value?: unknown;
|
|
85
|
+
[key: string]: unknown;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Stubs `cloudflare:*` imports for the discovery-time Node Vite server.
|
|
90
|
+
*
|
|
91
|
+
* Discovery only evaluates user module top-level code — it never invokes
|
|
92
|
+
* DurableObject / WorkerEntrypoint / Workflow handlers — so empty base
|
|
93
|
+
* classes are enough for `class X extends DurableObject {}` declarations
|
|
94
|
+
* to load in Node, where `cloudflare:*` is otherwise unresolvable.
|
|
95
|
+
*
|
|
96
|
+
* Interception point: a transform hook parses source with Rollup's
|
|
97
|
+
* plugin-context parser (`this.parse`) and rewrites only real import
|
|
98
|
+
* specifier spans (`import ... from "cloudflare:xxx"`,
|
|
99
|
+
* `import("cloudflare:xxx")`, `export ... from "cloudflare:xxx"`) to a
|
|
100
|
+
* plain virtual module name (`virtual:rango-cloudflare-stub-xxx`).
|
|
101
|
+
* This must be done in transform because Vite's module runner routes
|
|
102
|
+
* URL-scheme specifiers straight to Node's native ESM loader without
|
|
103
|
+
* consulting plugin `resolveId` hooks. Using the AST (instead of a
|
|
104
|
+
* text regex or a permissive lexer) guarantees that strings,
|
|
105
|
+
* comments, and template literals that merely contain import-like
|
|
106
|
+
* text are never mutated — the walker only looks at the four import
|
|
107
|
+
* node types.
|
|
108
|
+
*
|
|
109
|
+
* The transform runs on user source AND on compiled node_modules
|
|
110
|
+
* output: real-world CF packages (e.g. the Cloudflare Agents SDK)
|
|
111
|
+
* ship compiled JS that contains `import ... from "cloudflare:email"`
|
|
112
|
+
* and similar, so excluding node_modules would leave those imports
|
|
113
|
+
* unrewritten. Cost is small because the early exit (`code.includes`)
|
|
114
|
+
* skips files with no cloudflare: mention.
|
|
115
|
+
*
|
|
116
|
+
* The plugin intentionally runs at Vite's default ordering (no
|
|
117
|
+
* `enforce: "pre"`) so TS/JSX has already been compiled to plain JS
|
|
118
|
+
* by the time `this.parse` runs — acorn doesn't understand
|
|
119
|
+
* non-standard syntax.
|
|
120
|
+
*
|
|
121
|
+
* `cloudflare:workers`, `cloudflare:email`, `cloudflare:sockets`, and
|
|
122
|
+
* `cloudflare:workflows` each get curated stubs with the well-known
|
|
123
|
+
* symbols that appear in top-level `extends` positions. Any other
|
|
124
|
+
* `cloudflare:*` specifier falls back to an empty default export —
|
|
125
|
+
* discovery never executes the handlers, so an empty module is safe
|
|
126
|
+
* for anything the graph pulls in transitively.
|
|
127
|
+
*
|
|
128
|
+
* Only registered in the discovery temp server, not the user's runtime
|
|
129
|
+
* config.
|
|
130
|
+
* @internal
|
|
131
|
+
*/
|
|
132
|
+
export function createCloudflareProtocolStubPlugin(): Plugin {
|
|
133
|
+
return {
|
|
134
|
+
name: "@rangojs/router:cloudflare-protocol-stub",
|
|
135
|
+
transform(code, id) {
|
|
136
|
+
const cleanId = id.split("?")[0] ?? id;
|
|
137
|
+
if (!SOURCE_EXT_RE.test(cleanId)) return null;
|
|
138
|
+
if (!code.includes(CF_PREFIX)) return null;
|
|
139
|
+
|
|
140
|
+
let ast: AstNode;
|
|
141
|
+
try {
|
|
142
|
+
ast = this.parse(code) as unknown as AstNode;
|
|
143
|
+
} catch {
|
|
144
|
+
// Malformed source — let a downstream plugin surface the parse error.
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const hits: Array<{ start: number; end: number; value: string }> = [];
|
|
149
|
+
walk(ast, (node) => {
|
|
150
|
+
if (!IMPORT_NODE_TYPES.has(node.type)) return;
|
|
151
|
+
const source = node.source;
|
|
152
|
+
if (!source || source.type !== "Literal") return;
|
|
153
|
+
if (typeof source.value !== "string") return;
|
|
154
|
+
if (!source.value.startsWith(CF_PREFIX)) return;
|
|
155
|
+
if (typeof source.start !== "number" || typeof source.end !== "number")
|
|
156
|
+
return;
|
|
157
|
+
hits.push({
|
|
158
|
+
start: source.start,
|
|
159
|
+
end: source.end,
|
|
160
|
+
value: source.value,
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
if (hits.length === 0) return null;
|
|
165
|
+
|
|
166
|
+
// Rewrite from last to first so earlier offsets stay valid. `start`/
|
|
167
|
+
// `end` span the full literal including quotes, so we re-emit the
|
|
168
|
+
// same quote character around the new specifier.
|
|
169
|
+
hits.sort((a, b) => b.start - a.start);
|
|
170
|
+
let out = code;
|
|
171
|
+
for (const hit of hits) {
|
|
172
|
+
const submodule = hit.value.slice(CF_PREFIX.length);
|
|
173
|
+
const quote = code[hit.start] === "'" ? "'" : '"';
|
|
174
|
+
out =
|
|
175
|
+
out.slice(0, hit.start) +
|
|
176
|
+
quote +
|
|
177
|
+
VIRTUAL_PREFIX +
|
|
178
|
+
submodule +
|
|
179
|
+
quote +
|
|
180
|
+
out.slice(hit.end);
|
|
181
|
+
}
|
|
182
|
+
return { code: out, map: null };
|
|
183
|
+
},
|
|
184
|
+
resolveId(id) {
|
|
185
|
+
if (id.startsWith(VIRTUAL_PREFIX)) {
|
|
186
|
+
return "\0" + id;
|
|
187
|
+
}
|
|
188
|
+
return null;
|
|
189
|
+
},
|
|
190
|
+
load(id) {
|
|
191
|
+
if (!id.startsWith(NULL_PREFIX)) return null;
|
|
192
|
+
const submodule = id.slice(NULL_PREFIX.length);
|
|
193
|
+
const specifier = CF_PREFIX + submodule;
|
|
194
|
+
return STUBS[specifier] ?? FALLBACK_STUB;
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function walk(node: unknown, visit: (n: AstNode) => void): void {
|
|
200
|
+
if (!node || typeof node !== "object") return;
|
|
201
|
+
if (Array.isArray(node)) {
|
|
202
|
+
for (const child of node) walk(child, visit);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
const n = node as AstNode;
|
|
206
|
+
if (typeof n.type !== "string") return;
|
|
207
|
+
visit(n);
|
|
208
|
+
for (const key in n) {
|
|
209
|
+
if (key === "loc" || key === "start" || key === "end" || key === "range") {
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
walk(n[key], visit);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
|
|
15
15
|
import type { Plugin } from "vite";
|
|
16
16
|
import { readFile } from "node:fs/promises";
|
|
17
|
+
import { createRangoDebugger } from "../debug.js";
|
|
18
|
+
|
|
19
|
+
const debug = createRangoDebugger("rango: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*[;,])/;
|
|
@@ -76,12 +79,7 @@ export function performanceTracksPlugin(): Plugin {
|
|
|
76
79
|
if (!id.includes("react-server-dom") || !id.includes("client")) return;
|
|
77
80
|
const patched = patchRsdwClientDebugInfoRecovery(code);
|
|
78
81
|
if (!patched.debugInfoVar) return;
|
|
79
|
-
|
|
80
|
-
console.log(
|
|
81
|
-
"[perf-tracks] patched RSDW client (var:",
|
|
82
|
-
patched.debugInfoVar,
|
|
83
|
-
")",
|
|
84
|
-
);
|
|
82
|
+
debug?.("patched RSDW client (var: %s)", patched.debugInfoVar);
|
|
85
83
|
return patched.code;
|
|
86
84
|
},
|
|
87
85
|
};
|
package/src/vite/rango.ts
CHANGED
|
@@ -12,6 +12,8 @@ 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
18
|
import { findRouterFiles } from "../build/generate-route-types.js";
|
|
17
19
|
import { createVersionPlugin } from "./plugins/version-plugin.js";
|
|
@@ -27,6 +29,9 @@ import { createVersionInjectorPlugin } from "./plugins/version-injector.js";
|
|
|
27
29
|
import { createCjsToEsmPlugin } from "./plugins/cjs-to-esm.js";
|
|
28
30
|
import { createRouterDiscoveryPlugin } from "./router-discovery.js";
|
|
29
31
|
import { performanceTracksPlugin } from "./plugins/performance-tracks.js";
|
|
32
|
+
import { createRangoDebugger } from "./debug.js";
|
|
33
|
+
|
|
34
|
+
const debugConfig = createRangoDebugger("rango:config");
|
|
30
35
|
|
|
31
36
|
/**
|
|
32
37
|
* Vite plugin for @rangojs/router.
|
|
@@ -53,25 +58,41 @@ import { performanceTracksPlugin } from "./plugins/performance-tracks.js";
|
|
|
53
58
|
* ```
|
|
54
59
|
*/
|
|
55
60
|
export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
61
|
+
const rangoStart = performance.now();
|
|
56
62
|
const resolvedOptions: RangoOptions = options ?? { preset: "node" };
|
|
57
63
|
const preset = resolvedOptions.preset ?? "node";
|
|
58
64
|
const showBanner = resolvedOptions.banner ?? true;
|
|
65
|
+
debugConfig?.("rango(%s) setup start", preset);
|
|
59
66
|
|
|
60
67
|
const plugins: PluginOption[] = [];
|
|
61
68
|
|
|
62
|
-
// Get package resolution info (workspace vs npm install)
|
|
63
|
-
|
|
69
|
+
// Get package resolution info (workspace vs npm install).
|
|
70
|
+
// Vendor aliases redirect the bare plugin-rsc vendor specs (which plugin-rsc
|
|
71
|
+
// itself injects into optimizeDeps.include) to absolute paths resolved from
|
|
72
|
+
// this package — so strict-pnpm consumers don't hit "Failed to resolve
|
|
73
|
+
// dependency" warnings when those deps aren't hoisted to their app root.
|
|
74
|
+
const rangoAliases = { ...getPackageAliases(), ...getVendorAliases() };
|
|
64
75
|
const excludeDeps = [
|
|
65
76
|
...getExcludeDeps(),
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
// .
|
|
77
|
+
// plugin-rsc itself injects these into the client env's
|
|
78
|
+
// optimizeDeps.include, which overrides exclude for the dep's own
|
|
79
|
+
// pre-bundle entry. What exclude still controls is how *other*
|
|
80
|
+
// pre-bundled deps treat imports of these specs (external vs inlined)
|
|
81
|
+
// via esbuildCjsExternalPlugin. The cjs-to-esm transform in
|
|
82
|
+
// plugins/cjs-to-esm.ts is the fallback for strict-pnpm consumers,
|
|
83
|
+
// where client.browser's bare include fails to resolve and Vite ends up
|
|
84
|
+
// serving the raw CJS file at dev-serve time.
|
|
69
85
|
"@vitejs/plugin-rsc/browser",
|
|
70
|
-
// Keep the browser RSDW client out of Vite's dep optimizer so our
|
|
71
|
-
// cjs-to-esm transform can patch the real file.
|
|
72
86
|
"@vitejs/plugin-rsc/vendor/react-server-dom/client.browser",
|
|
73
87
|
];
|
|
74
88
|
|
|
89
|
+
// Vite supports a nested `A > B` syntax in optimizeDeps.include that resolves
|
|
90
|
+
// B from A's location. We anchor transitive deps (rsc-html-stream,
|
|
91
|
+
// @vitejs/plugin-rsc/vendor/*) to @rangojs/router so pnpm consumers — where
|
|
92
|
+
// these aren't visible at the app root — can still pre-bundle them.
|
|
93
|
+
const pkg = getPublishedPackageName();
|
|
94
|
+
const nested = (spec: string) => `${pkg} > ${spec}`;
|
|
95
|
+
|
|
75
96
|
// Mutable ref for router path (node preset only).
|
|
76
97
|
// Set immediately when user-specified, or populated by the auto-discover
|
|
77
98
|
// config() hook using Vite's resolved root.
|
|
@@ -126,7 +147,7 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
126
147
|
// Pre-bundle rsc-html-stream to prevent discovery during first request
|
|
127
148
|
// Exclude rsc-router modules to ensure same Context instance
|
|
128
149
|
optimizeDeps: {
|
|
129
|
-
include: ["rsc-html-stream/client"],
|
|
150
|
+
include: [nested("rsc-html-stream/client")],
|
|
130
151
|
exclude: excludeDeps,
|
|
131
152
|
esbuildOptions: sharedEsbuildOptions,
|
|
132
153
|
},
|
|
@@ -151,8 +172,10 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
151
172
|
"react-dom/static.edge",
|
|
152
173
|
"react/jsx-runtime",
|
|
153
174
|
"react/jsx-dev-runtime",
|
|
154
|
-
"rsc-html-stream/server",
|
|
155
|
-
|
|
175
|
+
nested("rsc-html-stream/server"),
|
|
176
|
+
nested(
|
|
177
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
|
|
178
|
+
),
|
|
156
179
|
],
|
|
157
180
|
exclude: excludeDeps,
|
|
158
181
|
esbuildOptions: sharedEsbuildOptions,
|
|
@@ -167,7 +190,9 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
167
190
|
"react",
|
|
168
191
|
"react/jsx-runtime",
|
|
169
192
|
"react/jsx-dev-runtime",
|
|
170
|
-
|
|
193
|
+
nested(
|
|
194
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge",
|
|
195
|
+
),
|
|
171
196
|
],
|
|
172
197
|
exclude: excludeDeps,
|
|
173
198
|
esbuildOptions: sharedEsbuildOptions,
|
|
@@ -280,7 +305,7 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
280
305
|
"react-dom",
|
|
281
306
|
"react/jsx-runtime",
|
|
282
307
|
"react/jsx-dev-runtime",
|
|
283
|
-
"rsc-html-stream/client",
|
|
308
|
+
nested("rsc-html-stream/client"),
|
|
284
309
|
],
|
|
285
310
|
exclude: excludeDeps,
|
|
286
311
|
esbuildOptions: sharedEsbuildOptions,
|
|
@@ -297,7 +322,9 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
297
322
|
"react-dom/static.edge",
|
|
298
323
|
"react/jsx-runtime",
|
|
299
324
|
"react/jsx-dev-runtime",
|
|
300
|
-
|
|
325
|
+
nested(
|
|
326
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
|
|
327
|
+
),
|
|
301
328
|
],
|
|
302
329
|
exclude: excludeDeps,
|
|
303
330
|
esbuildOptions: sharedEsbuildOptions,
|
|
@@ -310,7 +337,9 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
310
337
|
"react",
|
|
311
338
|
"react/jsx-runtime",
|
|
312
339
|
"react/jsx-dev-runtime",
|
|
313
|
-
|
|
340
|
+
nested(
|
|
341
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge",
|
|
342
|
+
),
|
|
314
343
|
],
|
|
315
344
|
esbuildOptions: sharedEsbuildOptions,
|
|
316
345
|
},
|
|
@@ -458,5 +487,11 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
458
487
|
}),
|
|
459
488
|
);
|
|
460
489
|
|
|
490
|
+
debugConfig?.(
|
|
491
|
+
"rango(%s) setup done: %d plugin(s) (%sms)",
|
|
492
|
+
preset,
|
|
493
|
+
plugins.length,
|
|
494
|
+
(performance.now() - rangoStart).toFixed(1),
|
|
495
|
+
);
|
|
461
496
|
return plugins;
|
|
462
497
|
}
|