@rangojs/router 0.0.0-experimental.88a3b2f7 → 0.0.0-experimental.89
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 +1185 -420
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +7 -5
- package/skills/breadcrumbs/SKILL.md +3 -1
- package/skills/handler-use/SKILL.md +362 -0
- package/skills/hooks/SKILL.md +28 -20
- package/skills/intercept/SKILL.md +20 -0
- package/skills/layout/SKILL.md +22 -0
- package/skills/links/SKILL.md +88 -16
- package/skills/loader/SKILL.md +35 -2
- package/skills/middleware/SKILL.md +32 -3
- package/skills/migrate-nextjs/SKILL.md +560 -0
- package/skills/migrate-react-router/SKILL.md +765 -0
- package/skills/parallel/SKILL.md +59 -0
- package/skills/rango/SKILL.md +24 -22
- package/skills/response-routes/SKILL.md +8 -0
- package/skills/route/SKILL.md +24 -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 +72 -4
- package/src/browser/navigation-client.ts +64 -13
- package/src/browser/navigation-store.ts +25 -1
- package/src/browser/partial-update.ts +34 -3
- package/src/browser/prefetch/cache.ts +129 -21
- package/src/browser/prefetch/fetch.ts +148 -16
- package/src/browser/prefetch/queue.ts +36 -5
- package/src/browser/rango-state.ts +53 -13
- package/src/browser/react/Link.tsx +30 -2
- package/src/browser/react/NavigationProvider.tsx +50 -11
- package/src/browser/react/use-navigation.ts +22 -2
- 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/segment-reconciler.ts +36 -14
- package/src/browser/types.ts +13 -0
- package/src/build/route-trie.ts +50 -24
- package/src/cache/cf/cf-cache-store.ts +5 -7
- package/src/client.tsx +84 -230
- package/src/index.rsc.ts +3 -0
- package/src/index.ts +44 -9
- package/src/outlet-context.ts +1 -1
- package/src/response-utils.ts +28 -0
- package/src/reverse.ts +7 -3
- package/src/route-definition/dsl-helpers.ts +180 -24
- package/src/route-definition/helpers-types.ts +61 -14
- package/src/route-definition/resolve-handler-use.ts +6 -0
- package/src/route-types.ts +7 -0
- package/src/router/handler-context.ts +24 -4
- package/src/router/lazy-includes.ts +6 -6
- package/src/router/loader-resolution.ts +73 -46
- package/src/router/manifest.ts +22 -13
- package/src/router/match-api.ts +3 -3
- package/src/router/match-middleware/cache-lookup.ts +10 -5
- package/src/router/match-middleware/segment-resolution.ts +1 -1
- package/src/router/match-result.ts +82 -4
- 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/segment-resolution/fresh.ts +52 -0
- package/src/router/segment-resolution/revalidation.ts +69 -1
- 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 +21 -9
- package/src/rsc/helpers.ts +69 -41
- package/src/rsc/loader-fetch.ts +23 -3
- package/src/rsc/progressive-enhancement.ts +12 -2
- package/src/rsc/response-route-handler.ts +14 -1
- package/src/rsc/rsc-rendering.ts +12 -1
- package/src/rsc/server-action.ts +8 -0
- package/src/rsc/types.ts +1 -0
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +122 -0
- package/src/segment-system.tsx +11 -61
- package/src/server/context.ts +26 -3
- package/src/server/handle-store.ts +19 -0
- package/src/server/request-context.ts +64 -56
- 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/types/route-entry.ts +11 -0
- package/src/types/segments.ts +1 -1
- package/src/urls/include-helper.ts +24 -14
- package/src/urls/path-helper-types.ts +34 -5
- package/src/urls/response-types.ts +2 -10
- package/src/use-loader.tsx +77 -5
- package/src/vite/debug.ts +184 -0
- package/src/vite/discovery/discover-routers.ts +31 -3
- package/src/vite/discovery/prerender-collection.ts +172 -84
- package/src/vite/plugins/cjs-to-esm.ts +5 -0
- package/src/vite/plugins/client-ref-dedup.ts +16 -0
- package/src/vite/plugins/client-ref-hashing.ts +16 -4
- 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 +52 -28
- package/src/vite/plugins/expose-id-utils.ts +12 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +30 -0
- package/src/vite/plugins/expose-ids/router-transform.ts +20 -3
- package/src/vite/plugins/expose-internal-ids.ts +563 -316
- package/src/vite/plugins/performance-tracks.ts +17 -9
- package/src/vite/plugins/use-cache-transform.ts +56 -43
- package/src/vite/rango.ts +49 -14
- package/src/vite/router-discovery.ts +244 -29
- package/src/vite/utils/banner.ts +1 -1
- package/src/vite/utils/package-resolution.ts +41 -1
- package/src/vite/utils/prerender-utils.ts +20 -6
package/dist/vite/index.js
CHANGED
|
@@ -18,6 +18,9 @@ function hashId(filePath, exportName) {
|
|
|
18
18
|
const hash = crypto.createHash("sha256").update(input).digest("hex");
|
|
19
19
|
return `${hash.slice(0, 8)}#${exportName}`;
|
|
20
20
|
}
|
|
21
|
+
function makeStubId(filePath, exportName, isBuild) {
|
|
22
|
+
return isBuild ? hashId(filePath, exportName) : `${filePath}#${exportName}`;
|
|
23
|
+
}
|
|
21
24
|
function hashInlineId(filePath, lineNumber, index) {
|
|
22
25
|
const input = index !== void 0 && index > 0 ? `${filePath}:${lineNumber}:${index}` : `${filePath}:${lineNumber}`;
|
|
23
26
|
return crypto.createHash("sha256").update(input).digest("hex").slice(0, 8);
|
|
@@ -188,7 +191,99 @@ function escapeRegExp(input) {
|
|
|
188
191
|
return input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
189
192
|
}
|
|
190
193
|
|
|
194
|
+
// src/vite/debug.ts
|
|
195
|
+
import debugFactory from "debug";
|
|
196
|
+
var NS = {
|
|
197
|
+
config: "rango:config",
|
|
198
|
+
discovery: "rango:discovery",
|
|
199
|
+
routes: "rango:routes",
|
|
200
|
+
prerender: "rango:prerender",
|
|
201
|
+
build: "rango:build",
|
|
202
|
+
dev: "rango:dev",
|
|
203
|
+
transform: "rango:transform"
|
|
204
|
+
};
|
|
205
|
+
if (process.env.INTERNAL_RANGO_DEBUG) {
|
|
206
|
+
const existing = debugFactory.disable();
|
|
207
|
+
debugFactory.enable(existing ? `${existing},rango:*` : "rango:*");
|
|
208
|
+
}
|
|
209
|
+
function createRangoDebugger(namespace) {
|
|
210
|
+
const primary = debugFactory(namespace);
|
|
211
|
+
const shadow = debugFactory(`vite:${namespace}`);
|
|
212
|
+
if (primary.enabled) return primary;
|
|
213
|
+
if (shadow.enabled) return shadow;
|
|
214
|
+
return void 0;
|
|
215
|
+
}
|
|
216
|
+
async function timed(debug11, label, fn) {
|
|
217
|
+
if (!debug11) return await fn();
|
|
218
|
+
const start = performance.now();
|
|
219
|
+
try {
|
|
220
|
+
return await fn();
|
|
221
|
+
} finally {
|
|
222
|
+
debug11("%s (%sms)", label, (performance.now() - start).toFixed(1));
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
function timedSync(debug11, label, fn) {
|
|
226
|
+
if (!debug11) return fn();
|
|
227
|
+
const start = performance.now();
|
|
228
|
+
try {
|
|
229
|
+
return fn();
|
|
230
|
+
} finally {
|
|
231
|
+
debug11("%s (%sms)", label, (performance.now() - start).toFixed(1));
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function createCounter(debug11, label) {
|
|
235
|
+
if (!debug11) return void 0;
|
|
236
|
+
let n = 0;
|
|
237
|
+
let totalMs = 0;
|
|
238
|
+
let slowestMs = 0;
|
|
239
|
+
let slowestFile = "";
|
|
240
|
+
const record = (file, ms) => {
|
|
241
|
+
n++;
|
|
242
|
+
totalMs += ms;
|
|
243
|
+
if (ms > slowestMs) {
|
|
244
|
+
slowestMs = ms;
|
|
245
|
+
slowestFile = file;
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
return {
|
|
249
|
+
record,
|
|
250
|
+
time(file, fn) {
|
|
251
|
+
const start = performance.now();
|
|
252
|
+
let out;
|
|
253
|
+
try {
|
|
254
|
+
out = fn();
|
|
255
|
+
} catch (err) {
|
|
256
|
+
record(file, performance.now() - start);
|
|
257
|
+
throw err;
|
|
258
|
+
}
|
|
259
|
+
if (out && typeof out.then === "function") {
|
|
260
|
+
return out.finally(
|
|
261
|
+
() => record(file, performance.now() - start)
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
record(file, performance.now() - start);
|
|
265
|
+
return out;
|
|
266
|
+
},
|
|
267
|
+
flush() {
|
|
268
|
+
if (n === 0) return;
|
|
269
|
+
debug11(
|
|
270
|
+
"%s: %d files, %sms total, slowest %sms %s",
|
|
271
|
+
label,
|
|
272
|
+
n,
|
|
273
|
+
totalMs.toFixed(1),
|
|
274
|
+
slowestMs.toFixed(1),
|
|
275
|
+
slowestFile
|
|
276
|
+
);
|
|
277
|
+
n = 0;
|
|
278
|
+
totalMs = 0;
|
|
279
|
+
slowestMs = 0;
|
|
280
|
+
slowestFile = "";
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
191
285
|
// src/vite/plugins/expose-action-id.ts
|
|
286
|
+
var debug = createRangoDebugger(NS.transform);
|
|
192
287
|
function getRscPluginApi(config) {
|
|
193
288
|
let plugin = config.plugins.find((p) => p.name === "rsc:minimal");
|
|
194
289
|
if (!plugin) {
|
|
@@ -277,6 +372,8 @@ function exposeActionId() {
|
|
|
277
372
|
let isBuild = false;
|
|
278
373
|
let hashToFileMap;
|
|
279
374
|
let rscPluginApi;
|
|
375
|
+
const counterTransform = createCounter(debug, "expose-action-id transform");
|
|
376
|
+
const counterRender = createCounter(debug, "expose-action-id renderChunk");
|
|
280
377
|
return {
|
|
281
378
|
name: "@rangojs/router:expose-action-id",
|
|
282
379
|
// Run after all other plugins (including RSC plugin's transforms)
|
|
@@ -286,6 +383,10 @@ function exposeActionId() {
|
|
|
286
383
|
isBuild = config.command === "build";
|
|
287
384
|
rscPluginApi = getRscPluginApi(config);
|
|
288
385
|
},
|
|
386
|
+
buildEnd() {
|
|
387
|
+
counterTransform?.flush();
|
|
388
|
+
counterRender?.flush();
|
|
389
|
+
},
|
|
289
390
|
buildStart() {
|
|
290
391
|
if (!rscPluginApi) {
|
|
291
392
|
rscPluginApi = getRscPluginApi(config);
|
|
@@ -322,28 +423,42 @@ function exposeActionId() {
|
|
|
322
423
|
if (id.includes("/node_modules/")) {
|
|
323
424
|
return;
|
|
324
425
|
}
|
|
325
|
-
|
|
426
|
+
const start = counterTransform ? performance.now() : 0;
|
|
427
|
+
try {
|
|
428
|
+
return transformServerReferences(code, id);
|
|
429
|
+
} finally {
|
|
430
|
+
counterTransform?.record(id, performance.now() - start);
|
|
431
|
+
}
|
|
326
432
|
},
|
|
327
433
|
// Build mode: renderChunk runs after all transforms and bundling complete
|
|
328
434
|
renderChunk(code, chunk) {
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
code
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
435
|
+
const start = counterRender ? performance.now() : 0;
|
|
436
|
+
try {
|
|
437
|
+
const isRscEnv = this.environment?.name === "rsc";
|
|
438
|
+
const effectiveMap = isRscEnv ? hashToFileMap : void 0;
|
|
439
|
+
if (isRscEnv && hashToFileMap) {
|
|
440
|
+
const s = new MagicString(code);
|
|
441
|
+
const changed1 = applyServerReferenceWrapping(code, s, effectiveMap);
|
|
442
|
+
const changed2 = applyRegisterReferenceWrapping(
|
|
443
|
+
code,
|
|
444
|
+
s,
|
|
445
|
+
hashToFileMap
|
|
446
|
+
);
|
|
447
|
+
if (changed1 || changed2) {
|
|
448
|
+
return {
|
|
449
|
+
code: s.toString(),
|
|
450
|
+
map: s.generateMap({
|
|
451
|
+
source: chunk.fileName,
|
|
452
|
+
includeContent: true
|
|
453
|
+
})
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
return null;
|
|
343
457
|
}
|
|
344
|
-
return
|
|
458
|
+
return transformServerReferences(code, chunk.fileName, effectiveMap);
|
|
459
|
+
} finally {
|
|
460
|
+
counterRender?.record(chunk.fileName, performance.now() - start);
|
|
345
461
|
}
|
|
346
|
-
return transformServerReferences(code, chunk.fileName, effectiveMap);
|
|
347
462
|
}
|
|
348
463
|
};
|
|
349
464
|
}
|
|
@@ -910,9 +1025,7 @@ function generateWholeFileStubs(cfg, bindings, code, filePath, isBuild) {
|
|
|
910
1025
|
});
|
|
911
1026
|
return { code: stubs.join("\n") + "\n", map: null };
|
|
912
1027
|
}
|
|
913
|
-
function
|
|
914
|
-
if (bindings.length === 0) return null;
|
|
915
|
-
const s = new MagicString2(code);
|
|
1028
|
+
function stubHandlerExprs(cfg, bindings, s, filePath, isBuild) {
|
|
916
1029
|
let hasChanges = false;
|
|
917
1030
|
for (const binding of bindings) {
|
|
918
1031
|
const exportName = binding.exportNames[0];
|
|
@@ -924,15 +1037,7 @@ function generateExprStubs(cfg, bindings, code, filePath, sourceId, isBuild) {
|
|
|
924
1037
|
);
|
|
925
1038
|
hasChanges = true;
|
|
926
1039
|
}
|
|
927
|
-
|
|
928
|
-
return {
|
|
929
|
-
code: s.toString(),
|
|
930
|
-
map: s.generateMap({
|
|
931
|
-
source: sourceId,
|
|
932
|
-
includeContent: true,
|
|
933
|
-
hires: "boundary"
|
|
934
|
-
})
|
|
935
|
-
};
|
|
1040
|
+
return hasChanges;
|
|
936
1041
|
}
|
|
937
1042
|
function transformHandlerIds(cfg, bindings, s, filePath, isBuild) {
|
|
938
1043
|
let hasChanges = false;
|
|
@@ -960,6 +1065,7 @@ ${binding.localName}.$$id = "${handlerId}";`;
|
|
|
960
1065
|
import MagicString3 from "magic-string";
|
|
961
1066
|
import path3 from "node:path";
|
|
962
1067
|
import { createHash } from "node:crypto";
|
|
1068
|
+
var debug2 = createRangoDebugger(NS.transform);
|
|
963
1069
|
function transformRouter(code, filePath, routerFnNames, absolutePath) {
|
|
964
1070
|
const pat = new RegExp(
|
|
965
1071
|
`\\b(?:${routerFnNames.map((n) => n.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})\\s*(?:<[^>]*>)?\\s*\\(`,
|
|
@@ -1002,11 +1108,15 @@ function transformRouter(code, filePath, routerFnNames, absolutePath) {
|
|
|
1002
1108
|
}
|
|
1003
1109
|
function exposeRouterId() {
|
|
1004
1110
|
let projectRoot = "";
|
|
1111
|
+
const counter = createCounter(debug2, "expose-router-id");
|
|
1005
1112
|
return {
|
|
1006
1113
|
name: "@rangojs/router:expose-router-id",
|
|
1007
1114
|
configResolved(config) {
|
|
1008
1115
|
projectRoot = config.root;
|
|
1009
1116
|
},
|
|
1117
|
+
buildEnd() {
|
|
1118
|
+
counter?.flush();
|
|
1119
|
+
},
|
|
1010
1120
|
transform(code, id) {
|
|
1011
1121
|
if (!code.includes("createRouter")) return null;
|
|
1012
1122
|
if (!/import\s*\{[^}]*\bcreateRouter\b[^}]*\}\s*from\s*["']@rangojs\/router(?:\/server)?["']/.test(
|
|
@@ -1015,14 +1125,25 @@ function exposeRouterId() {
|
|
|
1015
1125
|
return null;
|
|
1016
1126
|
}
|
|
1017
1127
|
if (id.includes("node_modules")) return null;
|
|
1018
|
-
const
|
|
1019
|
-
|
|
1020
|
-
|
|
1128
|
+
const start = counter ? performance.now() : 0;
|
|
1129
|
+
try {
|
|
1130
|
+
const filePath = normalizePath(path3.relative(projectRoot, id));
|
|
1131
|
+
const routerFnNames = getImportedFnNames(code, "createRouter");
|
|
1132
|
+
return transformRouter(
|
|
1133
|
+
code,
|
|
1134
|
+
filePath,
|
|
1135
|
+
routerFnNames,
|
|
1136
|
+
normalizePath(id)
|
|
1137
|
+
);
|
|
1138
|
+
} finally {
|
|
1139
|
+
counter?.record(id, performance.now() - start);
|
|
1140
|
+
}
|
|
1021
1141
|
}
|
|
1022
1142
|
};
|
|
1023
1143
|
}
|
|
1024
1144
|
|
|
1025
1145
|
// src/vite/plugins/expose-internal-ids.ts
|
|
1146
|
+
var debug3 = createRangoDebugger(NS.transform);
|
|
1026
1147
|
var VIRTUAL_LOADER_MANIFEST = "virtual:rsc-router/loader-manifest";
|
|
1027
1148
|
var RESOLVED_VIRTUAL_LOADER_MANIFEST = "\0" + VIRTUAL_LOADER_MANIFEST;
|
|
1028
1149
|
var VIRTUAL_HANDLER_PREFIX = "virtual:handler-extract:";
|
|
@@ -1035,9 +1156,13 @@ function exposeInternalIds(options) {
|
|
|
1035
1156
|
const staticHandlerModules = /* @__PURE__ */ new Map();
|
|
1036
1157
|
const virtualHandlers = /* @__PURE__ */ new Map();
|
|
1037
1158
|
const unsupportedShapeWarnings = /* @__PURE__ */ new Set();
|
|
1159
|
+
const counter = createCounter(debug3, "expose-internal-ids");
|
|
1038
1160
|
return {
|
|
1039
1161
|
name: "@rangojs/router:expose-internal-ids",
|
|
1040
1162
|
enforce: "post",
|
|
1163
|
+
buildEnd() {
|
|
1164
|
+
counter?.flush();
|
|
1165
|
+
},
|
|
1041
1166
|
api: {
|
|
1042
1167
|
prerenderHandlerModules,
|
|
1043
1168
|
staticHandlerModules
|
|
@@ -1151,11 +1276,13 @@ ${lazyImports.join(",\n")}
|
|
|
1151
1276
|
// --------------- Unified transform ---------------
|
|
1152
1277
|
transform(code, id) {
|
|
1153
1278
|
if (id.includes("/node_modules/")) return;
|
|
1154
|
-
const
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
this.
|
|
1158
|
-
|
|
1279
|
+
const __t0 = counter ? performance.now() : 0;
|
|
1280
|
+
try {
|
|
1281
|
+
const filePath = normalizePath(path4.relative(projectRoot, id));
|
|
1282
|
+
const isRscEnv = this.environment?.name === "rsc";
|
|
1283
|
+
if (id.includes(".named-routes.gen.") && !isRscEnv && this.environment?.name === "client") {
|
|
1284
|
+
this.warn(
|
|
1285
|
+
`
|
|
1159
1286
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
1160
1287
|
!! !!
|
|
1161
1288
|
!! WARNING: NamedRoutes imported in a CLIENT component! !!
|
|
@@ -1175,228 +1302,373 @@ ${lazyImports.join(",\n")}
|
|
|
1175
1302
|
!! !!
|
|
1176
1303
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
1177
1304
|
`
|
|
1178
|
-
|
|
1179
|
-
}
|
|
1180
|
-
if (!code.includes("@rangojs/router")) return;
|
|
1181
|
-
const has = detectImports(code);
|
|
1182
|
-
const hasLoaderCode = has.loader && code.includes("createLoader");
|
|
1183
|
-
const hasHandleCode = has.handle && code.includes("createHandle");
|
|
1184
|
-
const hasLocationStateCode = has.locationState && code.includes("createLocationState");
|
|
1185
|
-
const hasPrerenderHandlerCode = has.prerenderHandler && code.includes("Prerender");
|
|
1186
|
-
const hasStaticHandlerCode = has.staticHandler && code.includes("Static");
|
|
1187
|
-
if (!hasLoaderCode && !hasHandleCode && !hasLocationStateCode && !hasPrerenderHandlerCode && !hasStaticHandlerCode) {
|
|
1188
|
-
return;
|
|
1189
|
-
}
|
|
1190
|
-
const _fnNamesCache = /* @__PURE__ */ new Map();
|
|
1191
|
-
const _bindingsCache = /* @__PURE__ */ new Map();
|
|
1192
|
-
let _cachedAst;
|
|
1193
|
-
let _astParseFailed = false;
|
|
1194
|
-
let _astCodeRef = code;
|
|
1195
|
-
const getFnNames = (canonicalName) => {
|
|
1196
|
-
let result = _fnNamesCache.get(canonicalName);
|
|
1197
|
-
if (!result) {
|
|
1198
|
-
result = getImportedFnNames(code, canonicalName);
|
|
1199
|
-
_fnNamesCache.set(canonicalName, result);
|
|
1305
|
+
);
|
|
1200
1306
|
}
|
|
1201
|
-
return
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1307
|
+
if (!code.includes("@rangojs/router")) return;
|
|
1308
|
+
const has = detectImports(code);
|
|
1309
|
+
const hasLoaderCode = has.loader && code.includes("createLoader");
|
|
1310
|
+
const hasHandleCode = has.handle && code.includes("createHandle");
|
|
1311
|
+
const hasLocationStateCode = has.locationState && code.includes("createLocationState");
|
|
1312
|
+
const hasPrerenderHandlerCode = has.prerenderHandler && code.includes("Prerender");
|
|
1313
|
+
const hasStaticHandlerCode = has.staticHandler && code.includes("Static");
|
|
1314
|
+
if (!hasLoaderCode && !hasHandleCode && !hasLocationStateCode && !hasPrerenderHandlerCode && !hasStaticHandlerCode) {
|
|
1315
|
+
return;
|
|
1208
1316
|
}
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1317
|
+
const _fnNamesCache = /* @__PURE__ */ new Map();
|
|
1318
|
+
const _bindingsCache = /* @__PURE__ */ new Map();
|
|
1319
|
+
let _cachedAst;
|
|
1320
|
+
let _astParseFailed = false;
|
|
1321
|
+
let _astCodeRef = code;
|
|
1322
|
+
const getFnNames = (canonicalName) => {
|
|
1323
|
+
let result = _fnNamesCache.get(canonicalName);
|
|
1324
|
+
if (!result) {
|
|
1325
|
+
result = getImportedFnNames(code, canonicalName);
|
|
1326
|
+
_fnNamesCache.set(canonicalName, result);
|
|
1327
|
+
}
|
|
1328
|
+
return result;
|
|
1329
|
+
};
|
|
1330
|
+
const lazyAst = () => {
|
|
1331
|
+
if (code !== _astCodeRef) {
|
|
1332
|
+
_cachedAst = void 0;
|
|
1333
|
+
_astParseFailed = false;
|
|
1334
|
+
_astCodeRef = code;
|
|
1335
|
+
}
|
|
1336
|
+
if (_cachedAst !== void 0 || _astParseFailed) return _cachedAst;
|
|
1337
|
+
try {
|
|
1338
|
+
_cachedAst = parseAst2(code, { jsx: true });
|
|
1339
|
+
} catch {
|
|
1340
|
+
_astParseFailed = true;
|
|
1341
|
+
}
|
|
1342
|
+
return _cachedAst;
|
|
1343
|
+
};
|
|
1344
|
+
const getBindings = (currentCode, fnNames) => {
|
|
1345
|
+
const key = fnNames.join("\0");
|
|
1346
|
+
let result = _bindingsCache.get(key);
|
|
1347
|
+
if (!result) {
|
|
1348
|
+
result = collectCreateExportBindings(
|
|
1349
|
+
currentCode,
|
|
1350
|
+
fnNames,
|
|
1351
|
+
lazyAst()
|
|
1352
|
+
);
|
|
1353
|
+
_bindingsCache.set(key, result);
|
|
1354
|
+
}
|
|
1355
|
+
return result;
|
|
1356
|
+
};
|
|
1357
|
+
for (const cfg of STRICT_CREATE_CONFIGS) {
|
|
1358
|
+
const hasCode = cfg.fnName === "createLoader" ? hasLoaderCode : cfg.fnName === "createHandle" ? hasHandleCode : hasLocationStateCode;
|
|
1359
|
+
if (!hasCode) continue;
|
|
1360
|
+
const fnNames = getFnNames(cfg.fnName);
|
|
1361
|
+
const totalCalls = countCreateCallsForNames(code, fnNames);
|
|
1362
|
+
const supportedBindings = getBindings(code, fnNames).length;
|
|
1363
|
+
if (totalCalls <= supportedBindings) continue;
|
|
1364
|
+
const warnKey = `${id}::${cfg.fnName}`;
|
|
1365
|
+
if (unsupportedShapeWarnings.has(warnKey)) continue;
|
|
1366
|
+
unsupportedShapeWarnings.add(warnKey);
|
|
1367
|
+
this.warn(buildUnsupportedShapeWarning(filePath, cfg.fnName));
|
|
1214
1368
|
}
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1369
|
+
if (hasLoaderCode && isRscEnv) {
|
|
1370
|
+
const fnNames = getFnNames("createLoader");
|
|
1371
|
+
const bindings = getBindings(code, fnNames);
|
|
1372
|
+
for (const binding of bindings) {
|
|
1373
|
+
const exportName = binding.exportNames[0];
|
|
1374
|
+
const hashedId = hashId(filePath, exportName);
|
|
1375
|
+
loaderRegistry.set(hashedId, {
|
|
1376
|
+
filePath,
|
|
1377
|
+
exportName
|
|
1378
|
+
});
|
|
1379
|
+
}
|
|
1223
1380
|
}
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
const totalCalls = countCreateCallsForNames(code, fnNames);
|
|
1231
|
-
const supportedBindings = getBindings(code, fnNames).length;
|
|
1232
|
-
if (totalCalls <= supportedBindings) continue;
|
|
1233
|
-
const warnKey = `${id}::${cfg.fnName}`;
|
|
1234
|
-
if (unsupportedShapeWarnings.has(warnKey)) continue;
|
|
1235
|
-
unsupportedShapeWarnings.add(warnKey);
|
|
1236
|
-
this.warn(buildUnsupportedShapeWarning(filePath, cfg.fnName));
|
|
1237
|
-
}
|
|
1238
|
-
if (hasLoaderCode && isRscEnv) {
|
|
1239
|
-
const fnNames = getFnNames("createLoader");
|
|
1240
|
-
const bindings = getBindings(code, fnNames);
|
|
1241
|
-
for (const binding of bindings) {
|
|
1242
|
-
const exportName = binding.exportNames[0];
|
|
1243
|
-
const hashedId = hashId(filePath, exportName);
|
|
1244
|
-
loaderRegistry.set(hashedId, {
|
|
1381
|
+
if (hasLoaderCode && !isRscEnv) {
|
|
1382
|
+
const fnNames = getFnNames("createLoader");
|
|
1383
|
+
const bindings = getBindings(code, fnNames);
|
|
1384
|
+
const stubResult = generateClientLoaderStubs(
|
|
1385
|
+
bindings,
|
|
1386
|
+
code,
|
|
1245
1387
|
filePath,
|
|
1246
|
-
|
|
1247
|
-
|
|
1388
|
+
isBuild
|
|
1389
|
+
);
|
|
1390
|
+
if (stubResult) return stubResult;
|
|
1248
1391
|
}
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
}
|
|
1261
|
-
if (hasPrerenderHandlerCode && !isRscEnv) {
|
|
1262
|
-
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1263
|
-
const bindings = getBindings(code, fnNames);
|
|
1264
|
-
const wholeFile = generateWholeFileStubs(
|
|
1265
|
-
PRERENDER_CONFIG,
|
|
1266
|
-
bindings,
|
|
1267
|
-
code,
|
|
1268
|
-
filePath,
|
|
1269
|
-
isBuild
|
|
1270
|
-
);
|
|
1271
|
-
if (wholeFile) return wholeFile;
|
|
1272
|
-
const exprStubs = generateExprStubs(
|
|
1273
|
-
PRERENDER_CONFIG,
|
|
1274
|
-
bindings,
|
|
1275
|
-
code,
|
|
1276
|
-
filePath,
|
|
1277
|
-
id,
|
|
1278
|
-
isBuild
|
|
1279
|
-
);
|
|
1280
|
-
if (exprStubs) return exprStubs;
|
|
1281
|
-
}
|
|
1282
|
-
if (hasPrerenderHandlerCode && isRscEnv && isBuild) {
|
|
1283
|
-
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1284
|
-
const exportNames = getBindings(code, fnNames).map(
|
|
1285
|
-
(b) => b.exportNames[0]
|
|
1286
|
-
);
|
|
1287
|
-
if (exportNames.length > 0) {
|
|
1288
|
-
prerenderHandlerModules.set(id, exportNames);
|
|
1392
|
+
if (hasPrerenderHandlerCode && !isRscEnv) {
|
|
1393
|
+
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1394
|
+
const bindings = getBindings(code, fnNames);
|
|
1395
|
+
const wholeFile = generateWholeFileStubs(
|
|
1396
|
+
PRERENDER_CONFIG,
|
|
1397
|
+
bindings,
|
|
1398
|
+
code,
|
|
1399
|
+
filePath,
|
|
1400
|
+
isBuild
|
|
1401
|
+
);
|
|
1402
|
+
if (wholeFile) return wholeFile;
|
|
1289
1403
|
}
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
const
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
const
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1404
|
+
if (hasPrerenderHandlerCode && isRscEnv && isBuild) {
|
|
1405
|
+
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1406
|
+
const exportNames = getBindings(code, fnNames).map(
|
|
1407
|
+
(b) => b.exportNames[0]
|
|
1408
|
+
);
|
|
1409
|
+
if (exportNames.length > 0) {
|
|
1410
|
+
prerenderHandlerModules.set(id, exportNames);
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
let changed = false;
|
|
1414
|
+
const handlerConfigs = [
|
|
1415
|
+
hasStaticHandlerCode && STATIC_CONFIG,
|
|
1416
|
+
hasPrerenderHandlerCode && PRERENDER_CONFIG
|
|
1417
|
+
].filter((c) => !!c).map((cfg) => {
|
|
1418
|
+
const fnNames = getFnNames(cfg.fnName);
|
|
1419
|
+
return { cfg, fnNames };
|
|
1420
|
+
});
|
|
1421
|
+
for (const { cfg, fnNames } of handlerConfigs) {
|
|
1422
|
+
const totalCalls = countCreateCallsForNames(code, fnNames);
|
|
1423
|
+
const supportedBindings = getBindings(code, fnNames).length;
|
|
1424
|
+
if (totalCalls > supportedBindings) {
|
|
1425
|
+
const iterS = new MagicString4(code);
|
|
1426
|
+
const result = transformInlineHandlers(
|
|
1427
|
+
cfg.fnName,
|
|
1428
|
+
VIRTUAL_HANDLER_PREFIX,
|
|
1429
|
+
iterS,
|
|
1430
|
+
code,
|
|
1431
|
+
filePath,
|
|
1432
|
+
virtualHandlers,
|
|
1433
|
+
id,
|
|
1434
|
+
parseAst2
|
|
1435
|
+
);
|
|
1436
|
+
if (result) {
|
|
1437
|
+
changed = true;
|
|
1438
|
+
code = iterS.toString();
|
|
1439
|
+
_bindingsCache.clear();
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
if (hasStaticHandlerCode && !isRscEnv) {
|
|
1444
|
+
const fnNames = getFnNames(STATIC_CONFIG.fnName);
|
|
1445
|
+
const bindings = getBindings(code, fnNames);
|
|
1446
|
+
const wholeFile = generateWholeFileStubs(
|
|
1447
|
+
STATIC_CONFIG,
|
|
1448
|
+
bindings,
|
|
1308
1449
|
code,
|
|
1309
1450
|
filePath,
|
|
1310
|
-
|
|
1311
|
-
id,
|
|
1312
|
-
parseAst2
|
|
1451
|
+
isBuild
|
|
1313
1452
|
);
|
|
1314
|
-
if (
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1453
|
+
if (wholeFile) return wholeFile;
|
|
1454
|
+
}
|
|
1455
|
+
if (!isRscEnv && (hasPrerenderHandlerCode || hasStaticHandlerCode)) {
|
|
1456
|
+
const prerenderFnNames = hasPrerenderHandlerCode ? getFnNames(PRERENDER_CONFIG.fnName) : [];
|
|
1457
|
+
const staticFnNames = hasStaticHandlerCode ? getFnNames(STATIC_CONFIG.fnName) : [];
|
|
1458
|
+
const loaderFnNames = hasLoaderCode ? getFnNames("createLoader") : [];
|
|
1459
|
+
const handleFnNames = hasHandleCode ? getFnNames("createHandle") : [];
|
|
1460
|
+
const lsFnNames = hasLocationStateCode ? getFnNames("createLocationState") : [];
|
|
1461
|
+
const allBindings = [];
|
|
1462
|
+
for (const fnNames of [
|
|
1463
|
+
prerenderFnNames,
|
|
1464
|
+
staticFnNames,
|
|
1465
|
+
loaderFnNames,
|
|
1466
|
+
handleFnNames,
|
|
1467
|
+
lsFnNames
|
|
1468
|
+
]) {
|
|
1469
|
+
if (fnNames.length > 0) {
|
|
1470
|
+
allBindings.push(...getBindings(code, fnNames));
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
let canStubWholeFile = allBindings.length > 0 && isExportOnlyFile(code, allBindings);
|
|
1474
|
+
if (canStubWholeFile && (handleFnNames.length > 0 || lsFnNames.length > 0)) {
|
|
1475
|
+
const exportedLocals = new Set(allBindings.map((b) => b.localName));
|
|
1476
|
+
const strippedBindings = [];
|
|
1477
|
+
const localDeclPattern = /(?:^|;|\n)\s*(?:const|let|var|function)\s+(\w+)/g;
|
|
1478
|
+
let declMatch;
|
|
1479
|
+
while ((declMatch = localDeclPattern.exec(code)) !== null) {
|
|
1480
|
+
const name = declMatch[1];
|
|
1481
|
+
if (!exportedLocals.has(name) && !/^_c\d*$/.test(name)) {
|
|
1482
|
+
strippedBindings.push(name);
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
const importPattern = /import\s*\{([^}]*)\}\s*from\s*["'](?!@rangojs\/router)[^"']*["']/g;
|
|
1486
|
+
let importMatch;
|
|
1487
|
+
while ((importMatch = importPattern.exec(code)) !== null) {
|
|
1488
|
+
for (const spec of importMatch[1].split(",")) {
|
|
1489
|
+
const m = spec.trim().match(/^[A-Za-z_$][\w$]*(?:\s+as\s+([A-Za-z_$][\w$]*))?$/);
|
|
1490
|
+
if (m)
|
|
1491
|
+
strippedBindings.push(m[1] || m[0].trim().split(/\s/)[0]);
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
const defaultImportPattern = /import\s+([A-Za-z_$][\w$]*)\s+from\s*["'](?!@rangojs\/router)[^"']*["']/g;
|
|
1495
|
+
while ((importMatch = defaultImportPattern.exec(code)) !== null) {
|
|
1496
|
+
strippedBindings.push(importMatch[1]);
|
|
1497
|
+
}
|
|
1498
|
+
const nsImportPattern = /import\s+\*\s+as\s+([A-Za-z_$][\w$]*)\s+from\s*["'](?!@rangojs\/router)[^"']*["']/g;
|
|
1499
|
+
while ((importMatch = nsImportPattern.exec(code)) !== null) {
|
|
1500
|
+
strippedBindings.push(importMatch[1]);
|
|
1501
|
+
}
|
|
1502
|
+
if (strippedBindings.length > 0) {
|
|
1503
|
+
const preservedBindings = allBindings.filter((b) => {
|
|
1504
|
+
const fc = code.slice(b.callExprStart, b.callOpenParenPos + 1);
|
|
1505
|
+
return handleFnNames.some((n) => fc.includes(n)) || lsFnNames.some((n) => fc.includes(n));
|
|
1506
|
+
});
|
|
1507
|
+
const strippedRe = new RegExp(
|
|
1508
|
+
`\\b(?:${strippedBindings.join("|")})\\b`
|
|
1509
|
+
);
|
|
1510
|
+
canStubWholeFile = !preservedBindings.some((b) => {
|
|
1511
|
+
const expr = code.slice(
|
|
1512
|
+
b.callExprStart,
|
|
1513
|
+
b.callCloseParenPos + 1
|
|
1514
|
+
);
|
|
1515
|
+
return strippedRe.test(expr);
|
|
1516
|
+
});
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
if (canStubWholeFile) {
|
|
1520
|
+
const lines = [];
|
|
1521
|
+
const neededImports = [];
|
|
1522
|
+
if (handleFnNames.length > 0) neededImports.push("createHandle");
|
|
1523
|
+
if (lsFnNames.length > 0) neededImports.push("createLocationState");
|
|
1524
|
+
if (neededImports.length > 0) {
|
|
1525
|
+
lines.push(
|
|
1526
|
+
`import { ${neededImports.join(", ")} } from "@rangojs/router";`
|
|
1527
|
+
);
|
|
1528
|
+
}
|
|
1529
|
+
for (const binding of allBindings) {
|
|
1530
|
+
const fnCall = code.slice(
|
|
1531
|
+
binding.callExprStart,
|
|
1532
|
+
binding.callOpenParenPos + 1
|
|
1533
|
+
);
|
|
1534
|
+
const isHandle = handleFnNames.some((n) => fnCall.includes(n));
|
|
1535
|
+
const isLocationState = lsFnNames.some((n) => fnCall.includes(n));
|
|
1536
|
+
const primaryName = binding.exportNames[0];
|
|
1537
|
+
const stubId = makeStubId(filePath, primaryName, isBuild);
|
|
1538
|
+
if (isHandle || isLocationState) {
|
|
1539
|
+
const rawArgs = code.slice(
|
|
1540
|
+
binding.callOpenParenPos + 1,
|
|
1541
|
+
binding.callCloseParenPos
|
|
1542
|
+
).replace(/\b_c\d*\s*=\s*/g, "");
|
|
1543
|
+
const canonicalName = isHandle ? "createHandle" : "createLocationState";
|
|
1544
|
+
const activeFnNames = isHandle ? handleFnNames : lsFnNames;
|
|
1545
|
+
let rawCallee = code.slice(
|
|
1546
|
+
binding.callExprStart,
|
|
1547
|
+
binding.callOpenParenPos
|
|
1548
|
+
);
|
|
1549
|
+
for (const alias of activeFnNames) {
|
|
1550
|
+
if (alias !== canonicalName && rawCallee.startsWith(alias)) {
|
|
1551
|
+
rawCallee = canonicalName + rawCallee.slice(alias.length);
|
|
1552
|
+
break;
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
if (isHandle) {
|
|
1556
|
+
const idParam = binding.argCount === 0 ? `undefined, "${stubId}"` : `, "${stubId}"`;
|
|
1557
|
+
lines.push(
|
|
1558
|
+
`export const ${primaryName} = ${rawCallee}(${rawArgs}${idParam});`
|
|
1559
|
+
);
|
|
1560
|
+
lines.push(`${primaryName}.$$id = "${stubId}";`);
|
|
1561
|
+
} else {
|
|
1562
|
+
lines.push(
|
|
1563
|
+
`export const ${primaryName} = ${rawCallee}(${rawArgs});`
|
|
1564
|
+
);
|
|
1565
|
+
lines.push(
|
|
1566
|
+
`${primaryName}.__rsc_ls_key = "__rsc_ls_${stubId}";`
|
|
1567
|
+
);
|
|
1568
|
+
}
|
|
1569
|
+
for (const name of binding.exportNames.slice(1)) {
|
|
1570
|
+
lines.push(`export const ${name} = ${primaryName};`);
|
|
1571
|
+
}
|
|
1572
|
+
} else {
|
|
1573
|
+
let brand = "loader";
|
|
1574
|
+
if (prerenderFnNames.some((n) => fnCall.includes(n))) {
|
|
1575
|
+
brand = PRERENDER_CONFIG.brand;
|
|
1576
|
+
} else if (staticFnNames.some((n) => fnCall.includes(n))) {
|
|
1577
|
+
brand = STATIC_CONFIG.brand;
|
|
1578
|
+
}
|
|
1579
|
+
lines.push(
|
|
1580
|
+
`export const ${primaryName} = { __brand: "${brand}", $$id: "${stubId}" };`
|
|
1581
|
+
);
|
|
1582
|
+
for (const name of binding.exportNames.slice(1)) {
|
|
1583
|
+
lines.push(`export const ${name} = ${primaryName};`);
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
return { code: lines.join("\n") + "\n", map: null };
|
|
1318
1588
|
}
|
|
1319
1589
|
}
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
filePath,
|
|
1329
|
-
isBuild
|
|
1330
|
-
);
|
|
1331
|
-
if (wholeFile) return wholeFile;
|
|
1332
|
-
const exprStubs = generateExprStubs(
|
|
1333
|
-
STATIC_CONFIG,
|
|
1334
|
-
bindings,
|
|
1335
|
-
code,
|
|
1336
|
-
filePath,
|
|
1337
|
-
id,
|
|
1338
|
-
isBuild
|
|
1339
|
-
);
|
|
1340
|
-
if (exprStubs) return exprStubs;
|
|
1341
|
-
}
|
|
1342
|
-
if (hasStaticHandlerCode && isRscEnv && isBuild) {
|
|
1343
|
-
const fnNames = getFnNames(STATIC_CONFIG.fnName);
|
|
1344
|
-
const exportNames = getBindings(code, fnNames).map(
|
|
1345
|
-
(b) => b.exportNames[0]
|
|
1346
|
-
);
|
|
1347
|
-
if (exportNames.length > 0) {
|
|
1348
|
-
staticHandlerModules.set(id, exportNames);
|
|
1590
|
+
if (hasStaticHandlerCode && isRscEnv && isBuild) {
|
|
1591
|
+
const fnNames = getFnNames(STATIC_CONFIG.fnName);
|
|
1592
|
+
const exportNames = getBindings(code, fnNames).map(
|
|
1593
|
+
(b) => b.exportNames[0]
|
|
1594
|
+
);
|
|
1595
|
+
if (exportNames.length > 0) {
|
|
1596
|
+
staticHandlerModules.set(id, exportNames);
|
|
1597
|
+
}
|
|
1349
1598
|
}
|
|
1599
|
+
const s = new MagicString4(code);
|
|
1600
|
+
if (hasLoaderCode) {
|
|
1601
|
+
const fnNames = getFnNames("createLoader");
|
|
1602
|
+
changed = transformLoaders(
|
|
1603
|
+
getBindings(code, fnNames),
|
|
1604
|
+
s,
|
|
1605
|
+
filePath,
|
|
1606
|
+
isBuild
|
|
1607
|
+
) || changed;
|
|
1608
|
+
}
|
|
1609
|
+
if (hasHandleCode) {
|
|
1610
|
+
const fnNames = getFnNames("createHandle");
|
|
1611
|
+
changed = transformHandles(
|
|
1612
|
+
getBindings(code, fnNames),
|
|
1613
|
+
s,
|
|
1614
|
+
code,
|
|
1615
|
+
filePath,
|
|
1616
|
+
isBuild
|
|
1617
|
+
) || changed;
|
|
1618
|
+
}
|
|
1619
|
+
if (hasLocationStateCode) {
|
|
1620
|
+
const fnNames = getFnNames("createLocationState");
|
|
1621
|
+
changed = transformLocationState(
|
|
1622
|
+
getBindings(code, fnNames),
|
|
1623
|
+
s,
|
|
1624
|
+
filePath,
|
|
1625
|
+
isBuild
|
|
1626
|
+
) || changed;
|
|
1627
|
+
}
|
|
1628
|
+
if (hasPrerenderHandlerCode) {
|
|
1629
|
+
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1630
|
+
const bindings = getBindings(code, fnNames);
|
|
1631
|
+
if (isRscEnv) {
|
|
1632
|
+
changed = transformHandlerIds(
|
|
1633
|
+
PRERENDER_CONFIG,
|
|
1634
|
+
bindings,
|
|
1635
|
+
s,
|
|
1636
|
+
filePath,
|
|
1637
|
+
isBuild
|
|
1638
|
+
) || changed;
|
|
1639
|
+
} else {
|
|
1640
|
+
changed = stubHandlerExprs(
|
|
1641
|
+
PRERENDER_CONFIG,
|
|
1642
|
+
bindings,
|
|
1643
|
+
s,
|
|
1644
|
+
filePath,
|
|
1645
|
+
isBuild
|
|
1646
|
+
) || changed;
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
if (hasStaticHandlerCode) {
|
|
1650
|
+
const fnNames = getFnNames(STATIC_CONFIG.fnName);
|
|
1651
|
+
const bindings = getBindings(code, fnNames);
|
|
1652
|
+
if (isRscEnv) {
|
|
1653
|
+
changed = transformHandlerIds(
|
|
1654
|
+
STATIC_CONFIG,
|
|
1655
|
+
bindings,
|
|
1656
|
+
s,
|
|
1657
|
+
filePath,
|
|
1658
|
+
isBuild
|
|
1659
|
+
) || changed;
|
|
1660
|
+
} else {
|
|
1661
|
+
changed = stubHandlerExprs(STATIC_CONFIG, bindings, s, filePath, isBuild) || changed;
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
if (!changed) return;
|
|
1665
|
+
return {
|
|
1666
|
+
code: s.toString(),
|
|
1667
|
+
map: s.generateMap({ source: id, includeContent: true })
|
|
1668
|
+
};
|
|
1669
|
+
} finally {
|
|
1670
|
+
counter?.record(id, performance.now() - __t0);
|
|
1350
1671
|
}
|
|
1351
|
-
const s = new MagicString4(code);
|
|
1352
|
-
if (hasLoaderCode) {
|
|
1353
|
-
const fnNames = getFnNames("createLoader");
|
|
1354
|
-
changed = transformLoaders(getBindings(code, fnNames), s, filePath, isBuild) || changed;
|
|
1355
|
-
}
|
|
1356
|
-
if (hasHandleCode) {
|
|
1357
|
-
const fnNames = getFnNames("createHandle");
|
|
1358
|
-
changed = transformHandles(
|
|
1359
|
-
getBindings(code, fnNames),
|
|
1360
|
-
s,
|
|
1361
|
-
code,
|
|
1362
|
-
filePath,
|
|
1363
|
-
isBuild
|
|
1364
|
-
) || changed;
|
|
1365
|
-
}
|
|
1366
|
-
if (hasLocationStateCode) {
|
|
1367
|
-
const fnNames = getFnNames("createLocationState");
|
|
1368
|
-
changed = transformLocationState(
|
|
1369
|
-
getBindings(code, fnNames),
|
|
1370
|
-
s,
|
|
1371
|
-
filePath,
|
|
1372
|
-
isBuild
|
|
1373
|
-
) || changed;
|
|
1374
|
-
}
|
|
1375
|
-
if (hasPrerenderHandlerCode && isRscEnv) {
|
|
1376
|
-
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1377
|
-
changed = transformHandlerIds(
|
|
1378
|
-
PRERENDER_CONFIG,
|
|
1379
|
-
getBindings(code, fnNames),
|
|
1380
|
-
s,
|
|
1381
|
-
filePath,
|
|
1382
|
-
isBuild
|
|
1383
|
-
) || changed;
|
|
1384
|
-
}
|
|
1385
|
-
if (hasStaticHandlerCode && isRscEnv) {
|
|
1386
|
-
const fnNames = getFnNames(STATIC_CONFIG.fnName);
|
|
1387
|
-
changed = transformHandlerIds(
|
|
1388
|
-
STATIC_CONFIG,
|
|
1389
|
-
getBindings(code, fnNames),
|
|
1390
|
-
s,
|
|
1391
|
-
filePath,
|
|
1392
|
-
isBuild
|
|
1393
|
-
) || changed;
|
|
1394
|
-
}
|
|
1395
|
-
if (!changed) return;
|
|
1396
|
-
return {
|
|
1397
|
-
code: s.toString(),
|
|
1398
|
-
map: s.generateMap({ source: id, includeContent: true })
|
|
1399
|
-
};
|
|
1400
1672
|
}
|
|
1401
1673
|
};
|
|
1402
1674
|
}
|
|
@@ -1404,12 +1676,14 @@ ${lazyImports.join(",\n")}
|
|
|
1404
1676
|
// src/vite/plugins/use-cache-transform.ts
|
|
1405
1677
|
import path5 from "node:path";
|
|
1406
1678
|
import MagicString5 from "magic-string";
|
|
1679
|
+
var debug4 = createRangoDebugger(NS.transform);
|
|
1407
1680
|
var CACHE_RUNTIME_IMPORT = "@rangojs/router/cache-runtime";
|
|
1408
1681
|
var LAYOUT_TEMPLATE_PATTERN = /\/(layout|template)\.(tsx?|jsx?)$/;
|
|
1409
1682
|
function useCacheTransform() {
|
|
1410
1683
|
let projectRoot = "";
|
|
1411
1684
|
let isBuild = false;
|
|
1412
1685
|
let rscTransforms = null;
|
|
1686
|
+
const counter = createCounter(debug4, "use-cache");
|
|
1413
1687
|
return {
|
|
1414
1688
|
name: "@rangojs/router:use-cache",
|
|
1415
1689
|
enforce: "post",
|
|
@@ -1417,53 +1691,61 @@ function useCacheTransform() {
|
|
|
1417
1691
|
projectRoot = config.root;
|
|
1418
1692
|
isBuild = config.command === "build";
|
|
1419
1693
|
},
|
|
1694
|
+
buildEnd() {
|
|
1695
|
+
counter?.flush();
|
|
1696
|
+
},
|
|
1420
1697
|
async transform(code, id) {
|
|
1421
1698
|
if (this.environment?.name !== "rsc") return;
|
|
1422
1699
|
if (!code.includes("use cache")) return;
|
|
1423
1700
|
if (id.includes("/node_modules/") || id.startsWith("\0")) return;
|
|
1424
1701
|
if (!/\.(tsx?|jsx?|mjs)$/.test(id)) return;
|
|
1425
|
-
|
|
1702
|
+
const start = counter ? performance.now() : 0;
|
|
1703
|
+
try {
|
|
1704
|
+
if (!rscTransforms) {
|
|
1705
|
+
try {
|
|
1706
|
+
rscTransforms = await import("@vitejs/plugin-rsc/transforms");
|
|
1707
|
+
} catch {
|
|
1708
|
+
return;
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
const {
|
|
1712
|
+
hasDirective,
|
|
1713
|
+
transformWrapExport,
|
|
1714
|
+
transformHoistInlineDirective
|
|
1715
|
+
} = rscTransforms;
|
|
1716
|
+
let ast;
|
|
1426
1717
|
try {
|
|
1427
|
-
|
|
1718
|
+
const { parseAst: parseAst4 } = await import("vite");
|
|
1719
|
+
ast = parseAst4(code);
|
|
1428
1720
|
} catch {
|
|
1429
1721
|
return;
|
|
1430
1722
|
}
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
hasDirective,
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
const isLayoutOrTemplate = LAYOUT_TEMPLATE_PATTERN.test(id);
|
|
1446
|
-
if (hasDirective(ast.body, "use cache")) {
|
|
1447
|
-
return transformFileLevelUseCache(
|
|
1723
|
+
const filePath = normalizePath(path5.relative(projectRoot, id));
|
|
1724
|
+
const isLayoutOrTemplate = LAYOUT_TEMPLATE_PATTERN.test(id);
|
|
1725
|
+
if (hasDirective(ast.body, "use cache")) {
|
|
1726
|
+
return transformFileLevelUseCache(
|
|
1727
|
+
code,
|
|
1728
|
+
ast,
|
|
1729
|
+
filePath,
|
|
1730
|
+
id,
|
|
1731
|
+
isBuild,
|
|
1732
|
+
isLayoutOrTemplate,
|
|
1733
|
+
transformWrapExport
|
|
1734
|
+
);
|
|
1735
|
+
}
|
|
1736
|
+
const functionResult = transformFunctionLevelUseCache(
|
|
1448
1737
|
code,
|
|
1449
1738
|
ast,
|
|
1450
1739
|
filePath,
|
|
1451
1740
|
id,
|
|
1452
1741
|
isBuild,
|
|
1453
|
-
|
|
1454
|
-
transformWrapExport
|
|
1742
|
+
transformHoistInlineDirective
|
|
1455
1743
|
);
|
|
1744
|
+
warnOnNearMissDirectives(ast, id, this.warn.bind(this));
|
|
1745
|
+
if (functionResult) return functionResult;
|
|
1746
|
+
} finally {
|
|
1747
|
+
counter?.record(id, performance.now() - start);
|
|
1456
1748
|
}
|
|
1457
|
-
const functionResult = transformFunctionLevelUseCache(
|
|
1458
|
-
code,
|
|
1459
|
-
ast,
|
|
1460
|
-
filePath,
|
|
1461
|
-
id,
|
|
1462
|
-
isBuild,
|
|
1463
|
-
transformHoistInlineDirective
|
|
1464
|
-
);
|
|
1465
|
-
warnOnNearMissDirectives(ast, id, this.warn.bind(this));
|
|
1466
|
-
if (functionResult) return functionResult;
|
|
1467
1749
|
}
|
|
1468
1750
|
};
|
|
1469
1751
|
}
|
|
@@ -1586,6 +1868,7 @@ function warnOnNearMissDirectives(ast, fileId, warn) {
|
|
|
1586
1868
|
}
|
|
1587
1869
|
|
|
1588
1870
|
// src/vite/plugins/client-ref-dedup.ts
|
|
1871
|
+
var debug5 = createRangoDebugger(NS.transform);
|
|
1589
1872
|
var CLIENT_IN_SERVER_PROXY_PREFIX = "virtual:vite-rsc/client-in-server-package-proxy/";
|
|
1590
1873
|
function extractPackageName(absolutePath) {
|
|
1591
1874
|
const marker = "/node_modules/";
|
|
@@ -1602,6 +1885,7 @@ function extractPackageName(absolutePath) {
|
|
|
1602
1885
|
}
|
|
1603
1886
|
function clientRefDedup() {
|
|
1604
1887
|
let clientExclude = [];
|
|
1888
|
+
const dedupedPackages = /* @__PURE__ */ new Set();
|
|
1605
1889
|
return {
|
|
1606
1890
|
name: "@rangojs/router:client-ref-dedup",
|
|
1607
1891
|
enforce: "pre",
|
|
@@ -1610,6 +1894,15 @@ function clientRefDedup() {
|
|
|
1610
1894
|
const clientEnv = config.environments?.["client"];
|
|
1611
1895
|
clientExclude = clientEnv?.optimizeDeps?.exclude ?? config.optimizeDeps?.exclude ?? [];
|
|
1612
1896
|
},
|
|
1897
|
+
buildEnd() {
|
|
1898
|
+
if (debug5 && dedupedPackages.size > 0) {
|
|
1899
|
+
debug5(
|
|
1900
|
+
"client-ref-dedup: redirected %d package(s) (%s)",
|
|
1901
|
+
dedupedPackages.size,
|
|
1902
|
+
[...dedupedPackages].join(",")
|
|
1903
|
+
);
|
|
1904
|
+
}
|
|
1905
|
+
},
|
|
1613
1906
|
resolveId(source, importer, options) {
|
|
1614
1907
|
if (this.environment?.name !== "client") return;
|
|
1615
1908
|
if (!importer?.includes(CLIENT_IN_SERVER_PROXY_PREFIX)) return;
|
|
@@ -1618,6 +1911,7 @@ function clientRefDedup() {
|
|
|
1618
1911
|
const packageName = extractPackageName(source);
|
|
1619
1912
|
if (!packageName) return;
|
|
1620
1913
|
if (clientExclude.includes(packageName)) return;
|
|
1914
|
+
if (debug5) dedupedPackages.add(packageName);
|
|
1621
1915
|
return `\0rango:dedup/${packageName}`;
|
|
1622
1916
|
},
|
|
1623
1917
|
load(id) {
|
|
@@ -1740,12 +2034,13 @@ function getVirtualVersionContent(version) {
|
|
|
1740
2034
|
|
|
1741
2035
|
// src/vite/utils/package-resolution.ts
|
|
1742
2036
|
import { existsSync } from "node:fs";
|
|
2037
|
+
import { createRequire } from "node:module";
|
|
1743
2038
|
import { resolve } from "node:path";
|
|
1744
2039
|
|
|
1745
2040
|
// package.json
|
|
1746
2041
|
var package_default = {
|
|
1747
2042
|
name: "@rangojs/router",
|
|
1748
|
-
version: "0.0.0-experimental.
|
|
2043
|
+
version: "0.0.0-experimental.89",
|
|
1749
2044
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
1750
2045
|
keywords: [
|
|
1751
2046
|
"react",
|
|
@@ -1878,22 +2173,24 @@ var package_default = {
|
|
|
1878
2173
|
tag: "experimental"
|
|
1879
2174
|
},
|
|
1880
2175
|
scripts: {
|
|
1881
|
-
build: "pnpm dlx esbuild src/vite/index.ts --bundle --format=esm --outfile=dist/vite/index.js --platform=node --packages=external && pnpm dlx esbuild src/bin/rango.ts --bundle --format=esm --outfile=dist/bin/rango.js --platform=node --packages=external --banner:js='#!/usr/bin/env node' && chmod +x dist/bin/rango.js",
|
|
2176
|
+
build: "pnpm dlx esbuild src/vite/index.ts --bundle --format=esm --outfile=dist/vite/index.js --platform=node --packages=external && mkdir -p dist/vite/plugins && cp src/vite/plugins/cloudflare-protocol-loader-hook.mjs dist/vite/plugins/cloudflare-protocol-loader-hook.mjs && pnpm dlx esbuild src/bin/rango.ts --bundle --format=esm --outfile=dist/bin/rango.js --platform=node --packages=external --banner:js='#!/usr/bin/env node' && chmod +x dist/bin/rango.js",
|
|
1882
2177
|
prepublishOnly: "pnpm build",
|
|
1883
|
-
typecheck: "tsc --noEmit",
|
|
2178
|
+
typecheck: "tsc --noEmit && tsc -p tsconfig.strict-check.json --noEmit",
|
|
1884
2179
|
test: "playwright test",
|
|
1885
2180
|
"test:ui": "playwright test --ui",
|
|
1886
2181
|
"test:unit": "vitest run",
|
|
1887
2182
|
"test:unit:watch": "vitest"
|
|
1888
2183
|
},
|
|
1889
2184
|
dependencies: {
|
|
1890
|
-
"@vitejs/plugin-rsc": "^0.5.
|
|
2185
|
+
"@vitejs/plugin-rsc": "^0.5.23",
|
|
2186
|
+
debug: "^4.4.1",
|
|
1891
2187
|
"magic-string": "^0.30.17",
|
|
1892
2188
|
picomatch: "^4.0.3",
|
|
1893
2189
|
"rsc-html-stream": "^0.0.7"
|
|
1894
2190
|
},
|
|
1895
2191
|
devDependencies: {
|
|
1896
2192
|
"@playwright/test": "^1.49.1",
|
|
2193
|
+
"@types/debug": "^4.1.12",
|
|
1897
2194
|
"@types/node": "^24.10.1",
|
|
1898
2195
|
"@types/react": "catalog:",
|
|
1899
2196
|
"@types/react-dom": "catalog:",
|
|
@@ -1907,7 +2204,7 @@ var package_default = {
|
|
|
1907
2204
|
},
|
|
1908
2205
|
peerDependencies: {
|
|
1909
2206
|
"@cloudflare/vite-plugin": "^1.25.0",
|
|
1910
|
-
"@vitejs/plugin-rsc": "^0.5.
|
|
2207
|
+
"@vitejs/plugin-rsc": "^0.5.23",
|
|
1911
2208
|
react: "^18.0.0 || ^19.0.0",
|
|
1912
2209
|
vite: "^7.3.0"
|
|
1913
2210
|
},
|
|
@@ -1922,6 +2219,7 @@ var package_default = {
|
|
|
1922
2219
|
};
|
|
1923
2220
|
|
|
1924
2221
|
// src/vite/utils/package-resolution.ts
|
|
2222
|
+
var require2 = createRequire(import.meta.url);
|
|
1925
2223
|
var VIRTUAL_PACKAGE_NAME = "@rangojs/router";
|
|
1926
2224
|
function getPublishedPackageName() {
|
|
1927
2225
|
return package_default.name;
|
|
@@ -1962,6 +2260,20 @@ function getPackageAliases() {
|
|
|
1962
2260
|
}
|
|
1963
2261
|
return aliases;
|
|
1964
2262
|
}
|
|
2263
|
+
function getVendorAliases() {
|
|
2264
|
+
const specs = [
|
|
2265
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
|
|
2266
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge"
|
|
2267
|
+
];
|
|
2268
|
+
const aliases = {};
|
|
2269
|
+
for (const spec of specs) {
|
|
2270
|
+
try {
|
|
2271
|
+
aliases[spec] = require2.resolve(spec);
|
|
2272
|
+
} catch {
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2275
|
+
return aliases;
|
|
2276
|
+
}
|
|
1965
2277
|
|
|
1966
2278
|
// src/build/route-types/param-extraction.ts
|
|
1967
2279
|
function extractParamsFromPattern(pattern) {
|
|
@@ -2859,6 +3171,7 @@ import * as Vite from "vite";
|
|
|
2859
3171
|
|
|
2860
3172
|
// src/vite/plugins/performance-tracks.ts
|
|
2861
3173
|
import { readFile } from "node:fs/promises";
|
|
3174
|
+
var debug6 = createRangoDebugger(NS.transform);
|
|
2862
3175
|
var RSDW_PATCH_RE = /((?:var|let|const)\s+\w+\s*=\s*root\._children\s*,\s*(\w+)\s*=\s*root\._debugInfo\s*[;,])/;
|
|
2863
3176
|
function buildPatchReplacement(match, debugInfoVar) {
|
|
2864
3177
|
return `${match}
|
|
@@ -2900,19 +3213,23 @@ function performanceTracksOptimizeDepsPlugin() {
|
|
|
2900
3213
|
};
|
|
2901
3214
|
}
|
|
2902
3215
|
function performanceTracksPlugin() {
|
|
3216
|
+
const counter = createCounter(debug6, "performance-tracks");
|
|
2903
3217
|
return {
|
|
2904
3218
|
name: "@rangojs/router:performance-tracks",
|
|
3219
|
+
buildEnd() {
|
|
3220
|
+
counter?.flush();
|
|
3221
|
+
},
|
|
2905
3222
|
transform(code, id) {
|
|
2906
3223
|
if (!id.includes("react-server-dom") || !id.includes("client")) return;
|
|
2907
|
-
const
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
);
|
|
2915
|
-
|
|
3224
|
+
const start = counter ? performance.now() : 0;
|
|
3225
|
+
try {
|
|
3226
|
+
const patched = patchRsdwClientDebugInfoRecovery(code);
|
|
3227
|
+
if (!patched.debugInfoVar) return;
|
|
3228
|
+
debug6?.("patched RSDW client (var: %s)", patched.debugInfoVar);
|
|
3229
|
+
return patched.code;
|
|
3230
|
+
} finally {
|
|
3231
|
+
counter?.record(id, performance.now() - start);
|
|
3232
|
+
}
|
|
2916
3233
|
}
|
|
2917
3234
|
};
|
|
2918
3235
|
}
|
|
@@ -3083,6 +3400,7 @@ function createVersionInjectorPlugin(rscEntryPath) {
|
|
|
3083
3400
|
}
|
|
3084
3401
|
|
|
3085
3402
|
// src/vite/plugins/cjs-to-esm.ts
|
|
3403
|
+
var debug7 = createRangoDebugger(NS.transform);
|
|
3086
3404
|
function createCjsToEsmPlugin() {
|
|
3087
3405
|
return {
|
|
3088
3406
|
name: "@rangojs/router:cjs-to-esm",
|
|
@@ -3092,6 +3410,7 @@ function createCjsToEsmPlugin() {
|
|
|
3092
3410
|
if (cleanId.includes("vendor/react-server-dom/client.browser.js") || cleanId.includes("vendor\\react-server-dom\\client.browser.js")) {
|
|
3093
3411
|
const isProd = process.env.NODE_ENV === "production";
|
|
3094
3412
|
const cjsFile = isProd ? "./cjs/react-server-dom-webpack-client.browser.production.js" : "./cjs/react-server-dom-webpack-client.browser.development.js";
|
|
3413
|
+
debug7?.("cjs-to-esm entry redirect %s", id);
|
|
3095
3414
|
return {
|
|
3096
3415
|
code: `export * from "${cjsFile}";`,
|
|
3097
3416
|
map: null
|
|
@@ -3127,6 +3446,7 @@ function createCjsToEsmPlugin() {
|
|
|
3127
3446
|
"export const $1 ="
|
|
3128
3447
|
);
|
|
3129
3448
|
transformed = license + "\n" + transformed;
|
|
3449
|
+
debug7?.("cjs-to-esm body rewrite %s", id);
|
|
3130
3450
|
return {
|
|
3131
3451
|
code: transformed,
|
|
3132
3452
|
map: null
|
|
@@ -3141,7 +3461,7 @@ function createCjsToEsmPlugin() {
|
|
|
3141
3461
|
import { createServer as createViteServer } from "vite";
|
|
3142
3462
|
import { resolve as resolve8 } from "node:path";
|
|
3143
3463
|
import { readFileSync as readFileSync6 } from "node:fs";
|
|
3144
|
-
import { createRequire } from "node:module";
|
|
3464
|
+
import { createRequire as createRequire2, register } from "node:module";
|
|
3145
3465
|
import { pathToFileURL } from "node:url";
|
|
3146
3466
|
|
|
3147
3467
|
// src/vite/plugins/virtual-stub-plugin.ts
|
|
@@ -3168,9 +3488,117 @@ function createVirtualStubPlugin() {
|
|
|
3168
3488
|
};
|
|
3169
3489
|
}
|
|
3170
3490
|
|
|
3491
|
+
// src/vite/plugins/cloudflare-protocol-stub.ts
|
|
3492
|
+
var VIRTUAL_PREFIX = "virtual:rango-cloudflare-stub-";
|
|
3493
|
+
var NULL_PREFIX = "\0" + VIRTUAL_PREFIX;
|
|
3494
|
+
var CF_PREFIX = "cloudflare:";
|
|
3495
|
+
var BUILD_ENV_GLOBAL_KEY = "__rango_build_env__";
|
|
3496
|
+
var SOURCE_EXT_RE = /\.[mc]?[jt]sx?$/;
|
|
3497
|
+
var IMPORT_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
3498
|
+
"ImportDeclaration",
|
|
3499
|
+
"ImportExpression",
|
|
3500
|
+
"ExportNamedDeclaration",
|
|
3501
|
+
"ExportAllDeclaration"
|
|
3502
|
+
]);
|
|
3503
|
+
var STUBS = {
|
|
3504
|
+
"cloudflare:workers": `
|
|
3505
|
+
export class DurableObject { constructor(_ctx, _env) {} }
|
|
3506
|
+
export class WorkerEntrypoint { constructor(_ctx, _env) {} }
|
|
3507
|
+
export class WorkflowEntrypoint { constructor(_ctx, _env) {} }
|
|
3508
|
+
export class RpcTarget {}
|
|
3509
|
+
export const env = globalThis[${JSON.stringify(BUILD_ENV_GLOBAL_KEY)}] ?? {};
|
|
3510
|
+
export default {};
|
|
3511
|
+
`,
|
|
3512
|
+
"cloudflare:email": `
|
|
3513
|
+
export class EmailMessage { constructor(_from, _to, _raw) {} }
|
|
3514
|
+
export default {};
|
|
3515
|
+
`,
|
|
3516
|
+
"cloudflare:sockets": `
|
|
3517
|
+
export function connect() { return {}; }
|
|
3518
|
+
export default {};
|
|
3519
|
+
`,
|
|
3520
|
+
"cloudflare:workflows": `
|
|
3521
|
+
export class NonRetryableError extends Error {
|
|
3522
|
+
constructor(message, name) { super(message); this.name = name ?? "NonRetryableError"; }
|
|
3523
|
+
}
|
|
3524
|
+
export default {};
|
|
3525
|
+
`
|
|
3526
|
+
};
|
|
3527
|
+
var FALLBACK_STUB = `export default {};
|
|
3528
|
+
`;
|
|
3529
|
+
function createCloudflareProtocolStubPlugin() {
|
|
3530
|
+
return {
|
|
3531
|
+
name: "@rangojs/router:cloudflare-protocol-stub",
|
|
3532
|
+
transform(code, id) {
|
|
3533
|
+
const cleanId = id.split("?")[0] ?? id;
|
|
3534
|
+
if (!SOURCE_EXT_RE.test(cleanId)) return null;
|
|
3535
|
+
if (!code.includes(CF_PREFIX)) return null;
|
|
3536
|
+
let ast;
|
|
3537
|
+
try {
|
|
3538
|
+
ast = this.parse(code);
|
|
3539
|
+
} catch {
|
|
3540
|
+
return null;
|
|
3541
|
+
}
|
|
3542
|
+
const hits = [];
|
|
3543
|
+
walk(ast, (node) => {
|
|
3544
|
+
if (!IMPORT_NODE_TYPES.has(node.type)) return;
|
|
3545
|
+
const source = node.source;
|
|
3546
|
+
if (!source || source.type !== "Literal") return;
|
|
3547
|
+
if (typeof source.value !== "string") return;
|
|
3548
|
+
if (!source.value.startsWith(CF_PREFIX)) return;
|
|
3549
|
+
if (typeof source.start !== "number" || typeof source.end !== "number")
|
|
3550
|
+
return;
|
|
3551
|
+
hits.push({
|
|
3552
|
+
start: source.start,
|
|
3553
|
+
end: source.end,
|
|
3554
|
+
value: source.value
|
|
3555
|
+
});
|
|
3556
|
+
});
|
|
3557
|
+
if (hits.length === 0) return null;
|
|
3558
|
+
hits.sort((a, b) => b.start - a.start);
|
|
3559
|
+
let out = code;
|
|
3560
|
+
for (const hit of hits) {
|
|
3561
|
+
const submodule = hit.value.slice(CF_PREFIX.length);
|
|
3562
|
+
const quote = code[hit.start] === "'" ? "'" : '"';
|
|
3563
|
+
out = out.slice(0, hit.start) + quote + VIRTUAL_PREFIX + submodule + quote + out.slice(hit.end);
|
|
3564
|
+
}
|
|
3565
|
+
return { code: out, map: null };
|
|
3566
|
+
},
|
|
3567
|
+
resolveId(id) {
|
|
3568
|
+
if (id.startsWith(VIRTUAL_PREFIX)) {
|
|
3569
|
+
return "\0" + id;
|
|
3570
|
+
}
|
|
3571
|
+
return null;
|
|
3572
|
+
},
|
|
3573
|
+
load(id) {
|
|
3574
|
+
if (!id.startsWith(NULL_PREFIX)) return null;
|
|
3575
|
+
const submodule = id.slice(NULL_PREFIX.length);
|
|
3576
|
+
const specifier = CF_PREFIX + submodule;
|
|
3577
|
+
return STUBS[specifier] ?? FALLBACK_STUB;
|
|
3578
|
+
}
|
|
3579
|
+
};
|
|
3580
|
+
}
|
|
3581
|
+
function walk(node, visit) {
|
|
3582
|
+
if (!node || typeof node !== "object") return;
|
|
3583
|
+
if (Array.isArray(node)) {
|
|
3584
|
+
for (const child of node) walk(child, visit);
|
|
3585
|
+
return;
|
|
3586
|
+
}
|
|
3587
|
+
const n = node;
|
|
3588
|
+
if (typeof n.type !== "string") return;
|
|
3589
|
+
visit(n);
|
|
3590
|
+
for (const key in n) {
|
|
3591
|
+
if (key === "loc" || key === "start" || key === "end" || key === "range") {
|
|
3592
|
+
continue;
|
|
3593
|
+
}
|
|
3594
|
+
walk(n[key], visit);
|
|
3595
|
+
}
|
|
3596
|
+
}
|
|
3597
|
+
|
|
3171
3598
|
// src/vite/plugins/client-ref-hashing.ts
|
|
3172
3599
|
import { relative } from "node:path";
|
|
3173
3600
|
import { createHash as createHash2 } from "node:crypto";
|
|
3601
|
+
var debug8 = createRangoDebugger(NS.transform);
|
|
3174
3602
|
var CLIENT_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-package-proxy/";
|
|
3175
3603
|
var CLIENT_IN_SERVER_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-in-server-package-proxy/";
|
|
3176
3604
|
var FS_PREFIX = "/@fs/";
|
|
@@ -3209,6 +3637,7 @@ function transformClientRefs(code, projectRoot) {
|
|
|
3209
3637
|
return hasReplacement ? result : null;
|
|
3210
3638
|
}
|
|
3211
3639
|
function hashClientRefs(projectRoot) {
|
|
3640
|
+
const counter = createCounter(debug8, "hash-client-refs");
|
|
3212
3641
|
return {
|
|
3213
3642
|
name: "@rangojs/router:hash-client-refs",
|
|
3214
3643
|
// Run after the RSC plugin's transform (default enforce is normal)
|
|
@@ -3216,10 +3645,18 @@ function hashClientRefs(projectRoot) {
|
|
|
3216
3645
|
applyToEnvironment(env) {
|
|
3217
3646
|
return env.name === "rsc";
|
|
3218
3647
|
},
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3648
|
+
buildEnd() {
|
|
3649
|
+
counter?.flush();
|
|
3650
|
+
},
|
|
3651
|
+
transform(code, id) {
|
|
3652
|
+
const start = counter ? performance.now() : 0;
|
|
3653
|
+
try {
|
|
3654
|
+
const result = transformClientRefs(code, projectRoot);
|
|
3655
|
+
if (result === null) return;
|
|
3656
|
+
return { code: result, map: null };
|
|
3657
|
+
} finally {
|
|
3658
|
+
counter?.record(id, performance.now() - start);
|
|
3659
|
+
}
|
|
3223
3660
|
}
|
|
3224
3661
|
};
|
|
3225
3662
|
}
|
|
@@ -3461,11 +3898,19 @@ function substituteRouteParams(pattern, params, encode = encodeURIComponent) {
|
|
|
3461
3898
|
let hadOmittedOptional = false;
|
|
3462
3899
|
for (const [key, value] of Object.entries(params)) {
|
|
3463
3900
|
const escaped = escapeRegExp2(key);
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3901
|
+
if (value === "") {
|
|
3902
|
+
result = result.replace(
|
|
3903
|
+
new RegExp(`:${escaped}(\\([^)]*\\))?(?!\\?)`),
|
|
3904
|
+
""
|
|
3905
|
+
);
|
|
3906
|
+
result = result.replace(`*${key}`, "");
|
|
3907
|
+
} else {
|
|
3908
|
+
result = result.replace(
|
|
3909
|
+
new RegExp(`:${escaped}(\\([^)]*\\))?\\??`),
|
|
3910
|
+
encode(value)
|
|
3911
|
+
);
|
|
3912
|
+
result = result.replace(`*${key}`, encode(value));
|
|
3913
|
+
}
|
|
3469
3914
|
}
|
|
3470
3915
|
result = result.replace(/:([a-zA-Z_][a-zA-Z0-9_]*)(\([^)]*\))?\?/g, () => {
|
|
3471
3916
|
hadOmittedOptional = true;
|
|
@@ -3571,8 +4016,14 @@ function copyStagedBuildAssets(projectRoot, fileNames) {
|
|
|
3571
4016
|
}
|
|
3572
4017
|
|
|
3573
4018
|
// src/vite/discovery/prerender-collection.ts
|
|
4019
|
+
var debug9 = createRangoDebugger(NS.prerender);
|
|
3574
4020
|
async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
3575
4021
|
if (!state.opts?.enableBuildPrerender || !state.isBuildMode) return;
|
|
4022
|
+
const overallStart = debug9 ? performance.now() : 0;
|
|
4023
|
+
debug9?.(
|
|
4024
|
+
"expandPrerenderRoutes: start (%d router manifest(s))",
|
|
4025
|
+
allManifests.length
|
|
4026
|
+
);
|
|
3576
4027
|
const entries = [];
|
|
3577
4028
|
const allRoutes = {};
|
|
3578
4029
|
for (const { manifest: m } of allManifests) {
|
|
@@ -3584,100 +4035,151 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3584
4035
|
if (!params) return pattern;
|
|
3585
4036
|
return substituteRouteParams(pattern, params);
|
|
3586
4037
|
};
|
|
4038
|
+
let resolvedRoutes = 0;
|
|
4039
|
+
let totalDynamic = 0;
|
|
3587
4040
|
for (const { manifest } of allManifests) {
|
|
3588
4041
|
if (!manifest.prerenderRoutes) continue;
|
|
3589
|
-
const defs = manifest._prerenderDefs || {};
|
|
3590
|
-
const passthroughSet = new Set(manifest.passthroughRoutes || []);
|
|
3591
4042
|
for (const routeName of manifest.prerenderRoutes) {
|
|
3592
4043
|
const pattern = manifest.routeManifest[routeName];
|
|
3593
|
-
if (
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
const
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
4044
|
+
if (pattern && (pattern.includes(":") || pattern.includes("*"))) {
|
|
4045
|
+
totalDynamic++;
|
|
4046
|
+
}
|
|
4047
|
+
}
|
|
4048
|
+
}
|
|
4049
|
+
const paramsStart = performance.now();
|
|
4050
|
+
const progressInterval = totalDynamic > 0 ? setInterval(() => {
|
|
4051
|
+
const elapsed = ((performance.now() - paramsStart) / 1e3).toFixed(1);
|
|
4052
|
+
console.log(
|
|
4053
|
+
`[rsc-router] Resolving prerender params... ${resolvedRoutes}/${totalDynamic} routes (${elapsed}s)`
|
|
4054
|
+
);
|
|
4055
|
+
}, 5e3) : void 0;
|
|
4056
|
+
try {
|
|
4057
|
+
for (const { manifest } of allManifests) {
|
|
4058
|
+
if (!manifest.prerenderRoutes) continue;
|
|
4059
|
+
const defs = manifest._prerenderDefs || {};
|
|
4060
|
+
const passthroughSet = new Set(manifest.passthroughRoutes || []);
|
|
4061
|
+
for (const routeName of manifest.prerenderRoutes) {
|
|
4062
|
+
const pattern = manifest.routeManifest[routeName];
|
|
4063
|
+
if (!pattern) continue;
|
|
4064
|
+
const def = defs[routeName];
|
|
4065
|
+
const isPassthroughRoute = passthroughSet.has(routeName);
|
|
4066
|
+
const hasDynamic = pattern.includes(":") || pattern.includes("*");
|
|
4067
|
+
if (!hasDynamic) {
|
|
4068
|
+
entries.push({
|
|
4069
|
+
urlPath: pattern.replace(/\/$/, "") || "/",
|
|
4070
|
+
routeName,
|
|
4071
|
+
concurrency: 1,
|
|
4072
|
+
isPassthroughRoute
|
|
4073
|
+
});
|
|
4074
|
+
} else {
|
|
4075
|
+
if (def?.getParams) {
|
|
4076
|
+
const getParamsStart = debug9 ? performance.now() : 0;
|
|
4077
|
+
try {
|
|
4078
|
+
const buildVars = {};
|
|
4079
|
+
const buildEnv = state.resolvedBuildEnv;
|
|
4080
|
+
const getParamsCtx = {
|
|
4081
|
+
build: true,
|
|
4082
|
+
dev: !state.isBuildMode,
|
|
4083
|
+
set: ((keyOrVar, value) => {
|
|
4084
|
+
contextSet(buildVars, keyOrVar, value);
|
|
4085
|
+
}),
|
|
4086
|
+
reverse: getParamsReverse,
|
|
4087
|
+
get env() {
|
|
4088
|
+
if (buildEnv !== void 0) return buildEnv;
|
|
4089
|
+
throw new Error(
|
|
4090
|
+
"[rsc-router] ctx.env is not available during build-time getParams(). Configure buildEnv in your rango() plugin options to enable build-time env access."
|
|
4091
|
+
);
|
|
3636
4092
|
}
|
|
3637
|
-
}
|
|
3638
|
-
|
|
3639
|
-
|
|
4093
|
+
};
|
|
4094
|
+
const paramsList = await def.getParams(getParamsCtx);
|
|
4095
|
+
debug9?.(
|
|
4096
|
+
"getParams %s -> %d params (%sms)",
|
|
3640
4097
|
routeName,
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
isPassthroughRoute
|
|
3644
|
-
});
|
|
3645
|
-
}
|
|
3646
|
-
} catch (err) {
|
|
3647
|
-
if (err.name === "Skip") {
|
|
3648
|
-
console.log(
|
|
3649
|
-
`[rsc-router] SKIP route "${routeName}" - ${err.message}`
|
|
4098
|
+
paramsList.length,
|
|
4099
|
+
(performance.now() - getParamsStart).toFixed(1)
|
|
3650
4100
|
);
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
4101
|
+
const concurrency = def.options?.concurrency ?? 1;
|
|
4102
|
+
const hasBuildVars = Object.keys(buildVars).length > 0 || Object.getOwnPropertySymbols(buildVars).length > 0;
|
|
4103
|
+
for (const params of paramsList) {
|
|
4104
|
+
let url = substituteRouteParams(
|
|
4105
|
+
pattern,
|
|
4106
|
+
params,
|
|
4107
|
+
encodePathParam
|
|
4108
|
+
);
|
|
4109
|
+
if (url.includes("*")) {
|
|
4110
|
+
const wildcardValue = params["*"] ?? params.splat;
|
|
4111
|
+
if (wildcardValue !== void 0) {
|
|
4112
|
+
url = url.replace(
|
|
4113
|
+
/\*[^/]*$/,
|
|
4114
|
+
encodePathParam(wildcardValue)
|
|
4115
|
+
);
|
|
4116
|
+
}
|
|
4117
|
+
}
|
|
4118
|
+
entries.push({
|
|
4119
|
+
urlPath: url.replace(/\/$/, "") || "/",
|
|
4120
|
+
routeName,
|
|
4121
|
+
concurrency,
|
|
4122
|
+
...hasBuildVars ? { buildVars } : {},
|
|
4123
|
+
isPassthroughRoute
|
|
4124
|
+
});
|
|
4125
|
+
}
|
|
4126
|
+
resolvedRoutes++;
|
|
4127
|
+
} catch (err) {
|
|
4128
|
+
resolvedRoutes++;
|
|
4129
|
+
if (err.name === "Skip") {
|
|
4130
|
+
console.log(
|
|
4131
|
+
`[rsc-router] SKIP route "${routeName}" - ${err.message}`
|
|
4132
|
+
);
|
|
4133
|
+
notifyOnError(
|
|
4134
|
+
registry,
|
|
4135
|
+
err,
|
|
4136
|
+
"prerender",
|
|
4137
|
+
routeName,
|
|
4138
|
+
void 0,
|
|
4139
|
+
true
|
|
4140
|
+
);
|
|
4141
|
+
continue;
|
|
4142
|
+
}
|
|
4143
|
+
console.error(
|
|
4144
|
+
`[rsc-router] Failed to get params for prerender route "${routeName}": ${err.message}`
|
|
3658
4145
|
);
|
|
3659
|
-
|
|
4146
|
+
notifyOnError(registry, err, "prerender", routeName);
|
|
4147
|
+
throw err;
|
|
3660
4148
|
}
|
|
3661
|
-
|
|
3662
|
-
|
|
4149
|
+
} else {
|
|
4150
|
+
console.warn(
|
|
4151
|
+
`[rsc-router] Dynamic prerender route "${routeName}" has no getParams(), skipping`
|
|
3663
4152
|
);
|
|
3664
|
-
notifyOnError(registry, err, "prerender", routeName);
|
|
3665
|
-
throw err;
|
|
3666
4153
|
}
|
|
3667
|
-
} else {
|
|
3668
|
-
console.warn(
|
|
3669
|
-
`[rsc-router] Dynamic prerender route "${routeName}" has no getParams(), skipping`
|
|
3670
|
-
);
|
|
3671
4154
|
}
|
|
3672
4155
|
}
|
|
3673
4156
|
}
|
|
4157
|
+
} finally {
|
|
4158
|
+
if (progressInterval) {
|
|
4159
|
+
clearInterval(progressInterval);
|
|
4160
|
+
const elapsed = ((performance.now() - paramsStart) / 1e3).toFixed(1);
|
|
4161
|
+
console.log(
|
|
4162
|
+
`[rsc-router] Resolved prerender params: ${resolvedRoutes}/${totalDynamic} routes (${elapsed}s)`
|
|
4163
|
+
);
|
|
4164
|
+
}
|
|
4165
|
+
}
|
|
4166
|
+
if (entries.length === 0) {
|
|
4167
|
+
debug9?.(
|
|
4168
|
+
"no prerender entries (done in %sms)",
|
|
4169
|
+
(performance.now() - overallStart).toFixed(1)
|
|
4170
|
+
);
|
|
4171
|
+
return;
|
|
3674
4172
|
}
|
|
3675
|
-
if (entries.length === 0) return;
|
|
3676
4173
|
const maxConcurrency = Math.max(...entries.map((e) => e.concurrency));
|
|
3677
4174
|
const concurrencyNote = maxConcurrency > 1 ? ` (concurrency: ${maxConcurrency})` : "";
|
|
3678
4175
|
console.log(
|
|
3679
4176
|
`[rsc-router] Pre-rendering ${entries.length} URL(s)${concurrencyNote}...`
|
|
3680
4177
|
);
|
|
4178
|
+
debug9?.(
|
|
4179
|
+
"prerender loop: %d entries, max concurrency %d",
|
|
4180
|
+
entries.length,
|
|
4181
|
+
maxConcurrency
|
|
4182
|
+
);
|
|
3681
4183
|
const { hashParams } = await rscEnv.runner.import("@rangojs/router/build");
|
|
3682
4184
|
const manifestEntries = {};
|
|
3683
4185
|
let doneCount = 0;
|
|
@@ -3784,10 +4286,22 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3784
4286
|
console.log(
|
|
3785
4287
|
`[rsc-router] Pre-render complete: ${parts.join(", ")} (${totalElapsed}ms total)`
|
|
3786
4288
|
);
|
|
4289
|
+
debug9?.(
|
|
4290
|
+
"expandPrerenderRoutes done: %d done, %d skipped, %sms (overall %sms)",
|
|
4291
|
+
doneCount,
|
|
4292
|
+
skipCount,
|
|
4293
|
+
totalElapsed,
|
|
4294
|
+
(performance.now() - overallStart).toFixed(1)
|
|
4295
|
+
);
|
|
3787
4296
|
}
|
|
3788
4297
|
async function renderStaticHandlers(state, rscEnv, registry) {
|
|
3789
4298
|
if (!state.opts?.enableBuildPrerender || !state.isBuildMode || !state.resolvedStaticModules?.size)
|
|
3790
4299
|
return;
|
|
4300
|
+
const overallStart = debug9 ? performance.now() : 0;
|
|
4301
|
+
debug9?.(
|
|
4302
|
+
"renderStaticHandlers: start (%d static module(s))",
|
|
4303
|
+
state.resolvedStaticModules.size
|
|
4304
|
+
);
|
|
3791
4305
|
const manifestEntries = {};
|
|
3792
4306
|
let staticDone = 0;
|
|
3793
4307
|
let staticSkip = 0;
|
|
@@ -3877,13 +4391,29 @@ async function renderStaticHandlers(state, rscEnv, registry) {
|
|
|
3877
4391
|
console.log(
|
|
3878
4392
|
`[rsc-router] Static render complete: ${staticParts.join(", ")} (${totalStaticElapsed}ms total)`
|
|
3879
4393
|
);
|
|
4394
|
+
debug9?.(
|
|
4395
|
+
"renderStaticHandlers done: %d done, %d skipped, %sms (overall %sms)",
|
|
4396
|
+
staticDone,
|
|
4397
|
+
staticSkip,
|
|
4398
|
+
totalStaticElapsed,
|
|
4399
|
+
(performance.now() - overallStart).toFixed(1)
|
|
4400
|
+
);
|
|
3880
4401
|
}
|
|
3881
4402
|
|
|
3882
4403
|
// src/vite/discovery/discover-routers.ts
|
|
4404
|
+
var debug10 = createRangoDebugger(NS.discovery);
|
|
3883
4405
|
async function discoverRouters(state, rscEnv) {
|
|
3884
4406
|
if (!state.resolvedEntryPath) return;
|
|
3885
|
-
await
|
|
3886
|
-
|
|
4407
|
+
await timed(
|
|
4408
|
+
debug10,
|
|
4409
|
+
"inner: import entry",
|
|
4410
|
+
() => rscEnv.runner.import(state.resolvedEntryPath)
|
|
4411
|
+
);
|
|
4412
|
+
const serverMod = await timed(
|
|
4413
|
+
debug10,
|
|
4414
|
+
"inner: import @rangojs/router/server",
|
|
4415
|
+
() => rscEnv.runner.import("@rangojs/router/server")
|
|
4416
|
+
);
|
|
3887
4417
|
let registry = serverMod.RouterRegistry;
|
|
3888
4418
|
if (!registry || registry.size === 0) {
|
|
3889
4419
|
try {
|
|
@@ -3925,8 +4455,13 @@ async function discoverRouters(state, rscEnv) {
|
|
|
3925
4455
|
);
|
|
3926
4456
|
}
|
|
3927
4457
|
}
|
|
3928
|
-
const buildMod = await
|
|
4458
|
+
const buildMod = await timed(
|
|
4459
|
+
debug10,
|
|
4460
|
+
"inner: import @rangojs/router/build",
|
|
4461
|
+
() => rscEnv.runner.import("@rangojs/router/build")
|
|
4462
|
+
);
|
|
3929
4463
|
const generateManifestFull = buildMod.generateManifestFull;
|
|
4464
|
+
debug10?.("inner: found %d router(s) in registry", registry.size);
|
|
3930
4465
|
const nestedRouterConflict = findNestedRouterConflict(
|
|
3931
4466
|
[...registry.values()].map((router) => router.__sourceFile).filter(
|
|
3932
4467
|
(sourceFile) => typeof sourceFile === "string"
|
|
@@ -3945,6 +4480,7 @@ async function discoverRouters(state, rscEnv) {
|
|
|
3945
4480
|
let mergedRouteTrailingSlash = {};
|
|
3946
4481
|
let routerMountIndex = 0;
|
|
3947
4482
|
const allManifests = [];
|
|
4483
|
+
const manifestGenStart = debug10 ? performance.now() : 0;
|
|
3948
4484
|
for (const [id, router] of registry) {
|
|
3949
4485
|
if (!router.urlpatterns || !generateManifestFull) {
|
|
3950
4486
|
continue;
|
|
@@ -4019,7 +4555,13 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4019
4555
|
);
|
|
4020
4556
|
}
|
|
4021
4557
|
}
|
|
4558
|
+
debug10?.(
|
|
4559
|
+
"inner: generated manifests for %d router(s) (%sms)",
|
|
4560
|
+
allManifests.length,
|
|
4561
|
+
(performance.now() - manifestGenStart).toFixed(1)
|
|
4562
|
+
);
|
|
4022
4563
|
let newMergedRouteTrie = null;
|
|
4564
|
+
const trieStart = debug10 ? performance.now() : 0;
|
|
4023
4565
|
if (Object.keys(newMergedRouteManifest).length > 0) {
|
|
4024
4566
|
const buildRouteTrie = buildMod.buildRouteTrie;
|
|
4025
4567
|
if (buildRouteTrie && mergedRouteAncestry) {
|
|
@@ -4082,6 +4624,10 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4082
4624
|
}
|
|
4083
4625
|
}
|
|
4084
4626
|
}
|
|
4627
|
+
debug10?.(
|
|
4628
|
+
"inner: trie build done (%sms)",
|
|
4629
|
+
(performance.now() - trieStart).toFixed(1)
|
|
4630
|
+
);
|
|
4085
4631
|
state.mergedRouteManifest = newMergedRouteManifest;
|
|
4086
4632
|
state.mergedPrecomputedEntries = newMergedPrecomputedEntries;
|
|
4087
4633
|
state.perRouterManifests = newPerRouterManifests;
|
|
@@ -4522,7 +5068,26 @@ function postprocessBundle(state) {
|
|
|
4522
5068
|
}
|
|
4523
5069
|
|
|
4524
5070
|
// src/vite/router-discovery.ts
|
|
5071
|
+
var debugDiscovery = createRangoDebugger(NS.discovery);
|
|
5072
|
+
var debugRoutes = createRangoDebugger(NS.routes);
|
|
5073
|
+
var debugBuild = createRangoDebugger(NS.build);
|
|
5074
|
+
var debugDev = createRangoDebugger(NS.dev);
|
|
5075
|
+
var loaderHookRegistered = false;
|
|
5076
|
+
function ensureCloudflareProtocolLoaderRegistered() {
|
|
5077
|
+
if (loaderHookRegistered) return;
|
|
5078
|
+
loaderHookRegistered = true;
|
|
5079
|
+
try {
|
|
5080
|
+
register(
|
|
5081
|
+
new URL("./plugins/cloudflare-protocol-loader-hook.mjs", import.meta.url)
|
|
5082
|
+
);
|
|
5083
|
+
} catch (err) {
|
|
5084
|
+
console.warn(
|
|
5085
|
+
`[rsc-router] Could not register Node ESM loader hook for cloudflare:* imports (${err?.message ?? err}). Falling back to Vite transform only.`
|
|
5086
|
+
);
|
|
5087
|
+
}
|
|
5088
|
+
}
|
|
4525
5089
|
async function createTempRscServer(state, options = {}) {
|
|
5090
|
+
ensureCloudflareProtocolLoaderRegistered();
|
|
4526
5091
|
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
4527
5092
|
return createViteServer({
|
|
4528
5093
|
root: state.projectRoot,
|
|
@@ -4545,6 +5110,7 @@ async function createTempRscServer(state, options = {}) {
|
|
|
4545
5110
|
...options.forceBuild ? [hashClientRefs(state.projectRoot)] : [],
|
|
4546
5111
|
createVersionPlugin(),
|
|
4547
5112
|
createVirtualStubPlugin(),
|
|
5113
|
+
createCloudflareProtocolStubPlugin(),
|
|
4548
5114
|
// Dev prerender must use dev-mode IDs (path-based) to match the workerd
|
|
4549
5115
|
// runtime. forceBuild produces hashed IDs for production bundle consistency.
|
|
4550
5116
|
exposeInternalIds(options.forceBuild ? { forceBuild: true } : void 0),
|
|
@@ -4561,7 +5127,7 @@ async function resolveBuildEnv(option, factoryCtx) {
|
|
|
4561
5127
|
);
|
|
4562
5128
|
}
|
|
4563
5129
|
try {
|
|
4564
|
-
const userRequire =
|
|
5130
|
+
const userRequire = createRequire2(
|
|
4565
5131
|
resolve8(factoryCtx.root, "package.json")
|
|
4566
5132
|
);
|
|
4567
5133
|
const wranglerPath = userRequire.resolve("wrangler");
|
|
@@ -4596,6 +5162,7 @@ async function acquireBuildEnv(s, command, mode) {
|
|
|
4596
5162
|
if (!result) return false;
|
|
4597
5163
|
s.resolvedBuildEnv = result.env;
|
|
4598
5164
|
s.buildEnvDispose = result.dispose ?? null;
|
|
5165
|
+
globalThis[BUILD_ENV_GLOBAL_KEY] = result.env;
|
|
4599
5166
|
return true;
|
|
4600
5167
|
}
|
|
4601
5168
|
async function releaseBuildEnv(s) {
|
|
@@ -4608,6 +5175,7 @@ async function releaseBuildEnv(s) {
|
|
|
4608
5175
|
s.buildEnvDispose = null;
|
|
4609
5176
|
}
|
|
4610
5177
|
s.resolvedBuildEnv = void 0;
|
|
5178
|
+
delete globalThis[BUILD_ENV_GLOBAL_KEY];
|
|
4611
5179
|
}
|
|
4612
5180
|
function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
4613
5181
|
const s = createDiscoveryState(entryPath, opts);
|
|
@@ -4700,15 +5268,33 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4700
5268
|
return null;
|
|
4701
5269
|
}
|
|
4702
5270
|
const discover = async () => {
|
|
5271
|
+
const discoverStart = performance.now();
|
|
4703
5272
|
const rscEnv = server.environments?.rsc;
|
|
4704
5273
|
if (!rscEnv?.runner) {
|
|
5274
|
+
debugDiscovery?.("dev: no rsc runner (cloudflare path)");
|
|
4705
5275
|
s.devServerOrigin = getDevServerOrigin();
|
|
4706
5276
|
try {
|
|
4707
|
-
await
|
|
4708
|
-
|
|
5277
|
+
await timed(
|
|
5278
|
+
debugDiscovery,
|
|
5279
|
+
"acquireBuildEnv",
|
|
5280
|
+
() => acquireBuildEnv(s, viteCommand, viteMode)
|
|
5281
|
+
);
|
|
5282
|
+
const tempRscEnv = await timed(
|
|
5283
|
+
debugDiscovery,
|
|
5284
|
+
"getOrCreateTempServer",
|
|
5285
|
+
() => getOrCreateTempServer()
|
|
5286
|
+
);
|
|
4709
5287
|
if (tempRscEnv) {
|
|
4710
|
-
await
|
|
4711
|
-
|
|
5288
|
+
await timed(
|
|
5289
|
+
debugDiscovery,
|
|
5290
|
+
"discoverRouters (cloudflare)",
|
|
5291
|
+
() => discoverRouters(s, tempRscEnv)
|
|
5292
|
+
);
|
|
5293
|
+
timedSync(
|
|
5294
|
+
debugDiscovery,
|
|
5295
|
+
"writeRouteTypesFiles",
|
|
5296
|
+
() => writeRouteTypesFiles(s)
|
|
5297
|
+
);
|
|
4712
5298
|
}
|
|
4713
5299
|
} catch (err) {
|
|
4714
5300
|
console.warn(
|
|
@@ -4716,27 +5302,54 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4716
5302
|
${err.stack}`
|
|
4717
5303
|
);
|
|
4718
5304
|
}
|
|
5305
|
+
debugDiscovery?.(
|
|
5306
|
+
"dev discovery done (%sms)",
|
|
5307
|
+
(performance.now() - discoverStart).toFixed(1)
|
|
5308
|
+
);
|
|
4719
5309
|
resolveDiscovery();
|
|
4720
5310
|
return;
|
|
4721
5311
|
}
|
|
4722
5312
|
try {
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
5313
|
+
debugDiscovery?.("dev: node path start");
|
|
5314
|
+
await timed(
|
|
5315
|
+
debugDiscovery,
|
|
5316
|
+
"acquireBuildEnv",
|
|
5317
|
+
() => acquireBuildEnv(s, viteCommand, viteMode)
|
|
5318
|
+
);
|
|
5319
|
+
const serverMod = await timed(
|
|
5320
|
+
debugDiscovery,
|
|
5321
|
+
"import @rangojs/router/server",
|
|
5322
|
+
() => rscEnv.runner.import("@rangojs/router/server")
|
|
4726
5323
|
);
|
|
4727
5324
|
if (serverMod?.setManifestReadyPromise) {
|
|
4728
5325
|
serverMod.setManifestReadyPromise(discoveryPromise);
|
|
4729
5326
|
}
|
|
4730
|
-
await
|
|
5327
|
+
await timed(
|
|
5328
|
+
debugDiscovery,
|
|
5329
|
+
"discoverRouters",
|
|
5330
|
+
() => discoverRouters(s, rscEnv)
|
|
5331
|
+
);
|
|
4731
5332
|
s.devServerOrigin = getDevServerOrigin();
|
|
4732
|
-
|
|
4733
|
-
|
|
5333
|
+
timedSync(
|
|
5334
|
+
debugDiscovery,
|
|
5335
|
+
"writeRouteTypesFiles",
|
|
5336
|
+
() => writeRouteTypesFiles(s)
|
|
5337
|
+
);
|
|
5338
|
+
await timed(
|
|
5339
|
+
debugDiscovery,
|
|
5340
|
+
"propagateDiscoveryState",
|
|
5341
|
+
() => propagateDiscoveryState(rscEnv)
|
|
5342
|
+
);
|
|
4734
5343
|
} catch (err) {
|
|
4735
5344
|
console.warn(
|
|
4736
5345
|
`[rsc-router] Router discovery failed: ${err.message}
|
|
4737
5346
|
${err.stack}`
|
|
4738
5347
|
);
|
|
4739
5348
|
} finally {
|
|
5349
|
+
debugDiscovery?.(
|
|
5350
|
+
"dev discovery done (%sms)",
|
|
5351
|
+
(performance.now() - discoverStart).toFixed(1)
|
|
5352
|
+
);
|
|
4740
5353
|
resolveDiscovery();
|
|
4741
5354
|
}
|
|
4742
5355
|
};
|
|
@@ -4777,15 +5390,46 @@ ${err.stack}`
|
|
|
4777
5390
|
}
|
|
4778
5391
|
};
|
|
4779
5392
|
server.middlewares.use("/__rsc_prerender", async (req, res) => {
|
|
5393
|
+
const reqStart = debugDev ? performance.now() : 0;
|
|
5394
|
+
const logResult = (status, note) => {
|
|
5395
|
+
debugDev?.(
|
|
5396
|
+
"/__rsc_prerender %s -> %d %s (%sms)",
|
|
5397
|
+
req.url,
|
|
5398
|
+
status,
|
|
5399
|
+
note,
|
|
5400
|
+
(performance.now() - reqStart).toFixed(1)
|
|
5401
|
+
);
|
|
5402
|
+
};
|
|
4780
5403
|
if (s.discoveryDone) await s.discoveryDone;
|
|
4781
5404
|
const url = new URL(req.url || "/", "http://localhost");
|
|
4782
5405
|
const pathname = url.searchParams.get("pathname");
|
|
4783
5406
|
if (!pathname) {
|
|
4784
5407
|
res.statusCode = 400;
|
|
4785
5408
|
res.end("Missing pathname");
|
|
5409
|
+
logResult(400, "missing pathname");
|
|
4786
5410
|
return;
|
|
4787
5411
|
}
|
|
4788
|
-
|
|
5412
|
+
const rscEnv = server.environments?.rsc;
|
|
5413
|
+
let registry = null;
|
|
5414
|
+
if (rscEnv?.runner && s.resolvedEntryPath) {
|
|
5415
|
+
try {
|
|
5416
|
+
await rscEnv.runner.import(s.resolvedEntryPath);
|
|
5417
|
+
const serverMod = await rscEnv.runner.import(
|
|
5418
|
+
"@rangojs/router/server"
|
|
5419
|
+
);
|
|
5420
|
+
registry = serverMod.RouterRegistry ?? null;
|
|
5421
|
+
} catch (err) {
|
|
5422
|
+
console.warn(
|
|
5423
|
+
`[rsc-router] Dev prerender module refresh failed: ${err.message}`
|
|
5424
|
+
);
|
|
5425
|
+
res.statusCode = 500;
|
|
5426
|
+
res.end(`Prerender handler error: ${err.message}`);
|
|
5427
|
+
logResult(500, "module refresh failed");
|
|
5428
|
+
return;
|
|
5429
|
+
}
|
|
5430
|
+
} else {
|
|
5431
|
+
registry = mainRegistry;
|
|
5432
|
+
}
|
|
4789
5433
|
if (!registry) {
|
|
4790
5434
|
if (!prerenderNodeRegistry) {
|
|
4791
5435
|
await getOrCreateTempServer();
|
|
@@ -4795,6 +5439,7 @@ ${err.stack}`
|
|
|
4795
5439
|
if (!registry || registry.size === 0) {
|
|
4796
5440
|
res.statusCode = 503;
|
|
4797
5441
|
res.end("Prerender runner not available");
|
|
5442
|
+
logResult(503, "no registry");
|
|
4798
5443
|
return;
|
|
4799
5444
|
}
|
|
4800
5445
|
const wantIntercept = url.searchParams.get("intercept") === "1";
|
|
@@ -4829,6 +5474,7 @@ ${err.stack}`
|
|
|
4829
5474
|
payload = { segments: result.segments, handles: result.handles };
|
|
4830
5475
|
}
|
|
4831
5476
|
res.end(JSON.stringify(payload));
|
|
5477
|
+
logResult(200, `match ${result.routeName}`);
|
|
4832
5478
|
return;
|
|
4833
5479
|
} catch (err) {
|
|
4834
5480
|
console.warn(
|
|
@@ -4838,6 +5484,7 @@ ${err.stack}`
|
|
|
4838
5484
|
}
|
|
4839
5485
|
res.statusCode = 404;
|
|
4840
5486
|
res.end("No prerender match");
|
|
5487
|
+
logResult(404, "no match");
|
|
4841
5488
|
});
|
|
4842
5489
|
if (opts?.staticRouteTypesGeneration !== false) {
|
|
4843
5490
|
const isGeneratedRouteFile = (filePath) => filePath.endsWith(".gen.ts") && (filePath.includes("named-routes.gen.ts") || filePath.includes("urls.gen.ts"));
|
|
@@ -4862,15 +5509,32 @@ ${err.stack}`
|
|
|
4862
5509
|
const rscEnv = server.environments?.rsc;
|
|
4863
5510
|
if (!rscEnv?.runner || runtimeRediscoveryInProgress) return;
|
|
4864
5511
|
runtimeRediscoveryInProgress = true;
|
|
5512
|
+
const hmrStart = performance.now();
|
|
4865
5513
|
try {
|
|
4866
|
-
await
|
|
4867
|
-
|
|
4868
|
-
|
|
5514
|
+
await timed(
|
|
5515
|
+
debugDiscovery,
|
|
5516
|
+
"hmr discoverRouters",
|
|
5517
|
+
() => discoverRouters(s, rscEnv)
|
|
5518
|
+
);
|
|
5519
|
+
timedSync(
|
|
5520
|
+
debugDiscovery,
|
|
5521
|
+
"hmr writeRouteTypesFiles",
|
|
5522
|
+
() => writeRouteTypesFiles(s)
|
|
5523
|
+
);
|
|
5524
|
+
await timed(
|
|
5525
|
+
debugDiscovery,
|
|
5526
|
+
"hmr propagateDiscoveryState",
|
|
5527
|
+
() => propagateDiscoveryState(rscEnv)
|
|
5528
|
+
);
|
|
4869
5529
|
} catch (err) {
|
|
4870
5530
|
console.warn(
|
|
4871
5531
|
`[rsc-router] Runtime re-discovery failed: ${err.message}`
|
|
4872
5532
|
);
|
|
4873
5533
|
} finally {
|
|
5534
|
+
debugDiscovery?.(
|
|
5535
|
+
"hmr re-discovery done (%sms)",
|
|
5536
|
+
(performance.now() - hmrStart).toFixed(1)
|
|
5537
|
+
);
|
|
4874
5538
|
runtimeRediscoveryInProgress = false;
|
|
4875
5539
|
}
|
|
4876
5540
|
};
|
|
@@ -4878,6 +5542,7 @@ ${err.stack}`
|
|
|
4878
5542
|
clearTimeout(routeChangeTimer);
|
|
4879
5543
|
routeChangeTimer = setTimeout(() => {
|
|
4880
5544
|
routeChangeTimer = void 0;
|
|
5545
|
+
const regenStart = debugDiscovery ? performance.now() : 0;
|
|
4881
5546
|
try {
|
|
4882
5547
|
writeCombinedRouteTypesWithTracking(s);
|
|
4883
5548
|
if (s.perRouterManifests.length > 0) {
|
|
@@ -4888,6 +5553,10 @@ ${err.stack}`
|
|
|
4888
5553
|
`[rsc-router] Route regeneration error: ${err.message}`
|
|
4889
5554
|
);
|
|
4890
5555
|
}
|
|
5556
|
+
debugDiscovery?.(
|
|
5557
|
+
"watcher: regenerated gen files (%sms)",
|
|
5558
|
+
(performance.now() - regenStart).toFixed(1)
|
|
5559
|
+
);
|
|
4891
5560
|
if (s.perRouterManifests.length > 0) {
|
|
4892
5561
|
refreshRuntimeDiscovery().catch((err) => {
|
|
4893
5562
|
console.warn(
|
|
@@ -4910,6 +5579,12 @@ ${err.stack}`
|
|
|
4910
5579
|
const hasUrls = source.includes("urls(");
|
|
4911
5580
|
const hasCreateRouter = /\bcreateRouter\s*[<(]/.test(source);
|
|
4912
5581
|
if (!hasUrls && !hasCreateRouter) return;
|
|
5582
|
+
debugDiscovery?.(
|
|
5583
|
+
"watcher: %s matches (urls=%s, router=%s)",
|
|
5584
|
+
filePath,
|
|
5585
|
+
hasUrls,
|
|
5586
|
+
hasCreateRouter
|
|
5587
|
+
);
|
|
4913
5588
|
if (hasCreateRouter) {
|
|
4914
5589
|
const nestedRouterConflict = findNestedRouterConflict([
|
|
4915
5590
|
...s.cachedRouterFiles ?? [],
|
|
@@ -4942,15 +5617,31 @@ ${err.stack}`
|
|
|
4942
5617
|
// The manifest data is stored for the virtual module's load hook.
|
|
4943
5618
|
async buildStart() {
|
|
4944
5619
|
if (!s.isBuildMode) return;
|
|
4945
|
-
if (s.mergedRouteManifest !== null)
|
|
5620
|
+
if (s.mergedRouteManifest !== null) {
|
|
5621
|
+
debugDiscovery?.(
|
|
5622
|
+
"build: skip (already discovered, env=%s)",
|
|
5623
|
+
this.environment?.name ?? "?"
|
|
5624
|
+
);
|
|
5625
|
+
return;
|
|
5626
|
+
}
|
|
5627
|
+
const buildStartTime = performance.now();
|
|
5628
|
+
debugDiscovery?.("build: start (env=%s)", this.environment?.name ?? "?");
|
|
4946
5629
|
resetStagedBuildAssets(s.projectRoot);
|
|
4947
5630
|
s.prerenderManifestEntries = null;
|
|
4948
5631
|
s.staticManifestEntries = null;
|
|
4949
|
-
await
|
|
5632
|
+
await timed(
|
|
5633
|
+
debugDiscovery,
|
|
5634
|
+
"build acquireBuildEnv",
|
|
5635
|
+
() => acquireBuildEnv(s, viteCommand, viteMode)
|
|
5636
|
+
);
|
|
4950
5637
|
let tempServer = null;
|
|
4951
5638
|
globalThis.__rscRouterDiscoveryActive = true;
|
|
4952
5639
|
try {
|
|
4953
|
-
tempServer = await
|
|
5640
|
+
tempServer = await timed(
|
|
5641
|
+
debugDiscovery,
|
|
5642
|
+
"build createTempRscServer",
|
|
5643
|
+
() => createTempRscServer(s, { forceBuild: true })
|
|
5644
|
+
);
|
|
4954
5645
|
const rscEnv = tempServer.environments?.rsc;
|
|
4955
5646
|
if (!rscEnv?.runner) {
|
|
4956
5647
|
console.warn(
|
|
@@ -4964,8 +5655,16 @@ ${err.stack}`
|
|
|
4964
5655
|
if (tempIdsPlugin?.api?.staticHandlerModules) {
|
|
4965
5656
|
s.resolvedStaticModules = tempIdsPlugin.api.staticHandlerModules;
|
|
4966
5657
|
}
|
|
4967
|
-
await
|
|
4968
|
-
|
|
5658
|
+
await timed(
|
|
5659
|
+
debugDiscovery,
|
|
5660
|
+
"build discoverRouters",
|
|
5661
|
+
() => discoverRouters(s, rscEnv)
|
|
5662
|
+
);
|
|
5663
|
+
timedSync(
|
|
5664
|
+
debugDiscovery,
|
|
5665
|
+
"build writeRouteTypesFiles",
|
|
5666
|
+
() => writeRouteTypesFiles(s)
|
|
5667
|
+
);
|
|
4969
5668
|
} catch (err) {
|
|
4970
5669
|
const sourceFile = err.stack?.split("\n").find(
|
|
4971
5670
|
(line) => line.includes(s.projectRoot) && !line.includes("node_modules")
|
|
@@ -4984,9 +5683,17 @@ ${details}`
|
|
|
4984
5683
|
} finally {
|
|
4985
5684
|
delete globalThis.__rscRouterDiscoveryActive;
|
|
4986
5685
|
if (tempServer) {
|
|
4987
|
-
await
|
|
5686
|
+
await timed(
|
|
5687
|
+
debugDiscovery,
|
|
5688
|
+
"build tempServer.close",
|
|
5689
|
+
() => tempServer.close()
|
|
5690
|
+
);
|
|
4988
5691
|
}
|
|
4989
5692
|
await releaseBuildEnv(s);
|
|
5693
|
+
debugDiscovery?.(
|
|
5694
|
+
"build discovery done (%sms)",
|
|
5695
|
+
(performance.now() - buildStartTime).toFixed(1)
|
|
5696
|
+
);
|
|
4990
5697
|
}
|
|
4991
5698
|
},
|
|
4992
5699
|
// Virtual module: provides the pre-generated route manifest as a JS module
|
|
@@ -5003,17 +5710,36 @@ ${details}`
|
|
|
5003
5710
|
async load(id) {
|
|
5004
5711
|
if (id === "\0" + VIRTUAL_ROUTES_MANIFEST_ID) {
|
|
5005
5712
|
if (s.discoveryDone) {
|
|
5006
|
-
await
|
|
5713
|
+
await timed(
|
|
5714
|
+
debugRoutes,
|
|
5715
|
+
"await discoveryDone (manifest)",
|
|
5716
|
+
() => s.discoveryDone
|
|
5717
|
+
);
|
|
5007
5718
|
}
|
|
5008
|
-
|
|
5719
|
+
const code = await timed(
|
|
5720
|
+
debugRoutes,
|
|
5721
|
+
"generateRoutesManifestModule",
|
|
5722
|
+
() => generateRoutesManifestModule(s)
|
|
5723
|
+
);
|
|
5724
|
+
debugRoutes?.("manifest module emitted (%d bytes)", code?.length ?? 0);
|
|
5725
|
+
return code;
|
|
5009
5726
|
}
|
|
5010
5727
|
const perRouterPrefix = "\0" + VIRTUAL_ROUTES_MANIFEST_ID + "/";
|
|
5011
5728
|
if (id.startsWith(perRouterPrefix)) {
|
|
5012
5729
|
if (s.discoveryDone) {
|
|
5013
|
-
await
|
|
5730
|
+
await timed(
|
|
5731
|
+
debugRoutes,
|
|
5732
|
+
"await discoveryDone (per-router)",
|
|
5733
|
+
() => s.discoveryDone
|
|
5734
|
+
);
|
|
5014
5735
|
}
|
|
5015
5736
|
const routerId = id.slice(perRouterPrefix.length);
|
|
5016
|
-
|
|
5737
|
+
const code = await timed(
|
|
5738
|
+
debugRoutes,
|
|
5739
|
+
`generatePerRouterModule ${routerId}`,
|
|
5740
|
+
() => generatePerRouterModule(s, routerId)
|
|
5741
|
+
);
|
|
5742
|
+
return code;
|
|
5017
5743
|
}
|
|
5018
5744
|
return null;
|
|
5019
5745
|
},
|
|
@@ -5021,14 +5747,20 @@ ${details}`
|
|
|
5021
5747
|
// Used by closeBundle for handler code eviction and prerender data injection.
|
|
5022
5748
|
generateBundle(_options, bundle) {
|
|
5023
5749
|
if (this.environment?.name !== "rsc") return;
|
|
5750
|
+
const genStart = debugBuild ? performance.now() : 0;
|
|
5024
5751
|
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
5025
5752
|
if (chunk.type === "chunk" && chunk.isEntry) {
|
|
5026
5753
|
s.rscEntryFileName = fileName;
|
|
5027
5754
|
break;
|
|
5028
5755
|
}
|
|
5029
5756
|
}
|
|
5030
|
-
if (!s.resolvedPrerenderModules?.size && !s.resolvedStaticModules?.size)
|
|
5757
|
+
if (!s.resolvedPrerenderModules?.size && !s.resolvedStaticModules?.size) {
|
|
5758
|
+
debugBuild?.(
|
|
5759
|
+
"generateBundle (rsc): no handlers to scan (%sms)",
|
|
5760
|
+
(performance.now() - genStart).toFixed(1)
|
|
5761
|
+
);
|
|
5031
5762
|
return;
|
|
5763
|
+
}
|
|
5032
5764
|
s.handlerChunkInfoMap.clear();
|
|
5033
5765
|
s.staticHandlerChunkInfoMap.clear();
|
|
5034
5766
|
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
@@ -5072,6 +5804,13 @@ ${details}`
|
|
|
5072
5804
|
}
|
|
5073
5805
|
}
|
|
5074
5806
|
}
|
|
5807
|
+
debugBuild?.(
|
|
5808
|
+
"generateBundle (rsc): scanned %d chunks, %d prerender chunk(s), %d static chunk(s) (%sms)",
|
|
5809
|
+
Object.keys(bundle).length,
|
|
5810
|
+
s.handlerChunkInfoMap.size,
|
|
5811
|
+
s.staticHandlerChunkInfoMap.size,
|
|
5812
|
+
(performance.now() - genStart).toFixed(1)
|
|
5813
|
+
);
|
|
5075
5814
|
},
|
|
5076
5815
|
// Build-time pre-rendering: evict handler code and inject collected prerender data.
|
|
5077
5816
|
// Collection now happens in-process during discoverRouters() via RSC runner.
|
|
@@ -5082,29 +5821,41 @@ ${details}`
|
|
|
5082
5821
|
async handler() {
|
|
5083
5822
|
if (!s.isBuildMode) return;
|
|
5084
5823
|
if (this.environment && this.environment.name !== "rsc") return;
|
|
5085
|
-
|
|
5824
|
+
timedSync(
|
|
5825
|
+
debugBuild,
|
|
5826
|
+
"closeBundle postprocessBundle",
|
|
5827
|
+
() => postprocessBundle(s)
|
|
5828
|
+
);
|
|
5086
5829
|
}
|
|
5087
5830
|
}
|
|
5088
5831
|
};
|
|
5089
5832
|
}
|
|
5090
5833
|
|
|
5091
5834
|
// src/vite/rango.ts
|
|
5835
|
+
var debugConfig = createRangoDebugger(NS.config);
|
|
5092
5836
|
async function rango(options) {
|
|
5837
|
+
const rangoStart = performance.now();
|
|
5093
5838
|
const resolvedOptions = options ?? { preset: "node" };
|
|
5094
5839
|
const preset = resolvedOptions.preset ?? "node";
|
|
5095
5840
|
const showBanner = resolvedOptions.banner ?? true;
|
|
5841
|
+
debugConfig?.("rango(%s) setup start", preset);
|
|
5096
5842
|
const plugins = [];
|
|
5097
|
-
const rangoAliases = getPackageAliases();
|
|
5843
|
+
const rangoAliases = { ...getPackageAliases(), ...getVendorAliases() };
|
|
5098
5844
|
const excludeDeps = [
|
|
5099
5845
|
...getExcludeDeps(),
|
|
5100
|
-
//
|
|
5101
|
-
//
|
|
5102
|
-
// .
|
|
5846
|
+
// plugin-rsc itself injects these into the client env's
|
|
5847
|
+
// optimizeDeps.include, which overrides exclude for the dep's own
|
|
5848
|
+
// pre-bundle entry. What exclude still controls is how *other*
|
|
5849
|
+
// pre-bundled deps treat imports of these specs (external vs inlined)
|
|
5850
|
+
// via esbuildCjsExternalPlugin. The cjs-to-esm transform in
|
|
5851
|
+
// plugins/cjs-to-esm.ts is the fallback for strict-pnpm consumers,
|
|
5852
|
+
// where client.browser's bare include fails to resolve and Vite ends up
|
|
5853
|
+
// serving the raw CJS file at dev-serve time.
|
|
5103
5854
|
"@vitejs/plugin-rsc/browser",
|
|
5104
|
-
// Keep the browser RSDW client out of Vite's dep optimizer so our
|
|
5105
|
-
// cjs-to-esm transform can patch the real file.
|
|
5106
5855
|
"@vitejs/plugin-rsc/vendor/react-server-dom/client.browser"
|
|
5107
5856
|
];
|
|
5857
|
+
const pkg = getPublishedPackageName();
|
|
5858
|
+
const nested = (spec) => `${pkg} > ${spec}`;
|
|
5108
5859
|
const routerRef = { path: void 0 };
|
|
5109
5860
|
const prerenderEnabled = true;
|
|
5110
5861
|
if (preset === "cloudflare") {
|
|
@@ -5142,7 +5893,7 @@ async function rango(options) {
|
|
|
5142
5893
|
// Pre-bundle rsc-html-stream to prevent discovery during first request
|
|
5143
5894
|
// Exclude rsc-router modules to ensure same Context instance
|
|
5144
5895
|
optimizeDeps: {
|
|
5145
|
-
include: ["rsc-html-stream/client"],
|
|
5896
|
+
include: [nested("rsc-html-stream/client")],
|
|
5146
5897
|
exclude: excludeDeps,
|
|
5147
5898
|
esbuildOptions: sharedEsbuildOptions
|
|
5148
5899
|
}
|
|
@@ -5167,8 +5918,10 @@ async function rango(options) {
|
|
|
5167
5918
|
"react-dom/static.edge",
|
|
5168
5919
|
"react/jsx-runtime",
|
|
5169
5920
|
"react/jsx-dev-runtime",
|
|
5170
|
-
"rsc-html-stream/server",
|
|
5171
|
-
|
|
5921
|
+
nested("rsc-html-stream/server"),
|
|
5922
|
+
nested(
|
|
5923
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge"
|
|
5924
|
+
)
|
|
5172
5925
|
],
|
|
5173
5926
|
exclude: excludeDeps,
|
|
5174
5927
|
esbuildOptions: sharedEsbuildOptions
|
|
@@ -5183,7 +5936,9 @@ async function rango(options) {
|
|
|
5183
5936
|
"react",
|
|
5184
5937
|
"react/jsx-runtime",
|
|
5185
5938
|
"react/jsx-dev-runtime",
|
|
5186
|
-
|
|
5939
|
+
nested(
|
|
5940
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge"
|
|
5941
|
+
)
|
|
5187
5942
|
],
|
|
5188
5943
|
exclude: excludeDeps,
|
|
5189
5944
|
esbuildOptions: sharedEsbuildOptions
|
|
@@ -5264,7 +6019,7 @@ ${list}`);
|
|
|
5264
6019
|
"react-dom",
|
|
5265
6020
|
"react/jsx-runtime",
|
|
5266
6021
|
"react/jsx-dev-runtime",
|
|
5267
|
-
"rsc-html-stream/client"
|
|
6022
|
+
nested("rsc-html-stream/client")
|
|
5268
6023
|
],
|
|
5269
6024
|
exclude: excludeDeps,
|
|
5270
6025
|
esbuildOptions: sharedEsbuildOptions,
|
|
@@ -5281,7 +6036,9 @@ ${list}`);
|
|
|
5281
6036
|
"react-dom/static.edge",
|
|
5282
6037
|
"react/jsx-runtime",
|
|
5283
6038
|
"react/jsx-dev-runtime",
|
|
5284
|
-
|
|
6039
|
+
nested(
|
|
6040
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge"
|
|
6041
|
+
)
|
|
5285
6042
|
],
|
|
5286
6043
|
exclude: excludeDeps,
|
|
5287
6044
|
esbuildOptions: sharedEsbuildOptions
|
|
@@ -5294,7 +6051,9 @@ ${list}`);
|
|
|
5294
6051
|
"react",
|
|
5295
6052
|
"react/jsx-runtime",
|
|
5296
6053
|
"react/jsx-dev-runtime",
|
|
5297
|
-
|
|
6054
|
+
nested(
|
|
6055
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge"
|
|
6056
|
+
)
|
|
5298
6057
|
],
|
|
5299
6058
|
esbuildOptions: sharedEsbuildOptions
|
|
5300
6059
|
}
|
|
@@ -5364,6 +6123,12 @@ ${list}`);
|
|
|
5364
6123
|
preset
|
|
5365
6124
|
})
|
|
5366
6125
|
);
|
|
6126
|
+
debugConfig?.(
|
|
6127
|
+
"rango(%s) setup done: %d plugin(s) (%sms)",
|
|
6128
|
+
preset,
|
|
6129
|
+
plugins.length,
|
|
6130
|
+
(performance.now() - rangoStart).toFixed(1)
|
|
6131
|
+
);
|
|
5367
6132
|
return plugins;
|
|
5368
6133
|
}
|
|
5369
6134
|
|
|
@@ -5374,7 +6139,7 @@ function poke() {
|
|
|
5374
6139
|
apply: "serve",
|
|
5375
6140
|
configureServer(server) {
|
|
5376
6141
|
const stdin = process.stdin;
|
|
5377
|
-
const
|
|
6142
|
+
const debug11 = process.env.RANGO_POKE_DEBUG === "1";
|
|
5378
6143
|
const triggerReload = (source) => {
|
|
5379
6144
|
server.hot.send({ type: "full-reload", path: "*" });
|
|
5380
6145
|
server.config.logger.info(` browser reload (${source})`, {
|
|
@@ -5407,7 +6172,7 @@ function poke() {
|
|
|
5407
6172
|
lines.pop();
|
|
5408
6173
|
return lines;
|
|
5409
6174
|
};
|
|
5410
|
-
if (
|
|
6175
|
+
if (debug11) {
|
|
5411
6176
|
server.config.logger.info(
|
|
5412
6177
|
` poke debug enabled (isTTY=${stdin.isTTY ? "yes" : "no"}, isRaw=${stdin.isTTY ? stdin.isRaw ? "yes" : "no" : "n/a"})`,
|
|
5413
6178
|
{ timestamp: true }
|
|
@@ -5420,7 +6185,7 @@ function poke() {
|
|
|
5420
6185
|
);
|
|
5421
6186
|
}
|
|
5422
6187
|
const onData = (data) => {
|
|
5423
|
-
if (
|
|
6188
|
+
if (debug11) {
|
|
5424
6189
|
server.config.logger.info(` poke stdin ${formatChunk(data)}`, {
|
|
5425
6190
|
timestamp: true
|
|
5426
6191
|
});
|