@rangojs/router 0.0.0-experimental.b000c598 → 0.0.0-experimental.b30bbf02
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 +65 -0
- package/dist/vite/index.js +1160 -443
- package/package.json +3 -1
- package/skills/hooks/SKILL.md +5 -0
- package/skills/links/SKILL.md +2 -0
- package/skills/loader/SKILL.md +35 -1
- package/skills/middleware/SKILL.md +2 -0
- package/skills/migrate-nextjs/SKILL.md +3 -1
- package/skills/migrate-react-router/SKILL.md +4 -0
- package/skills/parallel/SKILL.md +7 -0
- package/skills/rango/SKILL.md +1 -0
- package/skills/server-actions/SKILL.md +739 -0
- package/src/browser/event-controller.ts +44 -4
- package/src/browser/react/NavigationProvider.tsx +20 -7
- package/src/browser/react/filter-segment-order.ts +51 -7
- package/src/browser/react/use-segments.ts +11 -8
- package/src/browser/types.ts +6 -0
- package/src/route-definition/helpers-types.ts +6 -1
- package/src/router/match-api.ts +1 -0
- package/src/router/match-handlers.ts +1 -0
- package/src/router/match-result.ts +21 -2
- package/src/router/middleware.ts +22 -3
- package/src/router/pattern-matching.ts +30 -11
- package/src/router/revalidation.ts +15 -1
- package/src/router/segment-resolution/fresh.ts +8 -0
- package/src/router/segment-resolution/revalidation.ts +128 -100
- package/src/router/trie-matching.ts +8 -9
- package/src/rsc/progressive-enhancement.ts +2 -0
- package/src/rsc/rsc-rendering.ts +3 -0
- package/src/rsc/server-action.ts +2 -0
- package/src/rsc/types.ts +6 -0
- package/src/ssr/index.tsx +5 -1
- package/src/types/handler-context.ts +10 -5
- package/src/types/segments.ts +17 -0
- package/src/vite/debug.ts +184 -0
- package/src/vite/discovery/discover-routers.ts +31 -3
- package/src/vite/discovery/gate-state.ts +171 -0
- package/src/vite/discovery/prerender-collection.ts +48 -1
- package/src/vite/discovery/self-gen-tracking.ts +27 -1
- 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/expose-action-id.ts +52 -28
- package/src/vite/plugins/expose-ids/router-transform.ts +20 -3
- package/src/vite/plugins/expose-internal-ids.ts +516 -486
- package/src/vite/plugins/performance-tracks.ts +17 -9
- package/src/vite/plugins/use-cache-transform.ts +56 -43
- package/src/vite/plugins/version-injector.ts +37 -11
- package/src/vite/rango.ts +19 -5
- package/src/vite/router-discovery.ts +498 -52
- package/src/vite/utils/package-resolution.ts +8 -0
package/dist/vite/index.js
CHANGED
|
@@ -191,7 +191,99 @@ function escapeRegExp(input) {
|
|
|
191
191
|
return input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
192
192
|
}
|
|
193
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
|
+
|
|
194
285
|
// src/vite/plugins/expose-action-id.ts
|
|
286
|
+
var debug = createRangoDebugger(NS.transform);
|
|
195
287
|
function getRscPluginApi(config) {
|
|
196
288
|
let plugin = config.plugins.find((p) => p.name === "rsc:minimal");
|
|
197
289
|
if (!plugin) {
|
|
@@ -280,6 +372,8 @@ function exposeActionId() {
|
|
|
280
372
|
let isBuild = false;
|
|
281
373
|
let hashToFileMap;
|
|
282
374
|
let rscPluginApi;
|
|
375
|
+
const counterTransform = createCounter(debug, "expose-action-id transform");
|
|
376
|
+
const counterRender = createCounter(debug, "expose-action-id renderChunk");
|
|
283
377
|
return {
|
|
284
378
|
name: "@rangojs/router:expose-action-id",
|
|
285
379
|
// Run after all other plugins (including RSC plugin's transforms)
|
|
@@ -289,6 +383,10 @@ function exposeActionId() {
|
|
|
289
383
|
isBuild = config.command === "build";
|
|
290
384
|
rscPluginApi = getRscPluginApi(config);
|
|
291
385
|
},
|
|
386
|
+
buildEnd() {
|
|
387
|
+
counterTransform?.flush();
|
|
388
|
+
counterRender?.flush();
|
|
389
|
+
},
|
|
292
390
|
buildStart() {
|
|
293
391
|
if (!rscPluginApi) {
|
|
294
392
|
rscPluginApi = getRscPluginApi(config);
|
|
@@ -325,28 +423,42 @@ function exposeActionId() {
|
|
|
325
423
|
if (id.includes("/node_modules/")) {
|
|
326
424
|
return;
|
|
327
425
|
}
|
|
328
|
-
|
|
426
|
+
const start = counterTransform ? performance.now() : 0;
|
|
427
|
+
try {
|
|
428
|
+
return transformServerReferences(code, id);
|
|
429
|
+
} finally {
|
|
430
|
+
counterTransform?.record(id, performance.now() - start);
|
|
431
|
+
}
|
|
329
432
|
},
|
|
330
433
|
// Build mode: renderChunk runs after all transforms and bundling complete
|
|
331
434
|
renderChunk(code, chunk) {
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
code
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
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;
|
|
346
457
|
}
|
|
347
|
-
return
|
|
458
|
+
return transformServerReferences(code, chunk.fileName, effectiveMap);
|
|
459
|
+
} finally {
|
|
460
|
+
counterRender?.record(chunk.fileName, performance.now() - start);
|
|
348
461
|
}
|
|
349
|
-
return transformServerReferences(code, chunk.fileName, effectiveMap);
|
|
350
462
|
}
|
|
351
463
|
};
|
|
352
464
|
}
|
|
@@ -953,6 +1065,7 @@ ${binding.localName}.$$id = "${handlerId}";`;
|
|
|
953
1065
|
import MagicString3 from "magic-string";
|
|
954
1066
|
import path3 from "node:path";
|
|
955
1067
|
import { createHash } from "node:crypto";
|
|
1068
|
+
var debug2 = createRangoDebugger(NS.transform);
|
|
956
1069
|
function transformRouter(code, filePath, routerFnNames, absolutePath) {
|
|
957
1070
|
const pat = new RegExp(
|
|
958
1071
|
`\\b(?:${routerFnNames.map((n) => n.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})\\s*(?:<[^>]*>)?\\s*\\(`,
|
|
@@ -995,11 +1108,15 @@ function transformRouter(code, filePath, routerFnNames, absolutePath) {
|
|
|
995
1108
|
}
|
|
996
1109
|
function exposeRouterId() {
|
|
997
1110
|
let projectRoot = "";
|
|
1111
|
+
const counter = createCounter(debug2, "expose-router-id");
|
|
998
1112
|
return {
|
|
999
1113
|
name: "@rangojs/router:expose-router-id",
|
|
1000
1114
|
configResolved(config) {
|
|
1001
1115
|
projectRoot = config.root;
|
|
1002
1116
|
},
|
|
1117
|
+
buildEnd() {
|
|
1118
|
+
counter?.flush();
|
|
1119
|
+
},
|
|
1003
1120
|
transform(code, id) {
|
|
1004
1121
|
if (!code.includes("createRouter")) return null;
|
|
1005
1122
|
if (!/import\s*\{[^}]*\bcreateRouter\b[^}]*\}\s*from\s*["']@rangojs\/router(?:\/server)?["']/.test(
|
|
@@ -1008,14 +1125,25 @@ function exposeRouterId() {
|
|
|
1008
1125
|
return null;
|
|
1009
1126
|
}
|
|
1010
1127
|
if (id.includes("node_modules")) return null;
|
|
1011
|
-
const
|
|
1012
|
-
|
|
1013
|
-
|
|
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
|
+
}
|
|
1014
1141
|
}
|
|
1015
1142
|
};
|
|
1016
1143
|
}
|
|
1017
1144
|
|
|
1018
1145
|
// src/vite/plugins/expose-internal-ids.ts
|
|
1146
|
+
var debug3 = createRangoDebugger(NS.transform);
|
|
1019
1147
|
var VIRTUAL_LOADER_MANIFEST = "virtual:rsc-router/loader-manifest";
|
|
1020
1148
|
var RESOLVED_VIRTUAL_LOADER_MANIFEST = "\0" + VIRTUAL_LOADER_MANIFEST;
|
|
1021
1149
|
var VIRTUAL_HANDLER_PREFIX = "virtual:handler-extract:";
|
|
@@ -1028,9 +1156,13 @@ function exposeInternalIds(options) {
|
|
|
1028
1156
|
const staticHandlerModules = /* @__PURE__ */ new Map();
|
|
1029
1157
|
const virtualHandlers = /* @__PURE__ */ new Map();
|
|
1030
1158
|
const unsupportedShapeWarnings = /* @__PURE__ */ new Set();
|
|
1159
|
+
const counter = createCounter(debug3, "expose-internal-ids");
|
|
1031
1160
|
return {
|
|
1032
1161
|
name: "@rangojs/router:expose-internal-ids",
|
|
1033
1162
|
enforce: "post",
|
|
1163
|
+
buildEnd() {
|
|
1164
|
+
counter?.flush();
|
|
1165
|
+
},
|
|
1034
1166
|
api: {
|
|
1035
1167
|
prerenderHandlerModules,
|
|
1036
1168
|
staticHandlerModules
|
|
@@ -1144,11 +1276,13 @@ ${lazyImports.join(",\n")}
|
|
|
1144
1276
|
// --------------- Unified transform ---------------
|
|
1145
1277
|
transform(code, id) {
|
|
1146
1278
|
if (id.includes("/node_modules/")) return;
|
|
1147
|
-
const
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
this.
|
|
1151
|
-
|
|
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
|
+
`
|
|
1152
1286
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
1153
1287
|
!! !!
|
|
1154
1288
|
!! WARNING: NamedRoutes imported in a CLIENT component! !!
|
|
@@ -1168,354 +1302,373 @@ ${lazyImports.join(",\n")}
|
|
|
1168
1302
|
!! !!
|
|
1169
1303
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
1170
1304
|
`
|
|
1171
|
-
|
|
1172
|
-
}
|
|
1173
|
-
if (!code.includes("@rangojs/router")) return;
|
|
1174
|
-
const has = detectImports(code);
|
|
1175
|
-
const hasLoaderCode = has.loader && code.includes("createLoader");
|
|
1176
|
-
const hasHandleCode = has.handle && code.includes("createHandle");
|
|
1177
|
-
const hasLocationStateCode = has.locationState && code.includes("createLocationState");
|
|
1178
|
-
const hasPrerenderHandlerCode = has.prerenderHandler && code.includes("Prerender");
|
|
1179
|
-
const hasStaticHandlerCode = has.staticHandler && code.includes("Static");
|
|
1180
|
-
if (!hasLoaderCode && !hasHandleCode && !hasLocationStateCode && !hasPrerenderHandlerCode && !hasStaticHandlerCode) {
|
|
1181
|
-
return;
|
|
1182
|
-
}
|
|
1183
|
-
const _fnNamesCache = /* @__PURE__ */ new Map();
|
|
1184
|
-
const _bindingsCache = /* @__PURE__ */ new Map();
|
|
1185
|
-
let _cachedAst;
|
|
1186
|
-
let _astParseFailed = false;
|
|
1187
|
-
let _astCodeRef = code;
|
|
1188
|
-
const getFnNames = (canonicalName) => {
|
|
1189
|
-
let result = _fnNamesCache.get(canonicalName);
|
|
1190
|
-
if (!result) {
|
|
1191
|
-
result = getImportedFnNames(code, canonicalName);
|
|
1192
|
-
_fnNamesCache.set(canonicalName, result);
|
|
1305
|
+
);
|
|
1193
1306
|
}
|
|
1194
|
-
return
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
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;
|
|
1201
1316
|
}
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
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));
|
|
1207
1368
|
}
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
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
|
+
}
|
|
1216
1380
|
}
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
const totalCalls = countCreateCallsForNames(code, fnNames);
|
|
1224
|
-
const supportedBindings = getBindings(code, fnNames).length;
|
|
1225
|
-
if (totalCalls <= supportedBindings) continue;
|
|
1226
|
-
const warnKey = `${id}::${cfg.fnName}`;
|
|
1227
|
-
if (unsupportedShapeWarnings.has(warnKey)) continue;
|
|
1228
|
-
unsupportedShapeWarnings.add(warnKey);
|
|
1229
|
-
this.warn(buildUnsupportedShapeWarning(filePath, cfg.fnName));
|
|
1230
|
-
}
|
|
1231
|
-
if (hasLoaderCode && isRscEnv) {
|
|
1232
|
-
const fnNames = getFnNames("createLoader");
|
|
1233
|
-
const bindings = getBindings(code, fnNames);
|
|
1234
|
-
for (const binding of bindings) {
|
|
1235
|
-
const exportName = binding.exportNames[0];
|
|
1236
|
-
const hashedId = hashId(filePath, exportName);
|
|
1237
|
-
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,
|
|
1238
1387
|
filePath,
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
}
|
|
1243
|
-
if (hasLoaderCode && !isRscEnv) {
|
|
1244
|
-
const fnNames = getFnNames("createLoader");
|
|
1245
|
-
const bindings = getBindings(code, fnNames);
|
|
1246
|
-
const stubResult = generateClientLoaderStubs(
|
|
1247
|
-
bindings,
|
|
1248
|
-
code,
|
|
1249
|
-
filePath,
|
|
1250
|
-
isBuild
|
|
1251
|
-
);
|
|
1252
|
-
if (stubResult) return stubResult;
|
|
1253
|
-
}
|
|
1254
|
-
if (hasPrerenderHandlerCode && !isRscEnv) {
|
|
1255
|
-
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1256
|
-
const bindings = getBindings(code, fnNames);
|
|
1257
|
-
const wholeFile = generateWholeFileStubs(
|
|
1258
|
-
PRERENDER_CONFIG,
|
|
1259
|
-
bindings,
|
|
1260
|
-
code,
|
|
1261
|
-
filePath,
|
|
1262
|
-
isBuild
|
|
1263
|
-
);
|
|
1264
|
-
if (wholeFile) return wholeFile;
|
|
1265
|
-
}
|
|
1266
|
-
if (hasPrerenderHandlerCode && isRscEnv && isBuild) {
|
|
1267
|
-
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1268
|
-
const exportNames = getBindings(code, fnNames).map(
|
|
1269
|
-
(b) => b.exportNames[0]
|
|
1270
|
-
);
|
|
1271
|
-
if (exportNames.length > 0) {
|
|
1272
|
-
prerenderHandlerModules.set(id, exportNames);
|
|
1388
|
+
isBuild
|
|
1389
|
+
);
|
|
1390
|
+
if (stubResult) return stubResult;
|
|
1273
1391
|
}
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
const fnNames = getFnNames(cfg.fnName);
|
|
1281
|
-
return { cfg, fnNames };
|
|
1282
|
-
});
|
|
1283
|
-
for (const { cfg, fnNames } of handlerConfigs) {
|
|
1284
|
-
const totalCalls = countCreateCallsForNames(code, fnNames);
|
|
1285
|
-
const supportedBindings = getBindings(code, fnNames).length;
|
|
1286
|
-
if (totalCalls > supportedBindings) {
|
|
1287
|
-
const iterS = new MagicString4(code);
|
|
1288
|
-
const result = transformInlineHandlers(
|
|
1289
|
-
cfg.fnName,
|
|
1290
|
-
VIRTUAL_HANDLER_PREFIX,
|
|
1291
|
-
iterS,
|
|
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,
|
|
1292
1398
|
code,
|
|
1293
1399
|
filePath,
|
|
1294
|
-
|
|
1295
|
-
id,
|
|
1296
|
-
parseAst2
|
|
1400
|
+
isBuild
|
|
1297
1401
|
);
|
|
1298
|
-
if (
|
|
1299
|
-
changed = true;
|
|
1300
|
-
code = iterS.toString();
|
|
1301
|
-
_bindingsCache.clear();
|
|
1302
|
-
}
|
|
1402
|
+
if (wholeFile) return wholeFile;
|
|
1303
1403
|
}
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
code,
|
|
1312
|
-
filePath,
|
|
1313
|
-
isBuild
|
|
1314
|
-
);
|
|
1315
|
-
if (wholeFile) return wholeFile;
|
|
1316
|
-
}
|
|
1317
|
-
if (!isRscEnv && (hasPrerenderHandlerCode || hasStaticHandlerCode)) {
|
|
1318
|
-
const prerenderFnNames = hasPrerenderHandlerCode ? getFnNames(PRERENDER_CONFIG.fnName) : [];
|
|
1319
|
-
const staticFnNames = hasStaticHandlerCode ? getFnNames(STATIC_CONFIG.fnName) : [];
|
|
1320
|
-
const loaderFnNames = hasLoaderCode ? getFnNames("createLoader") : [];
|
|
1321
|
-
const handleFnNames = hasHandleCode ? getFnNames("createHandle") : [];
|
|
1322
|
-
const lsFnNames = hasLocationStateCode ? getFnNames("createLocationState") : [];
|
|
1323
|
-
const allBindings = [];
|
|
1324
|
-
for (const fnNames of [
|
|
1325
|
-
prerenderFnNames,
|
|
1326
|
-
staticFnNames,
|
|
1327
|
-
loaderFnNames,
|
|
1328
|
-
handleFnNames,
|
|
1329
|
-
lsFnNames
|
|
1330
|
-
]) {
|
|
1331
|
-
if (fnNames.length > 0) {
|
|
1332
|
-
allBindings.push(...getBindings(code, fnNames));
|
|
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);
|
|
1333
1411
|
}
|
|
1334
1412
|
}
|
|
1335
|
-
let
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
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();
|
|
1345
1440
|
}
|
|
1346
1441
|
}
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
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,
|
|
1449
|
+
code,
|
|
1450
|
+
filePath,
|
|
1451
|
+
isBuild
|
|
1452
|
+
);
|
|
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));
|
|
1353
1471
|
}
|
|
1354
1472
|
}
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
});
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
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
|
+
}
|
|
1386
1518
|
}
|
|
1387
|
-
|
|
1388
|
-
const
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
);
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
const
|
|
1399
|
-
const activeFnNames = isHandle ? handleFnNames : lsFnNames;
|
|
1400
|
-
let rawCallee = code.slice(
|
|
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(
|
|
1401
1531
|
binding.callExprStart,
|
|
1402
|
-
binding.callOpenParenPos
|
|
1532
|
+
binding.callOpenParenPos + 1
|
|
1403
1533
|
);
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
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
|
|
1414
1548
|
);
|
|
1415
|
-
|
|
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
|
+
}
|
|
1416
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
|
+
}
|
|
1417
1579
|
lines.push(
|
|
1418
|
-
`export const ${primaryName} = ${
|
|
1419
|
-
);
|
|
1420
|
-
lines.push(
|
|
1421
|
-
`${primaryName}.__rsc_ls_key = "__rsc_ls_${stubId}";`
|
|
1580
|
+
`export const ${primaryName} = { __brand: "${brand}", $$id: "${stubId}" };`
|
|
1422
1581
|
);
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
}
|
|
1427
|
-
} else {
|
|
1428
|
-
let brand = "loader";
|
|
1429
|
-
if (prerenderFnNames.some((n) => fnCall.includes(n))) {
|
|
1430
|
-
brand = PRERENDER_CONFIG.brand;
|
|
1431
|
-
} else if (staticFnNames.some((n) => fnCall.includes(n))) {
|
|
1432
|
-
brand = STATIC_CONFIG.brand;
|
|
1433
|
-
}
|
|
1434
|
-
lines.push(
|
|
1435
|
-
`export const ${primaryName} = { __brand: "${brand}", $$id: "${stubId}" };`
|
|
1436
|
-
);
|
|
1437
|
-
for (const name of binding.exportNames.slice(1)) {
|
|
1438
|
-
lines.push(`export const ${name} = ${primaryName};`);
|
|
1582
|
+
for (const name of binding.exportNames.slice(1)) {
|
|
1583
|
+
lines.push(`export const ${name} = ${primaryName};`);
|
|
1584
|
+
}
|
|
1439
1585
|
}
|
|
1440
1586
|
}
|
|
1587
|
+
return { code: lines.join("\n") + "\n", map: null };
|
|
1441
1588
|
}
|
|
1442
|
-
return { code: lines.join("\n") + "\n", map: null };
|
|
1443
1589
|
}
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
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
|
+
}
|
|
1452
1598
|
}
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
}
|
|
1459
|
-
if (hasHandleCode) {
|
|
1460
|
-
const fnNames = getFnNames("createHandle");
|
|
1461
|
-
changed = transformHandles(
|
|
1462
|
-
getBindings(code, fnNames),
|
|
1463
|
-
s,
|
|
1464
|
-
code,
|
|
1465
|
-
filePath,
|
|
1466
|
-
isBuild
|
|
1467
|
-
) || changed;
|
|
1468
|
-
}
|
|
1469
|
-
if (hasLocationStateCode) {
|
|
1470
|
-
const fnNames = getFnNames("createLocationState");
|
|
1471
|
-
changed = transformLocationState(
|
|
1472
|
-
getBindings(code, fnNames),
|
|
1473
|
-
s,
|
|
1474
|
-
filePath,
|
|
1475
|
-
isBuild
|
|
1476
|
-
) || changed;
|
|
1477
|
-
}
|
|
1478
|
-
if (hasPrerenderHandlerCode) {
|
|
1479
|
-
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1480
|
-
const bindings = getBindings(code, fnNames);
|
|
1481
|
-
if (isRscEnv) {
|
|
1482
|
-
changed = transformHandlerIds(
|
|
1483
|
-
PRERENDER_CONFIG,
|
|
1484
|
-
bindings,
|
|
1599
|
+
const s = new MagicString4(code);
|
|
1600
|
+
if (hasLoaderCode) {
|
|
1601
|
+
const fnNames = getFnNames("createLoader");
|
|
1602
|
+
changed = transformLoaders(
|
|
1603
|
+
getBindings(code, fnNames),
|
|
1485
1604
|
s,
|
|
1486
1605
|
filePath,
|
|
1487
1606
|
isBuild
|
|
1488
1607
|
) || changed;
|
|
1489
|
-
}
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1608
|
+
}
|
|
1609
|
+
if (hasHandleCode) {
|
|
1610
|
+
const fnNames = getFnNames("createHandle");
|
|
1611
|
+
changed = transformHandles(
|
|
1612
|
+
getBindings(code, fnNames),
|
|
1493
1613
|
s,
|
|
1614
|
+
code,
|
|
1494
1615
|
filePath,
|
|
1495
1616
|
isBuild
|
|
1496
1617
|
) || changed;
|
|
1497
1618
|
}
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
if (isRscEnv) {
|
|
1503
|
-
changed = transformHandlerIds(
|
|
1504
|
-
STATIC_CONFIG,
|
|
1505
|
-
bindings,
|
|
1619
|
+
if (hasLocationStateCode) {
|
|
1620
|
+
const fnNames = getFnNames("createLocationState");
|
|
1621
|
+
changed = transformLocationState(
|
|
1622
|
+
getBindings(code, fnNames),
|
|
1506
1623
|
s,
|
|
1507
1624
|
filePath,
|
|
1508
1625
|
isBuild
|
|
1509
1626
|
) || changed;
|
|
1510
|
-
} else {
|
|
1511
|
-
changed = stubHandlerExprs(STATIC_CONFIG, bindings, s, filePath, isBuild) || changed;
|
|
1512
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);
|
|
1513
1671
|
}
|
|
1514
|
-
if (!changed) return;
|
|
1515
|
-
return {
|
|
1516
|
-
code: s.toString(),
|
|
1517
|
-
map: s.generateMap({ source: id, includeContent: true })
|
|
1518
|
-
};
|
|
1519
1672
|
}
|
|
1520
1673
|
};
|
|
1521
1674
|
}
|
|
@@ -1523,12 +1676,14 @@ ${lazyImports.join(",\n")}
|
|
|
1523
1676
|
// src/vite/plugins/use-cache-transform.ts
|
|
1524
1677
|
import path5 from "node:path";
|
|
1525
1678
|
import MagicString5 from "magic-string";
|
|
1679
|
+
var debug4 = createRangoDebugger(NS.transform);
|
|
1526
1680
|
var CACHE_RUNTIME_IMPORT = "@rangojs/router/cache-runtime";
|
|
1527
1681
|
var LAYOUT_TEMPLATE_PATTERN = /\/(layout|template)\.(tsx?|jsx?)$/;
|
|
1528
1682
|
function useCacheTransform() {
|
|
1529
1683
|
let projectRoot = "";
|
|
1530
1684
|
let isBuild = false;
|
|
1531
1685
|
let rscTransforms = null;
|
|
1686
|
+
const counter = createCounter(debug4, "use-cache");
|
|
1532
1687
|
return {
|
|
1533
1688
|
name: "@rangojs/router:use-cache",
|
|
1534
1689
|
enforce: "post",
|
|
@@ -1536,53 +1691,61 @@ function useCacheTransform() {
|
|
|
1536
1691
|
projectRoot = config.root;
|
|
1537
1692
|
isBuild = config.command === "build";
|
|
1538
1693
|
},
|
|
1694
|
+
buildEnd() {
|
|
1695
|
+
counter?.flush();
|
|
1696
|
+
},
|
|
1539
1697
|
async transform(code, id) {
|
|
1540
1698
|
if (this.environment?.name !== "rsc") return;
|
|
1541
1699
|
if (!code.includes("use cache")) return;
|
|
1542
1700
|
if (id.includes("/node_modules/") || id.startsWith("\0")) return;
|
|
1543
1701
|
if (!/\.(tsx?|jsx?|mjs)$/.test(id)) return;
|
|
1544
|
-
|
|
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;
|
|
1545
1717
|
try {
|
|
1546
|
-
|
|
1718
|
+
const { parseAst: parseAst4 } = await import("vite");
|
|
1719
|
+
ast = parseAst4(code);
|
|
1547
1720
|
} catch {
|
|
1548
1721
|
return;
|
|
1549
1722
|
}
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
hasDirective,
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
const isLayoutOrTemplate = LAYOUT_TEMPLATE_PATTERN.test(id);
|
|
1565
|
-
if (hasDirective(ast.body, "use cache")) {
|
|
1566
|
-
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(
|
|
1567
1737
|
code,
|
|
1568
1738
|
ast,
|
|
1569
1739
|
filePath,
|
|
1570
1740
|
id,
|
|
1571
1741
|
isBuild,
|
|
1572
|
-
|
|
1573
|
-
transformWrapExport
|
|
1742
|
+
transformHoistInlineDirective
|
|
1574
1743
|
);
|
|
1744
|
+
warnOnNearMissDirectives(ast, id, this.warn.bind(this));
|
|
1745
|
+
if (functionResult) return functionResult;
|
|
1746
|
+
} finally {
|
|
1747
|
+
counter?.record(id, performance.now() - start);
|
|
1575
1748
|
}
|
|
1576
|
-
const functionResult = transformFunctionLevelUseCache(
|
|
1577
|
-
code,
|
|
1578
|
-
ast,
|
|
1579
|
-
filePath,
|
|
1580
|
-
id,
|
|
1581
|
-
isBuild,
|
|
1582
|
-
transformHoistInlineDirective
|
|
1583
|
-
);
|
|
1584
|
-
warnOnNearMissDirectives(ast, id, this.warn.bind(this));
|
|
1585
|
-
if (functionResult) return functionResult;
|
|
1586
1749
|
}
|
|
1587
1750
|
};
|
|
1588
1751
|
}
|
|
@@ -1705,6 +1868,7 @@ function warnOnNearMissDirectives(ast, fileId, warn) {
|
|
|
1705
1868
|
}
|
|
1706
1869
|
|
|
1707
1870
|
// src/vite/plugins/client-ref-dedup.ts
|
|
1871
|
+
var debug5 = createRangoDebugger(NS.transform);
|
|
1708
1872
|
var CLIENT_IN_SERVER_PROXY_PREFIX = "virtual:vite-rsc/client-in-server-package-proxy/";
|
|
1709
1873
|
function extractPackageName(absolutePath) {
|
|
1710
1874
|
const marker = "/node_modules/";
|
|
@@ -1721,6 +1885,7 @@ function extractPackageName(absolutePath) {
|
|
|
1721
1885
|
}
|
|
1722
1886
|
function clientRefDedup() {
|
|
1723
1887
|
let clientExclude = [];
|
|
1888
|
+
const dedupedPackages = /* @__PURE__ */ new Set();
|
|
1724
1889
|
return {
|
|
1725
1890
|
name: "@rangojs/router:client-ref-dedup",
|
|
1726
1891
|
enforce: "pre",
|
|
@@ -1729,6 +1894,15 @@ function clientRefDedup() {
|
|
|
1729
1894
|
const clientEnv = config.environments?.["client"];
|
|
1730
1895
|
clientExclude = clientEnv?.optimizeDeps?.exclude ?? config.optimizeDeps?.exclude ?? [];
|
|
1731
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
|
+
},
|
|
1732
1906
|
resolveId(source, importer, options) {
|
|
1733
1907
|
if (this.environment?.name !== "client") return;
|
|
1734
1908
|
if (!importer?.includes(CLIENT_IN_SERVER_PROXY_PREFIX)) return;
|
|
@@ -1737,6 +1911,7 @@ function clientRefDedup() {
|
|
|
1737
1911
|
const packageName = extractPackageName(source);
|
|
1738
1912
|
if (!packageName) return;
|
|
1739
1913
|
if (clientExclude.includes(packageName)) return;
|
|
1914
|
+
if (debug5) dedupedPackages.add(packageName);
|
|
1740
1915
|
return `\0rango:dedup/${packageName}`;
|
|
1741
1916
|
},
|
|
1742
1917
|
load(id) {
|
|
@@ -1865,7 +2040,7 @@ import { resolve } from "node:path";
|
|
|
1865
2040
|
// package.json
|
|
1866
2041
|
var package_default = {
|
|
1867
2042
|
name: "@rangojs/router",
|
|
1868
|
-
version: "0.0.0-experimental.
|
|
2043
|
+
version: "0.0.0-experimental.b30bbf02",
|
|
1869
2044
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
1870
2045
|
keywords: [
|
|
1871
2046
|
"react",
|
|
@@ -2007,7 +2182,9 @@ var package_default = {
|
|
|
2007
2182
|
"test:unit:watch": "vitest"
|
|
2008
2183
|
},
|
|
2009
2184
|
dependencies: {
|
|
2185
|
+
"@types/debug": "^4.1.12",
|
|
2010
2186
|
"@vitejs/plugin-rsc": "^0.5.23",
|
|
2187
|
+
debug: "^4.4.1",
|
|
2011
2188
|
"magic-string": "^0.30.17",
|
|
2012
2189
|
picomatch: "^4.0.3",
|
|
2013
2190
|
"rsc-html-stream": "^0.0.7"
|
|
@@ -2994,6 +3171,7 @@ import * as Vite from "vite";
|
|
|
2994
3171
|
|
|
2995
3172
|
// src/vite/plugins/performance-tracks.ts
|
|
2996
3173
|
import { readFile } from "node:fs/promises";
|
|
3174
|
+
var debug6 = createRangoDebugger(NS.transform);
|
|
2997
3175
|
var RSDW_PATCH_RE = /((?:var|let|const)\s+\w+\s*=\s*root\._children\s*,\s*(\w+)\s*=\s*root\._debugInfo\s*[;,])/;
|
|
2998
3176
|
function buildPatchReplacement(match, debugInfoVar) {
|
|
2999
3177
|
return `${match}
|
|
@@ -3035,19 +3213,23 @@ function performanceTracksOptimizeDepsPlugin() {
|
|
|
3035
3213
|
};
|
|
3036
3214
|
}
|
|
3037
3215
|
function performanceTracksPlugin() {
|
|
3216
|
+
const counter = createCounter(debug6, "performance-tracks");
|
|
3038
3217
|
return {
|
|
3039
3218
|
name: "@rangojs/router:performance-tracks",
|
|
3219
|
+
buildEnd() {
|
|
3220
|
+
counter?.flush();
|
|
3221
|
+
},
|
|
3040
3222
|
transform(code, id) {
|
|
3041
3223
|
if (!id.includes("react-server-dom") || !id.includes("client")) return;
|
|
3042
|
-
const
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
);
|
|
3050
|
-
|
|
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
|
+
}
|
|
3051
3233
|
}
|
|
3052
3234
|
};
|
|
3053
3235
|
}
|
|
@@ -3194,11 +3376,10 @@ function createVersionInjectorPlugin(rscEntryPath) {
|
|
|
3194
3376
|
if (normalizedId !== normalizedEntry) {
|
|
3195
3377
|
return null;
|
|
3196
3378
|
}
|
|
3197
|
-
const prepend = [
|
|
3379
|
+
const prepend = [
|
|
3380
|
+
`import "virtual:rsc-router/routes-manifest";`
|
|
3381
|
+
];
|
|
3198
3382
|
let newCode = code;
|
|
3199
|
-
if (!code.includes("virtual:rsc-router/routes-manifest")) {
|
|
3200
|
-
prepend.push(`import "virtual:rsc-router/routes-manifest";`);
|
|
3201
|
-
}
|
|
3202
3383
|
const needsVersion = code.includes("createRSCHandler") && !code.includes("@rangojs/router:version") && /createRSCHandler\s*\(\s*\{/.test(code);
|
|
3203
3384
|
if (needsVersion) {
|
|
3204
3385
|
prepend.push(`import { VERSION } from "@rangojs/router:version";`);
|
|
@@ -3207,8 +3388,21 @@ function createVersionInjectorPlugin(rscEntryPath) {
|
|
|
3207
3388
|
"createRSCHandler({\n version: VERSION,"
|
|
3208
3389
|
);
|
|
3209
3390
|
}
|
|
3210
|
-
|
|
3211
|
-
|
|
3391
|
+
const lines = newCode.split("\n");
|
|
3392
|
+
let insertAt = 0;
|
|
3393
|
+
while (insertAt < lines.length) {
|
|
3394
|
+
const trimmed = lines[insertAt].trim();
|
|
3395
|
+
if (trimmed === "" || /^\/\/\/\s*<reference\b/.test(trimmed)) {
|
|
3396
|
+
insertAt++;
|
|
3397
|
+
} else {
|
|
3398
|
+
break;
|
|
3399
|
+
}
|
|
3400
|
+
}
|
|
3401
|
+
newCode = [
|
|
3402
|
+
...lines.slice(0, insertAt),
|
|
3403
|
+
...prepend,
|
|
3404
|
+
...lines.slice(insertAt)
|
|
3405
|
+
].join("\n");
|
|
3212
3406
|
return {
|
|
3213
3407
|
code: newCode,
|
|
3214
3408
|
map: null
|
|
@@ -3218,6 +3412,7 @@ function createVersionInjectorPlugin(rscEntryPath) {
|
|
|
3218
3412
|
}
|
|
3219
3413
|
|
|
3220
3414
|
// src/vite/plugins/cjs-to-esm.ts
|
|
3415
|
+
var debug7 = createRangoDebugger(NS.transform);
|
|
3221
3416
|
function createCjsToEsmPlugin() {
|
|
3222
3417
|
return {
|
|
3223
3418
|
name: "@rangojs/router:cjs-to-esm",
|
|
@@ -3227,6 +3422,7 @@ function createCjsToEsmPlugin() {
|
|
|
3227
3422
|
if (cleanId.includes("vendor/react-server-dom/client.browser.js") || cleanId.includes("vendor\\react-server-dom\\client.browser.js")) {
|
|
3228
3423
|
const isProd = process.env.NODE_ENV === "production";
|
|
3229
3424
|
const cjsFile = isProd ? "./cjs/react-server-dom-webpack-client.browser.production.js" : "./cjs/react-server-dom-webpack-client.browser.development.js";
|
|
3425
|
+
debug7?.("cjs-to-esm entry redirect %s", id);
|
|
3230
3426
|
return {
|
|
3231
3427
|
code: `export * from "${cjsFile}";`,
|
|
3232
3428
|
map: null
|
|
@@ -3262,6 +3458,7 @@ function createCjsToEsmPlugin() {
|
|
|
3262
3458
|
"export const $1 ="
|
|
3263
3459
|
);
|
|
3264
3460
|
transformed = license + "\n" + transformed;
|
|
3461
|
+
debug7?.("cjs-to-esm body rewrite %s", id);
|
|
3265
3462
|
return {
|
|
3266
3463
|
code: transformed,
|
|
3267
3464
|
map: null
|
|
@@ -3413,6 +3610,7 @@ function walk(node, visit) {
|
|
|
3413
3610
|
// src/vite/plugins/client-ref-hashing.ts
|
|
3414
3611
|
import { relative } from "node:path";
|
|
3415
3612
|
import { createHash as createHash2 } from "node:crypto";
|
|
3613
|
+
var debug8 = createRangoDebugger(NS.transform);
|
|
3416
3614
|
var CLIENT_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-package-proxy/";
|
|
3417
3615
|
var CLIENT_IN_SERVER_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-in-server-package-proxy/";
|
|
3418
3616
|
var FS_PREFIX = "/@fs/";
|
|
@@ -3451,6 +3649,7 @@ function transformClientRefs(code, projectRoot) {
|
|
|
3451
3649
|
return hasReplacement ? result : null;
|
|
3452
3650
|
}
|
|
3453
3651
|
function hashClientRefs(projectRoot) {
|
|
3652
|
+
const counter = createCounter(debug8, "hash-client-refs");
|
|
3454
3653
|
return {
|
|
3455
3654
|
name: "@rangojs/router:hash-client-refs",
|
|
3456
3655
|
// Run after the RSC plugin's transform (default enforce is normal)
|
|
@@ -3458,10 +3657,18 @@ function hashClientRefs(projectRoot) {
|
|
|
3458
3657
|
applyToEnvironment(env) {
|
|
3459
3658
|
return env.name === "rsc";
|
|
3460
3659
|
},
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3660
|
+
buildEnd() {
|
|
3661
|
+
counter?.flush();
|
|
3662
|
+
},
|
|
3663
|
+
transform(code, id) {
|
|
3664
|
+
const start = counter ? performance.now() : 0;
|
|
3665
|
+
try {
|
|
3666
|
+
const result = transformClientRefs(code, projectRoot);
|
|
3667
|
+
if (result === null) return;
|
|
3668
|
+
return { code: result, map: null };
|
|
3669
|
+
} finally {
|
|
3670
|
+
counter?.record(id, performance.now() - start);
|
|
3671
|
+
}
|
|
3465
3672
|
}
|
|
3466
3673
|
};
|
|
3467
3674
|
}
|
|
@@ -3589,6 +3796,12 @@ function markSelfGenWrite(state, filePath, content) {
|
|
|
3589
3796
|
state.selfWrittenGenFiles.set(filePath, { at: Date.now(), hash });
|
|
3590
3797
|
}
|
|
3591
3798
|
function consumeSelfGenWrite(state, filePath) {
|
|
3799
|
+
return checkSelfGenWrite(state, filePath, true);
|
|
3800
|
+
}
|
|
3801
|
+
function peekSelfGenWrite(state, filePath) {
|
|
3802
|
+
return checkSelfGenWrite(state, filePath, false);
|
|
3803
|
+
}
|
|
3804
|
+
function checkSelfGenWrite(state, filePath, consume) {
|
|
3592
3805
|
const info = state.selfWrittenGenFiles.get(filePath);
|
|
3593
3806
|
if (!info) return false;
|
|
3594
3807
|
if (Date.now() - info.at > state.SELF_WRITE_WINDOW_MS) {
|
|
@@ -3599,7 +3812,7 @@ function consumeSelfGenWrite(state, filePath) {
|
|
|
3599
3812
|
const current = readFileSync3(filePath, "utf-8");
|
|
3600
3813
|
const currentHash = createHash3("sha256").update(current).digest("hex");
|
|
3601
3814
|
if (currentHash === info.hash) {
|
|
3602
|
-
state.selfWrittenGenFiles.delete(filePath);
|
|
3815
|
+
if (consume) state.selfWrittenGenFiles.delete(filePath);
|
|
3603
3816
|
return true;
|
|
3604
3817
|
}
|
|
3605
3818
|
return false;
|
|
@@ -3821,8 +4034,14 @@ function copyStagedBuildAssets(projectRoot, fileNames) {
|
|
|
3821
4034
|
}
|
|
3822
4035
|
|
|
3823
4036
|
// src/vite/discovery/prerender-collection.ts
|
|
4037
|
+
var debug9 = createRangoDebugger(NS.prerender);
|
|
3824
4038
|
async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
3825
4039
|
if (!state.opts?.enableBuildPrerender || !state.isBuildMode) return;
|
|
4040
|
+
const overallStart = debug9 ? performance.now() : 0;
|
|
4041
|
+
debug9?.(
|
|
4042
|
+
"expandPrerenderRoutes: start (%d router manifest(s))",
|
|
4043
|
+
allManifests.length
|
|
4044
|
+
);
|
|
3826
4045
|
const entries = [];
|
|
3827
4046
|
const allRoutes = {};
|
|
3828
4047
|
for (const { manifest: m } of allManifests) {
|
|
@@ -3872,6 +4091,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3872
4091
|
});
|
|
3873
4092
|
} else {
|
|
3874
4093
|
if (def?.getParams) {
|
|
4094
|
+
const getParamsStart = debug9 ? performance.now() : 0;
|
|
3875
4095
|
try {
|
|
3876
4096
|
const buildVars = {};
|
|
3877
4097
|
const buildEnv = state.resolvedBuildEnv;
|
|
@@ -3890,6 +4110,12 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3890
4110
|
}
|
|
3891
4111
|
};
|
|
3892
4112
|
const paramsList = await def.getParams(getParamsCtx);
|
|
4113
|
+
debug9?.(
|
|
4114
|
+
"getParams %s -> %d params (%sms)",
|
|
4115
|
+
routeName,
|
|
4116
|
+
paramsList.length,
|
|
4117
|
+
(performance.now() - getParamsStart).toFixed(1)
|
|
4118
|
+
);
|
|
3893
4119
|
const concurrency = def.options?.concurrency ?? 1;
|
|
3894
4120
|
const hasBuildVars = Object.keys(buildVars).length > 0 || Object.getOwnPropertySymbols(buildVars).length > 0;
|
|
3895
4121
|
for (const params of paramsList) {
|
|
@@ -3955,12 +4181,23 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3955
4181
|
);
|
|
3956
4182
|
}
|
|
3957
4183
|
}
|
|
3958
|
-
if (entries.length === 0)
|
|
4184
|
+
if (entries.length === 0) {
|
|
4185
|
+
debug9?.(
|
|
4186
|
+
"no prerender entries (done in %sms)",
|
|
4187
|
+
(performance.now() - overallStart).toFixed(1)
|
|
4188
|
+
);
|
|
4189
|
+
return;
|
|
4190
|
+
}
|
|
3959
4191
|
const maxConcurrency = Math.max(...entries.map((e) => e.concurrency));
|
|
3960
4192
|
const concurrencyNote = maxConcurrency > 1 ? ` (concurrency: ${maxConcurrency})` : "";
|
|
3961
4193
|
console.log(
|
|
3962
4194
|
`[rsc-router] Pre-rendering ${entries.length} URL(s)${concurrencyNote}...`
|
|
3963
4195
|
);
|
|
4196
|
+
debug9?.(
|
|
4197
|
+
"prerender loop: %d entries, max concurrency %d",
|
|
4198
|
+
entries.length,
|
|
4199
|
+
maxConcurrency
|
|
4200
|
+
);
|
|
3964
4201
|
const { hashParams } = await rscEnv.runner.import("@rangojs/router/build");
|
|
3965
4202
|
const manifestEntries = {};
|
|
3966
4203
|
let doneCount = 0;
|
|
@@ -4067,10 +4304,22 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
4067
4304
|
console.log(
|
|
4068
4305
|
`[rsc-router] Pre-render complete: ${parts.join(", ")} (${totalElapsed}ms total)`
|
|
4069
4306
|
);
|
|
4307
|
+
debug9?.(
|
|
4308
|
+
"expandPrerenderRoutes done: %d done, %d skipped, %sms (overall %sms)",
|
|
4309
|
+
doneCount,
|
|
4310
|
+
skipCount,
|
|
4311
|
+
totalElapsed,
|
|
4312
|
+
(performance.now() - overallStart).toFixed(1)
|
|
4313
|
+
);
|
|
4070
4314
|
}
|
|
4071
4315
|
async function renderStaticHandlers(state, rscEnv, registry) {
|
|
4072
4316
|
if (!state.opts?.enableBuildPrerender || !state.isBuildMode || !state.resolvedStaticModules?.size)
|
|
4073
4317
|
return;
|
|
4318
|
+
const overallStart = debug9 ? performance.now() : 0;
|
|
4319
|
+
debug9?.(
|
|
4320
|
+
"renderStaticHandlers: start (%d static module(s))",
|
|
4321
|
+
state.resolvedStaticModules.size
|
|
4322
|
+
);
|
|
4074
4323
|
const manifestEntries = {};
|
|
4075
4324
|
let staticDone = 0;
|
|
4076
4325
|
let staticSkip = 0;
|
|
@@ -4160,13 +4409,29 @@ async function renderStaticHandlers(state, rscEnv, registry) {
|
|
|
4160
4409
|
console.log(
|
|
4161
4410
|
`[rsc-router] Static render complete: ${staticParts.join(", ")} (${totalStaticElapsed}ms total)`
|
|
4162
4411
|
);
|
|
4412
|
+
debug9?.(
|
|
4413
|
+
"renderStaticHandlers done: %d done, %d skipped, %sms (overall %sms)",
|
|
4414
|
+
staticDone,
|
|
4415
|
+
staticSkip,
|
|
4416
|
+
totalStaticElapsed,
|
|
4417
|
+
(performance.now() - overallStart).toFixed(1)
|
|
4418
|
+
);
|
|
4163
4419
|
}
|
|
4164
4420
|
|
|
4165
4421
|
// src/vite/discovery/discover-routers.ts
|
|
4422
|
+
var debug10 = createRangoDebugger(NS.discovery);
|
|
4166
4423
|
async function discoverRouters(state, rscEnv) {
|
|
4167
4424
|
if (!state.resolvedEntryPath) return;
|
|
4168
|
-
await
|
|
4169
|
-
|
|
4425
|
+
await timed(
|
|
4426
|
+
debug10,
|
|
4427
|
+
"inner: import entry",
|
|
4428
|
+
() => rscEnv.runner.import(state.resolvedEntryPath)
|
|
4429
|
+
);
|
|
4430
|
+
const serverMod = await timed(
|
|
4431
|
+
debug10,
|
|
4432
|
+
"inner: import @rangojs/router/server",
|
|
4433
|
+
() => rscEnv.runner.import("@rangojs/router/server")
|
|
4434
|
+
);
|
|
4170
4435
|
let registry = serverMod.RouterRegistry;
|
|
4171
4436
|
if (!registry || registry.size === 0) {
|
|
4172
4437
|
try {
|
|
@@ -4208,8 +4473,13 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4208
4473
|
);
|
|
4209
4474
|
}
|
|
4210
4475
|
}
|
|
4211
|
-
const buildMod = await
|
|
4476
|
+
const buildMod = await timed(
|
|
4477
|
+
debug10,
|
|
4478
|
+
"inner: import @rangojs/router/build",
|
|
4479
|
+
() => rscEnv.runner.import("@rangojs/router/build")
|
|
4480
|
+
);
|
|
4212
4481
|
const generateManifestFull = buildMod.generateManifestFull;
|
|
4482
|
+
debug10?.("inner: found %d router(s) in registry", registry.size);
|
|
4213
4483
|
const nestedRouterConflict = findNestedRouterConflict(
|
|
4214
4484
|
[...registry.values()].map((router) => router.__sourceFile).filter(
|
|
4215
4485
|
(sourceFile) => typeof sourceFile === "string"
|
|
@@ -4228,6 +4498,7 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4228
4498
|
let mergedRouteTrailingSlash = {};
|
|
4229
4499
|
let routerMountIndex = 0;
|
|
4230
4500
|
const allManifests = [];
|
|
4501
|
+
const manifestGenStart = debug10 ? performance.now() : 0;
|
|
4231
4502
|
for (const [id, router] of registry) {
|
|
4232
4503
|
if (!router.urlpatterns || !generateManifestFull) {
|
|
4233
4504
|
continue;
|
|
@@ -4302,7 +4573,13 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4302
4573
|
);
|
|
4303
4574
|
}
|
|
4304
4575
|
}
|
|
4576
|
+
debug10?.(
|
|
4577
|
+
"inner: generated manifests for %d router(s) (%sms)",
|
|
4578
|
+
allManifests.length,
|
|
4579
|
+
(performance.now() - manifestGenStart).toFixed(1)
|
|
4580
|
+
);
|
|
4305
4581
|
let newMergedRouteTrie = null;
|
|
4582
|
+
const trieStart = debug10 ? performance.now() : 0;
|
|
4306
4583
|
if (Object.keys(newMergedRouteManifest).length > 0) {
|
|
4307
4584
|
const buildRouteTrie = buildMod.buildRouteTrie;
|
|
4308
4585
|
if (buildRouteTrie && mergedRouteAncestry) {
|
|
@@ -4365,6 +4642,10 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4365
4642
|
}
|
|
4366
4643
|
}
|
|
4367
4644
|
}
|
|
4645
|
+
debug10?.(
|
|
4646
|
+
"inner: trie build done (%sms)",
|
|
4647
|
+
(performance.now() - trieStart).toFixed(1)
|
|
4648
|
+
);
|
|
4368
4649
|
state.mergedRouteManifest = newMergedRouteManifest;
|
|
4369
4650
|
state.mergedPrecomputedEntries = newMergedPrecomputedEntries;
|
|
4370
4651
|
state.perRouterManifests = newPerRouterManifests;
|
|
@@ -4804,7 +5085,85 @@ function postprocessBundle(state) {
|
|
|
4804
5085
|
}
|
|
4805
5086
|
}
|
|
4806
5087
|
|
|
5088
|
+
// src/vite/discovery/gate-state.ts
|
|
5089
|
+
function createDiscoveryGate(s, debug11) {
|
|
5090
|
+
let gatePending = false;
|
|
5091
|
+
let gateResolver = () => {
|
|
5092
|
+
};
|
|
5093
|
+
let inProgress = false;
|
|
5094
|
+
let queued = false;
|
|
5095
|
+
let pendingEvents = false;
|
|
5096
|
+
const beginGate = () => {
|
|
5097
|
+
if (gatePending) return;
|
|
5098
|
+
s.discoveryDone = new Promise((resolve10) => {
|
|
5099
|
+
gateResolver = resolve10;
|
|
5100
|
+
});
|
|
5101
|
+
gatePending = true;
|
|
5102
|
+
};
|
|
5103
|
+
const resolveGate = () => {
|
|
5104
|
+
if (!gatePending) return;
|
|
5105
|
+
if (inProgress || queued || pendingEvents) {
|
|
5106
|
+
debug11?.(
|
|
5107
|
+
"hmr: resolveGate deferred \u2014 work in flight (inProgress=%s queued=%s pendingEvents=%s)",
|
|
5108
|
+
inProgress,
|
|
5109
|
+
queued,
|
|
5110
|
+
pendingEvents
|
|
5111
|
+
);
|
|
5112
|
+
return;
|
|
5113
|
+
}
|
|
5114
|
+
gatePending = false;
|
|
5115
|
+
debug11?.("hmr: discoveryDone resolved");
|
|
5116
|
+
gateResolver();
|
|
5117
|
+
};
|
|
5118
|
+
const noteRouteEvent = () => {
|
|
5119
|
+
pendingEvents = true;
|
|
5120
|
+
beginGate();
|
|
5121
|
+
};
|
|
5122
|
+
const runRefreshCycle = async (work) => {
|
|
5123
|
+
if (inProgress) {
|
|
5124
|
+
queued = true;
|
|
5125
|
+
debug11?.("hmr: rediscovery in flight \u2014 queued for a follow-up cycle");
|
|
5126
|
+
return;
|
|
5127
|
+
}
|
|
5128
|
+
pendingEvents = false;
|
|
5129
|
+
inProgress = true;
|
|
5130
|
+
try {
|
|
5131
|
+
await work();
|
|
5132
|
+
} finally {
|
|
5133
|
+
inProgress = false;
|
|
5134
|
+
if (queued) {
|
|
5135
|
+
queued = false;
|
|
5136
|
+
debug11?.("hmr: consuming queued rediscovery");
|
|
5137
|
+
runRefreshCycle(work).catch((err) => {
|
|
5138
|
+
debug11?.(
|
|
5139
|
+
"hmr: queued cycle rejected \u2014 releasing gate (%s)",
|
|
5140
|
+
err instanceof Error ? err.message : String(err)
|
|
5141
|
+
);
|
|
5142
|
+
resolveGate();
|
|
5143
|
+
});
|
|
5144
|
+
} else if (pendingEvents) {
|
|
5145
|
+
debug11?.(
|
|
5146
|
+
"hmr: holding gate for pending events (debounce not yet fired)"
|
|
5147
|
+
);
|
|
5148
|
+
} else {
|
|
5149
|
+
resolveGate();
|
|
5150
|
+
}
|
|
5151
|
+
}
|
|
5152
|
+
};
|
|
5153
|
+
return {
|
|
5154
|
+
beginGate,
|
|
5155
|
+
resolveGate,
|
|
5156
|
+
noteRouteEvent,
|
|
5157
|
+
runRefreshCycle,
|
|
5158
|
+
state: () => ({ gatePending, inProgress, queued, pendingEvents })
|
|
5159
|
+
};
|
|
5160
|
+
}
|
|
5161
|
+
|
|
4807
5162
|
// src/vite/router-discovery.ts
|
|
5163
|
+
var debugDiscovery = createRangoDebugger(NS.discovery);
|
|
5164
|
+
var debugRoutes = createRangoDebugger(NS.routes);
|
|
5165
|
+
var debugBuild = createRangoDebugger(NS.build);
|
|
5166
|
+
var debugDev = createRangoDebugger(NS.dev);
|
|
4808
5167
|
var loaderHookRegistered = false;
|
|
4809
5168
|
function ensureCloudflareProtocolLoaderRegistered() {
|
|
4810
5169
|
if (loaderHookRegistered) return;
|
|
@@ -4964,6 +5323,9 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4964
5323
|
const discoveryPromise = new Promise((resolve10) => {
|
|
4965
5324
|
resolveDiscovery = resolve10;
|
|
4966
5325
|
});
|
|
5326
|
+
const gate = createDiscoveryGate(s, debugDiscovery);
|
|
5327
|
+
const beginDiscoveryGate = gate.beginGate;
|
|
5328
|
+
const resolveDiscoveryGate = gate.resolveGate;
|
|
4967
5329
|
const getDevServerOrigin = () => server.resolvedUrls?.local?.[0]?.replace(/\/$/, "") || `http://localhost:${server.config.server.port || 5173}`;
|
|
4968
5330
|
let prerenderTempServer = null;
|
|
4969
5331
|
let prerenderNodeRegistry = null;
|
|
@@ -4976,40 +5338,180 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4976
5338
|
releaseBuildEnv(s).catch(() => {
|
|
4977
5339
|
});
|
|
4978
5340
|
});
|
|
5341
|
+
async function importEntryAndRegistry(tempRscEnv) {
|
|
5342
|
+
const flagAlreadySet = !!globalThis.__rscRouterDiscoveryActive;
|
|
5343
|
+
if (!flagAlreadySet) {
|
|
5344
|
+
globalThis.__rscRouterDiscoveryActive = true;
|
|
5345
|
+
}
|
|
5346
|
+
try {
|
|
5347
|
+
debugDiscovery?.(
|
|
5348
|
+
"importEntryAndRegistry: importing entry (flag=%s)",
|
|
5349
|
+
globalThis.__rscRouterDiscoveryActive ?? false
|
|
5350
|
+
);
|
|
5351
|
+
await tempRscEnv.runner.import(s.resolvedEntryPath);
|
|
5352
|
+
debugDiscovery?.(
|
|
5353
|
+
"importEntryAndRegistry: entry import OK, fetching RouterRegistry"
|
|
5354
|
+
);
|
|
5355
|
+
const serverMod = await tempRscEnv.runner.import(
|
|
5356
|
+
"@rangojs/router/server"
|
|
5357
|
+
);
|
|
5358
|
+
prerenderNodeRegistry = serverMod.RouterRegistry;
|
|
5359
|
+
debugDiscovery?.(
|
|
5360
|
+
"importEntryAndRegistry: registry size=%d",
|
|
5361
|
+
prerenderNodeRegistry?.size ?? 0
|
|
5362
|
+
);
|
|
5363
|
+
} finally {
|
|
5364
|
+
if (!flagAlreadySet) {
|
|
5365
|
+
delete globalThis.__rscRouterDiscoveryActive;
|
|
5366
|
+
debugDiscovery?.(
|
|
5367
|
+
"importEntryAndRegistry: cleared __rscRouterDiscoveryActive"
|
|
5368
|
+
);
|
|
5369
|
+
}
|
|
5370
|
+
}
|
|
5371
|
+
}
|
|
4979
5372
|
async function getOrCreateTempServer() {
|
|
4980
|
-
if (
|
|
4981
|
-
|
|
5373
|
+
if (prerenderTempServer) {
|
|
5374
|
+
const existingEnv = prerenderTempServer.environments?.rsc;
|
|
5375
|
+
if (existingEnv?.runner) {
|
|
5376
|
+
if (prerenderNodeRegistry) {
|
|
5377
|
+
debugDiscovery?.(
|
|
5378
|
+
"getOrCreateTempServer: cached temp runner reused"
|
|
5379
|
+
);
|
|
5380
|
+
return existingEnv;
|
|
5381
|
+
}
|
|
5382
|
+
debugDiscovery?.(
|
|
5383
|
+
"getOrCreateTempServer: server alive but registry missing \u2014 re-importing"
|
|
5384
|
+
);
|
|
5385
|
+
try {
|
|
5386
|
+
await importEntryAndRegistry(existingEnv);
|
|
5387
|
+
return existingEnv;
|
|
5388
|
+
} catch (err) {
|
|
5389
|
+
debugDiscovery?.(
|
|
5390
|
+
"getOrCreateTempServer: reuse import failed (%s) \u2014 closing orphan and creating fresh",
|
|
5391
|
+
err?.message ?? String(err)
|
|
5392
|
+
);
|
|
5393
|
+
await prerenderTempServer.close().catch(() => {
|
|
5394
|
+
});
|
|
5395
|
+
prerenderTempServer = null;
|
|
5396
|
+
prerenderNodeRegistry = null;
|
|
5397
|
+
}
|
|
5398
|
+
} else {
|
|
5399
|
+
debugDiscovery?.(
|
|
5400
|
+
"getOrCreateTempServer: existing server has no rsc.runner \u2014 closing and recreating"
|
|
5401
|
+
);
|
|
5402
|
+
await prerenderTempServer.close().catch(() => {
|
|
5403
|
+
});
|
|
5404
|
+
prerenderTempServer = null;
|
|
5405
|
+
prerenderNodeRegistry = null;
|
|
5406
|
+
}
|
|
4982
5407
|
}
|
|
5408
|
+
debugDiscovery?.(
|
|
5409
|
+
"getOrCreateTempServer: creating new temp server, entry=%s",
|
|
5410
|
+
s.resolvedEntryPath ?? "(unset)"
|
|
5411
|
+
);
|
|
4983
5412
|
try {
|
|
4984
5413
|
prerenderTempServer = await createTempRscServer(s, {
|
|
4985
5414
|
cacheDir: "node_modules/.vite_prerender"
|
|
4986
5415
|
});
|
|
4987
5416
|
const tempRscEnv = prerenderTempServer.environments?.rsc;
|
|
4988
5417
|
if (tempRscEnv?.runner) {
|
|
4989
|
-
await tempRscEnv
|
|
4990
|
-
const serverMod = await tempRscEnv.runner.import(
|
|
4991
|
-
"@rangojs/router/server"
|
|
4992
|
-
);
|
|
4993
|
-
prerenderNodeRegistry = serverMod.RouterRegistry;
|
|
5418
|
+
await importEntryAndRegistry(tempRscEnv);
|
|
4994
5419
|
return tempRscEnv;
|
|
4995
5420
|
}
|
|
5421
|
+
debugDiscovery?.(
|
|
5422
|
+
"getOrCreateTempServer: tempRscEnv.runner unavailable"
|
|
5423
|
+
);
|
|
4996
5424
|
} catch (err) {
|
|
5425
|
+
debugDiscovery?.(
|
|
5426
|
+
"getOrCreateTempServer: FAILED message=%s",
|
|
5427
|
+
err.message
|
|
5428
|
+
);
|
|
4997
5429
|
console.warn(
|
|
4998
5430
|
`[rsc-router] Failed to create temp runner: ${err.message}`
|
|
4999
5431
|
);
|
|
5000
5432
|
}
|
|
5001
5433
|
return null;
|
|
5002
5434
|
}
|
|
5435
|
+
async function clearTempRegistries(tempRscEnv) {
|
|
5436
|
+
try {
|
|
5437
|
+
const serverMod = await tempRscEnv.runner.import(
|
|
5438
|
+
"@rangojs/router/server"
|
|
5439
|
+
);
|
|
5440
|
+
if (typeof serverMod?.RouterRegistry?.clear === "function") {
|
|
5441
|
+
serverMod.RouterRegistry.clear();
|
|
5442
|
+
}
|
|
5443
|
+
if (typeof serverMod?.HostRouterRegistry?.clear === "function") {
|
|
5444
|
+
serverMod.HostRouterRegistry.clear();
|
|
5445
|
+
}
|
|
5446
|
+
debugDiscovery?.(
|
|
5447
|
+
"clearTempRegistries: cleared RouterRegistry + HostRouterRegistry"
|
|
5448
|
+
);
|
|
5449
|
+
} catch (err) {
|
|
5450
|
+
debugDiscovery?.(
|
|
5451
|
+
"clearTempRegistries: import @rangojs/router/server failed (%s)",
|
|
5452
|
+
err?.message ?? String(err)
|
|
5453
|
+
);
|
|
5454
|
+
}
|
|
5455
|
+
}
|
|
5456
|
+
async function refreshTempRscEnv() {
|
|
5457
|
+
let tempRscEnv = await getOrCreateTempServer();
|
|
5458
|
+
if (!tempRscEnv) return null;
|
|
5459
|
+
const envGraph = tempRscEnv.moduleGraph;
|
|
5460
|
+
const serverGraph = prerenderTempServer?.moduleGraph;
|
|
5461
|
+
const target = envGraph?.invalidateAll ? envGraph : serverGraph?.invalidateAll ? serverGraph : null;
|
|
5462
|
+
if (!target) {
|
|
5463
|
+
debugDiscovery?.(
|
|
5464
|
+
"refreshTempRscEnv: invalidateAll unavailable on env+server graphs, falling back to close+recreate"
|
|
5465
|
+
);
|
|
5466
|
+
if (prerenderTempServer) {
|
|
5467
|
+
await prerenderTempServer.close().catch(() => {
|
|
5468
|
+
});
|
|
5469
|
+
prerenderTempServer = null;
|
|
5470
|
+
prerenderNodeRegistry = null;
|
|
5471
|
+
}
|
|
5472
|
+
return await getOrCreateTempServer();
|
|
5473
|
+
}
|
|
5474
|
+
debugDiscovery?.(
|
|
5475
|
+
"refreshTempRscEnv: invalidating module graph (%s)",
|
|
5476
|
+
envGraph?.invalidateAll ? "env" : "server"
|
|
5477
|
+
);
|
|
5478
|
+
target.invalidateAll();
|
|
5479
|
+
prerenderNodeRegistry = null;
|
|
5480
|
+
await clearTempRegistries(tempRscEnv);
|
|
5481
|
+
await importEntryAndRegistry(tempRscEnv);
|
|
5482
|
+
return tempRscEnv;
|
|
5483
|
+
}
|
|
5003
5484
|
const discover = async () => {
|
|
5485
|
+
const discoverStart = performance.now();
|
|
5004
5486
|
const rscEnv = server.environments?.rsc;
|
|
5005
5487
|
if (!rscEnv?.runner) {
|
|
5488
|
+
debugDiscovery?.(
|
|
5489
|
+
"dev: cloudflare path start, __rscRouterDiscoveryActive=%s",
|
|
5490
|
+
globalThis.__rscRouterDiscoveryActive ?? false
|
|
5491
|
+
);
|
|
5006
5492
|
s.devServerOrigin = getDevServerOrigin();
|
|
5007
5493
|
try {
|
|
5008
|
-
await
|
|
5009
|
-
|
|
5494
|
+
await timed(
|
|
5495
|
+
debugDiscovery,
|
|
5496
|
+
"acquireBuildEnv",
|
|
5497
|
+
() => acquireBuildEnv(s, viteCommand, viteMode)
|
|
5498
|
+
);
|
|
5499
|
+
const tempRscEnv = await timed(
|
|
5500
|
+
debugDiscovery,
|
|
5501
|
+
"getOrCreateTempServer",
|
|
5502
|
+
() => getOrCreateTempServer()
|
|
5503
|
+
);
|
|
5010
5504
|
if (tempRscEnv) {
|
|
5011
|
-
await
|
|
5012
|
-
|
|
5505
|
+
await timed(
|
|
5506
|
+
debugDiscovery,
|
|
5507
|
+
"discoverRouters (cloudflare)",
|
|
5508
|
+
() => discoverRouters(s, tempRscEnv)
|
|
5509
|
+
);
|
|
5510
|
+
timedSync(
|
|
5511
|
+
debugDiscovery,
|
|
5512
|
+
"writeRouteTypesFiles",
|
|
5513
|
+
() => writeRouteTypesFiles(s)
|
|
5514
|
+
);
|
|
5013
5515
|
}
|
|
5014
5516
|
} catch (err) {
|
|
5015
5517
|
console.warn(
|
|
@@ -5017,33 +5519,62 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
5017
5519
|
${err.stack}`
|
|
5018
5520
|
);
|
|
5019
5521
|
}
|
|
5522
|
+
debugDiscovery?.(
|
|
5523
|
+
"dev discovery done (%sms)",
|
|
5524
|
+
(performance.now() - discoverStart).toFixed(1)
|
|
5525
|
+
);
|
|
5020
5526
|
resolveDiscovery();
|
|
5021
5527
|
return;
|
|
5022
5528
|
}
|
|
5023
5529
|
try {
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5530
|
+
debugDiscovery?.("dev: node path start");
|
|
5531
|
+
await timed(
|
|
5532
|
+
debugDiscovery,
|
|
5533
|
+
"acquireBuildEnv",
|
|
5534
|
+
() => acquireBuildEnv(s, viteCommand, viteMode)
|
|
5535
|
+
);
|
|
5536
|
+
const serverMod = await timed(
|
|
5537
|
+
debugDiscovery,
|
|
5538
|
+
"import @rangojs/router/server",
|
|
5539
|
+
() => rscEnv.runner.import("@rangojs/router/server")
|
|
5027
5540
|
);
|
|
5028
5541
|
if (serverMod?.setManifestReadyPromise) {
|
|
5029
5542
|
serverMod.setManifestReadyPromise(discoveryPromise);
|
|
5030
5543
|
}
|
|
5031
|
-
await
|
|
5544
|
+
await timed(
|
|
5545
|
+
debugDiscovery,
|
|
5546
|
+
"discoverRouters",
|
|
5547
|
+
() => discoverRouters(s, rscEnv)
|
|
5548
|
+
);
|
|
5032
5549
|
s.devServerOrigin = getDevServerOrigin();
|
|
5033
|
-
|
|
5034
|
-
|
|
5550
|
+
timedSync(
|
|
5551
|
+
debugDiscovery,
|
|
5552
|
+
"writeRouteTypesFiles",
|
|
5553
|
+
() => writeRouteTypesFiles(s)
|
|
5554
|
+
);
|
|
5555
|
+
await timed(
|
|
5556
|
+
debugDiscovery,
|
|
5557
|
+
"propagateDiscoveryState",
|
|
5558
|
+
() => propagateDiscoveryState(rscEnv)
|
|
5559
|
+
);
|
|
5035
5560
|
} catch (err) {
|
|
5036
5561
|
console.warn(
|
|
5037
5562
|
`[rsc-router] Router discovery failed: ${err.message}
|
|
5038
5563
|
${err.stack}`
|
|
5039
5564
|
);
|
|
5040
5565
|
} finally {
|
|
5566
|
+
debugDiscovery?.(
|
|
5567
|
+
"dev discovery done (%sms)",
|
|
5568
|
+
(performance.now() - discoverStart).toFixed(1)
|
|
5569
|
+
);
|
|
5041
5570
|
resolveDiscovery();
|
|
5042
5571
|
}
|
|
5043
5572
|
};
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5573
|
+
beginDiscoveryGate();
|
|
5574
|
+
setTimeout(
|
|
5575
|
+
() => discover().then(resolveDiscoveryGate, resolveDiscoveryGate),
|
|
5576
|
+
0
|
|
5577
|
+
);
|
|
5047
5578
|
let mainRegistry = null;
|
|
5048
5579
|
const propagateDiscoveryState = async (rscEnv) => {
|
|
5049
5580
|
const serverMod = await rscEnv.runner.import("@rangojs/router/server");
|
|
@@ -5078,12 +5609,23 @@ ${err.stack}`
|
|
|
5078
5609
|
}
|
|
5079
5610
|
};
|
|
5080
5611
|
server.middlewares.use("/__rsc_prerender", async (req, res) => {
|
|
5612
|
+
const reqStart = debugDev ? performance.now() : 0;
|
|
5613
|
+
const logResult = (status, note) => {
|
|
5614
|
+
debugDev?.(
|
|
5615
|
+
"/__rsc_prerender %s -> %d %s (%sms)",
|
|
5616
|
+
req.url,
|
|
5617
|
+
status,
|
|
5618
|
+
note,
|
|
5619
|
+
(performance.now() - reqStart).toFixed(1)
|
|
5620
|
+
);
|
|
5621
|
+
};
|
|
5081
5622
|
if (s.discoveryDone) await s.discoveryDone;
|
|
5082
5623
|
const url = new URL(req.url || "/", "http://localhost");
|
|
5083
5624
|
const pathname = url.searchParams.get("pathname");
|
|
5084
5625
|
if (!pathname) {
|
|
5085
5626
|
res.statusCode = 400;
|
|
5086
5627
|
res.end("Missing pathname");
|
|
5628
|
+
logResult(400, "missing pathname");
|
|
5087
5629
|
return;
|
|
5088
5630
|
}
|
|
5089
5631
|
const rscEnv = server.environments?.rsc;
|
|
@@ -5101,6 +5643,7 @@ ${err.stack}`
|
|
|
5101
5643
|
);
|
|
5102
5644
|
res.statusCode = 500;
|
|
5103
5645
|
res.end(`Prerender handler error: ${err.message}`);
|
|
5646
|
+
logResult(500, "module refresh failed");
|
|
5104
5647
|
return;
|
|
5105
5648
|
}
|
|
5106
5649
|
} else {
|
|
@@ -5115,6 +5658,7 @@ ${err.stack}`
|
|
|
5115
5658
|
if (!registry || registry.size === 0) {
|
|
5116
5659
|
res.statusCode = 503;
|
|
5117
5660
|
res.end("Prerender runner not available");
|
|
5661
|
+
logResult(503, "no registry");
|
|
5118
5662
|
return;
|
|
5119
5663
|
}
|
|
5120
5664
|
const wantIntercept = url.searchParams.get("intercept") === "1";
|
|
@@ -5149,6 +5693,7 @@ ${err.stack}`
|
|
|
5149
5693
|
payload = { segments: result.segments, handles: result.handles };
|
|
5150
5694
|
}
|
|
5151
5695
|
res.end(JSON.stringify(payload));
|
|
5696
|
+
logResult(200, `match ${result.routeName}`);
|
|
5152
5697
|
return;
|
|
5153
5698
|
} catch (err) {
|
|
5154
5699
|
console.warn(
|
|
@@ -5158,6 +5703,7 @@ ${err.stack}`
|
|
|
5158
5703
|
}
|
|
5159
5704
|
res.statusCode = 404;
|
|
5160
5705
|
res.end("No prerender match");
|
|
5706
|
+
logResult(404, "no match");
|
|
5161
5707
|
});
|
|
5162
5708
|
if (opts?.staticRouteTypesGeneration !== false) {
|
|
5163
5709
|
const isGeneratedRouteFile = (filePath) => filePath.endsWith(".gen.ts") && (filePath.includes("named-routes.gen.ts") || filePath.includes("urls.gen.ts"));
|
|
@@ -5177,42 +5723,96 @@ ${err.stack}`
|
|
|
5177
5723
|
return true;
|
|
5178
5724
|
};
|
|
5179
5725
|
let routeChangeTimer;
|
|
5180
|
-
let runtimeRediscoveryInProgress = false;
|
|
5181
5726
|
const refreshRuntimeDiscovery = async () => {
|
|
5182
5727
|
const rscEnv = server.environments?.rsc;
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5728
|
+
const hasMainRunner = !!rscEnv?.runner;
|
|
5729
|
+
if (!hasMainRunner && s.perRouterManifests.length === 0) return;
|
|
5730
|
+
await gate.runRefreshCycle(async () => {
|
|
5731
|
+
const hmrStart = performance.now();
|
|
5732
|
+
try {
|
|
5733
|
+
if (hasMainRunner) {
|
|
5734
|
+
await timed(
|
|
5735
|
+
debugDiscovery,
|
|
5736
|
+
"hmr discoverRouters",
|
|
5737
|
+
() => discoverRouters(s, rscEnv)
|
|
5738
|
+
);
|
|
5739
|
+
timedSync(
|
|
5740
|
+
debugDiscovery,
|
|
5741
|
+
"hmr writeRouteTypesFiles",
|
|
5742
|
+
() => writeRouteTypesFiles(s)
|
|
5743
|
+
);
|
|
5744
|
+
await timed(
|
|
5745
|
+
debugDiscovery,
|
|
5746
|
+
"hmr propagateDiscoveryState",
|
|
5747
|
+
() => propagateDiscoveryState(rscEnv)
|
|
5748
|
+
);
|
|
5749
|
+
} else {
|
|
5750
|
+
const tempRscEnv = await timed(
|
|
5751
|
+
debugDiscovery,
|
|
5752
|
+
"hmr refreshTempRscEnv (cloudflare)",
|
|
5753
|
+
() => refreshTempRscEnv()
|
|
5754
|
+
);
|
|
5755
|
+
if (!tempRscEnv) {
|
|
5756
|
+
throw new Error(
|
|
5757
|
+
"temp runner unavailable for cloudflare HMR rediscovery"
|
|
5758
|
+
);
|
|
5759
|
+
}
|
|
5760
|
+
await timed(
|
|
5761
|
+
debugDiscovery,
|
|
5762
|
+
"hmr discoverRouters (cloudflare)",
|
|
5763
|
+
() => discoverRouters(s, tempRscEnv)
|
|
5764
|
+
);
|
|
5765
|
+
timedSync(
|
|
5766
|
+
debugDiscovery,
|
|
5767
|
+
"hmr writeRouteTypesFiles",
|
|
5768
|
+
() => writeRouteTypesFiles(s)
|
|
5769
|
+
);
|
|
5770
|
+
}
|
|
5771
|
+
} catch (err) {
|
|
5772
|
+
console.warn(
|
|
5773
|
+
`[rsc-router] Runtime re-discovery failed: ${err.message}`
|
|
5774
|
+
);
|
|
5775
|
+
} finally {
|
|
5776
|
+
debugDiscovery?.(
|
|
5777
|
+
"hmr re-discovery done (%sms)",
|
|
5778
|
+
(performance.now() - hmrStart).toFixed(1)
|
|
5779
|
+
);
|
|
5780
|
+
}
|
|
5781
|
+
});
|
|
5196
5782
|
};
|
|
5197
5783
|
const scheduleRouteRegeneration = () => {
|
|
5198
5784
|
clearTimeout(routeChangeTimer);
|
|
5199
5785
|
routeChangeTimer = setTimeout(() => {
|
|
5200
5786
|
routeChangeTimer = void 0;
|
|
5787
|
+
const regenStart = debugDiscovery ? performance.now() : 0;
|
|
5788
|
+
const rscEnv = server.environments?.rsc;
|
|
5789
|
+
const skipStaticWrite = !rscEnv?.runner && s.perRouterManifests.length > 0;
|
|
5201
5790
|
try {
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5791
|
+
if (skipStaticWrite) {
|
|
5792
|
+
debugDiscovery?.(
|
|
5793
|
+
"watcher: skipping static write (cloudflare HMR \u2014 runtime rediscovery owns gen file)"
|
|
5794
|
+
);
|
|
5795
|
+
} else {
|
|
5796
|
+
writeCombinedRouteTypesWithTracking(s);
|
|
5797
|
+
if (s.perRouterManifests.length > 0) {
|
|
5798
|
+
supplementGenFilesWithRuntimeRoutes(s);
|
|
5799
|
+
}
|
|
5205
5800
|
}
|
|
5206
5801
|
} catch (err) {
|
|
5207
5802
|
console.error(
|
|
5208
5803
|
`[rsc-router] Route regeneration error: ${err.message}`
|
|
5209
5804
|
);
|
|
5210
5805
|
}
|
|
5806
|
+
debugDiscovery?.(
|
|
5807
|
+
"watcher: regenerated gen files (%sms)",
|
|
5808
|
+
(performance.now() - regenStart).toFixed(1)
|
|
5809
|
+
);
|
|
5211
5810
|
if (s.perRouterManifests.length > 0) {
|
|
5212
5811
|
refreshRuntimeDiscovery().catch((err) => {
|
|
5213
5812
|
console.warn(
|
|
5214
5813
|
`[rsc-router] Runtime re-discovery error: ${err.message}`
|
|
5215
5814
|
);
|
|
5815
|
+
resolveDiscoveryGate();
|
|
5216
5816
|
});
|
|
5217
5817
|
}
|
|
5218
5818
|
}, 100);
|
|
@@ -5230,6 +5830,12 @@ ${err.stack}`
|
|
|
5230
5830
|
const hasUrls = source.includes("urls(");
|
|
5231
5831
|
const hasCreateRouter = /\bcreateRouter\s*[<(]/.test(source);
|
|
5232
5832
|
if (!hasUrls && !hasCreateRouter) return;
|
|
5833
|
+
debugDiscovery?.(
|
|
5834
|
+
"watcher: %s matches (urls=%s, router=%s)",
|
|
5835
|
+
filePath,
|
|
5836
|
+
hasUrls,
|
|
5837
|
+
hasCreateRouter
|
|
5838
|
+
);
|
|
5233
5839
|
if (hasCreateRouter) {
|
|
5234
5840
|
const nestedRouterConflict = findNestedRouterConflict([
|
|
5235
5841
|
...s.cachedRouterFiles ?? [],
|
|
@@ -5243,6 +5849,9 @@ ${err.stack}`
|
|
|
5243
5849
|
}
|
|
5244
5850
|
s.cachedRouterFiles = void 0;
|
|
5245
5851
|
}
|
|
5852
|
+
if (s.perRouterManifests.length > 0) {
|
|
5853
|
+
gate.noteRouteEvent();
|
|
5854
|
+
}
|
|
5246
5855
|
scheduleRouteRegeneration();
|
|
5247
5856
|
} catch {
|
|
5248
5857
|
}
|
|
@@ -5262,15 +5871,31 @@ ${err.stack}`
|
|
|
5262
5871
|
// The manifest data is stored for the virtual module's load hook.
|
|
5263
5872
|
async buildStart() {
|
|
5264
5873
|
if (!s.isBuildMode) return;
|
|
5265
|
-
if (s.mergedRouteManifest !== null)
|
|
5874
|
+
if (s.mergedRouteManifest !== null) {
|
|
5875
|
+
debugDiscovery?.(
|
|
5876
|
+
"build: skip (already discovered, env=%s)",
|
|
5877
|
+
this.environment?.name ?? "?"
|
|
5878
|
+
);
|
|
5879
|
+
return;
|
|
5880
|
+
}
|
|
5881
|
+
const buildStartTime = performance.now();
|
|
5882
|
+
debugDiscovery?.("build: start (env=%s)", this.environment?.name ?? "?");
|
|
5266
5883
|
resetStagedBuildAssets(s.projectRoot);
|
|
5267
5884
|
s.prerenderManifestEntries = null;
|
|
5268
5885
|
s.staticManifestEntries = null;
|
|
5269
|
-
await
|
|
5886
|
+
await timed(
|
|
5887
|
+
debugDiscovery,
|
|
5888
|
+
"build acquireBuildEnv",
|
|
5889
|
+
() => acquireBuildEnv(s, viteCommand, viteMode)
|
|
5890
|
+
);
|
|
5270
5891
|
let tempServer = null;
|
|
5271
5892
|
globalThis.__rscRouterDiscoveryActive = true;
|
|
5272
5893
|
try {
|
|
5273
|
-
tempServer = await
|
|
5894
|
+
tempServer = await timed(
|
|
5895
|
+
debugDiscovery,
|
|
5896
|
+
"build createTempRscServer",
|
|
5897
|
+
() => createTempRscServer(s, { forceBuild: true })
|
|
5898
|
+
);
|
|
5274
5899
|
const rscEnv = tempServer.environments?.rsc;
|
|
5275
5900
|
if (!rscEnv?.runner) {
|
|
5276
5901
|
console.warn(
|
|
@@ -5284,8 +5909,16 @@ ${err.stack}`
|
|
|
5284
5909
|
if (tempIdsPlugin?.api?.staticHandlerModules) {
|
|
5285
5910
|
s.resolvedStaticModules = tempIdsPlugin.api.staticHandlerModules;
|
|
5286
5911
|
}
|
|
5287
|
-
await
|
|
5288
|
-
|
|
5912
|
+
await timed(
|
|
5913
|
+
debugDiscovery,
|
|
5914
|
+
"build discoverRouters",
|
|
5915
|
+
() => discoverRouters(s, rscEnv)
|
|
5916
|
+
);
|
|
5917
|
+
timedSync(
|
|
5918
|
+
debugDiscovery,
|
|
5919
|
+
"build writeRouteTypesFiles",
|
|
5920
|
+
() => writeRouteTypesFiles(s)
|
|
5921
|
+
);
|
|
5289
5922
|
} catch (err) {
|
|
5290
5923
|
const sourceFile = err.stack?.split("\n").find(
|
|
5291
5924
|
(line) => line.includes(s.projectRoot) && !line.includes("node_modules")
|
|
@@ -5304,9 +5937,45 @@ ${details}`
|
|
|
5304
5937
|
} finally {
|
|
5305
5938
|
delete globalThis.__rscRouterDiscoveryActive;
|
|
5306
5939
|
if (tempServer) {
|
|
5307
|
-
await
|
|
5940
|
+
await timed(
|
|
5941
|
+
debugDiscovery,
|
|
5942
|
+
"build tempServer.close",
|
|
5943
|
+
() => tempServer.close()
|
|
5944
|
+
);
|
|
5308
5945
|
}
|
|
5309
5946
|
await releaseBuildEnv(s);
|
|
5947
|
+
debugDiscovery?.(
|
|
5948
|
+
"build discovery done (%sms)",
|
|
5949
|
+
(performance.now() - buildStartTime).toFixed(1)
|
|
5950
|
+
);
|
|
5951
|
+
}
|
|
5952
|
+
},
|
|
5953
|
+
// Suppress vite's HMR cascade for our own gen-file writes.
|
|
5954
|
+
//
|
|
5955
|
+
// After every cf HMR cycle, refreshTempRscEnv → writeRouteTypesFiles
|
|
5956
|
+
// writes the configured gen files (default `router.named-routes.gen.ts`,
|
|
5957
|
+
// but the source filenames and gen suffix are user-configurable). The
|
|
5958
|
+
// chokidar watcher then fires twice independently: our
|
|
5959
|
+
// `handleRouteFileChange` (already short-circuited by
|
|
5960
|
+
// `consumeSelfGenWrite` inside `maybeHandleGeneratedRouteFileMutation`),
|
|
5961
|
+
// AND vite's own HMR pipeline (which invalidates the gen file's
|
|
5962
|
+
// importers and triggers a second workerd full reload — visible to the
|
|
5963
|
+
// user as a duplicate "[RSCRouter] HMR: version changed" on the client).
|
|
5964
|
+
//
|
|
5965
|
+
// `peekSelfGenWrite` is the authoritative filter: its map only contains
|
|
5966
|
+
// paths that `markSelfGenWrite` has registered, so it natively works
|
|
5967
|
+
// for any configured gen-file name. It is non-consuming so the chokidar
|
|
5968
|
+
// handler that fires later can still consume the same entry. Returning
|
|
5969
|
+
// [] tells vite "no modules invalidated by this change" — safe because
|
|
5970
|
+
// `s.perRouterManifests` is already up-to-date (the write that just
|
|
5971
|
+
// happened is the consequence of our just-completed rediscovery).
|
|
5972
|
+
handleHotUpdate(ctx) {
|
|
5973
|
+
if (peekSelfGenWrite(s, ctx.file)) {
|
|
5974
|
+
debugDiscovery?.(
|
|
5975
|
+
"handleHotUpdate: suppressing self-write HMR cascade for %s",
|
|
5976
|
+
ctx.file
|
|
5977
|
+
);
|
|
5978
|
+
return [];
|
|
5310
5979
|
}
|
|
5311
5980
|
},
|
|
5312
5981
|
// Virtual module: provides the pre-generated route manifest as a JS module
|
|
@@ -5323,17 +5992,36 @@ ${details}`
|
|
|
5323
5992
|
async load(id) {
|
|
5324
5993
|
if (id === "\0" + VIRTUAL_ROUTES_MANIFEST_ID) {
|
|
5325
5994
|
if (s.discoveryDone) {
|
|
5326
|
-
await
|
|
5995
|
+
await timed(
|
|
5996
|
+
debugRoutes,
|
|
5997
|
+
"await discoveryDone (manifest)",
|
|
5998
|
+
() => s.discoveryDone
|
|
5999
|
+
);
|
|
5327
6000
|
}
|
|
5328
|
-
|
|
6001
|
+
const code = await timed(
|
|
6002
|
+
debugRoutes,
|
|
6003
|
+
"generateRoutesManifestModule",
|
|
6004
|
+
() => generateRoutesManifestModule(s)
|
|
6005
|
+
);
|
|
6006
|
+
debugRoutes?.("manifest module emitted (%d bytes)", code?.length ?? 0);
|
|
6007
|
+
return code;
|
|
5329
6008
|
}
|
|
5330
6009
|
const perRouterPrefix = "\0" + VIRTUAL_ROUTES_MANIFEST_ID + "/";
|
|
5331
6010
|
if (id.startsWith(perRouterPrefix)) {
|
|
5332
6011
|
if (s.discoveryDone) {
|
|
5333
|
-
await
|
|
6012
|
+
await timed(
|
|
6013
|
+
debugRoutes,
|
|
6014
|
+
"await discoveryDone (per-router)",
|
|
6015
|
+
() => s.discoveryDone
|
|
6016
|
+
);
|
|
5334
6017
|
}
|
|
5335
6018
|
const routerId = id.slice(perRouterPrefix.length);
|
|
5336
|
-
|
|
6019
|
+
const code = await timed(
|
|
6020
|
+
debugRoutes,
|
|
6021
|
+
`generatePerRouterModule ${routerId}`,
|
|
6022
|
+
() => generatePerRouterModule(s, routerId)
|
|
6023
|
+
);
|
|
6024
|
+
return code;
|
|
5337
6025
|
}
|
|
5338
6026
|
return null;
|
|
5339
6027
|
},
|
|
@@ -5341,14 +6029,20 @@ ${details}`
|
|
|
5341
6029
|
// Used by closeBundle for handler code eviction and prerender data injection.
|
|
5342
6030
|
generateBundle(_options, bundle) {
|
|
5343
6031
|
if (this.environment?.name !== "rsc") return;
|
|
6032
|
+
const genStart = debugBuild ? performance.now() : 0;
|
|
5344
6033
|
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
5345
6034
|
if (chunk.type === "chunk" && chunk.isEntry) {
|
|
5346
6035
|
s.rscEntryFileName = fileName;
|
|
5347
6036
|
break;
|
|
5348
6037
|
}
|
|
5349
6038
|
}
|
|
5350
|
-
if (!s.resolvedPrerenderModules?.size && !s.resolvedStaticModules?.size)
|
|
6039
|
+
if (!s.resolvedPrerenderModules?.size && !s.resolvedStaticModules?.size) {
|
|
6040
|
+
debugBuild?.(
|
|
6041
|
+
"generateBundle (rsc): no handlers to scan (%sms)",
|
|
6042
|
+
(performance.now() - genStart).toFixed(1)
|
|
6043
|
+
);
|
|
5351
6044
|
return;
|
|
6045
|
+
}
|
|
5352
6046
|
s.handlerChunkInfoMap.clear();
|
|
5353
6047
|
s.staticHandlerChunkInfoMap.clear();
|
|
5354
6048
|
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
@@ -5392,6 +6086,13 @@ ${details}`
|
|
|
5392
6086
|
}
|
|
5393
6087
|
}
|
|
5394
6088
|
}
|
|
6089
|
+
debugBuild?.(
|
|
6090
|
+
"generateBundle (rsc): scanned %d chunks, %d prerender chunk(s), %d static chunk(s) (%sms)",
|
|
6091
|
+
Object.keys(bundle).length,
|
|
6092
|
+
s.handlerChunkInfoMap.size,
|
|
6093
|
+
s.staticHandlerChunkInfoMap.size,
|
|
6094
|
+
(performance.now() - genStart).toFixed(1)
|
|
6095
|
+
);
|
|
5395
6096
|
},
|
|
5396
6097
|
// Build-time pre-rendering: evict handler code and inject collected prerender data.
|
|
5397
6098
|
// Collection now happens in-process during discoverRouters() via RSC runner.
|
|
@@ -5402,27 +6103,37 @@ ${details}`
|
|
|
5402
6103
|
async handler() {
|
|
5403
6104
|
if (!s.isBuildMode) return;
|
|
5404
6105
|
if (this.environment && this.environment.name !== "rsc") return;
|
|
5405
|
-
|
|
6106
|
+
timedSync(
|
|
6107
|
+
debugBuild,
|
|
6108
|
+
"closeBundle postprocessBundle",
|
|
6109
|
+
() => postprocessBundle(s)
|
|
6110
|
+
);
|
|
5406
6111
|
}
|
|
5407
6112
|
}
|
|
5408
6113
|
};
|
|
5409
6114
|
}
|
|
5410
6115
|
|
|
5411
6116
|
// src/vite/rango.ts
|
|
6117
|
+
var debugConfig = createRangoDebugger(NS.config);
|
|
5412
6118
|
async function rango(options) {
|
|
6119
|
+
const rangoStart = performance.now();
|
|
5413
6120
|
const resolvedOptions = options ?? { preset: "node" };
|
|
5414
6121
|
const preset = resolvedOptions.preset ?? "node";
|
|
5415
6122
|
const showBanner = resolvedOptions.banner ?? true;
|
|
6123
|
+
debugConfig?.("rango(%s) setup start", preset);
|
|
5416
6124
|
const plugins = [];
|
|
5417
6125
|
const rangoAliases = { ...getPackageAliases(), ...getVendorAliases() };
|
|
5418
6126
|
const excludeDeps = [
|
|
5419
6127
|
...getExcludeDeps(),
|
|
5420
|
-
//
|
|
5421
|
-
//
|
|
5422
|
-
// .
|
|
6128
|
+
// plugin-rsc itself injects these into the client env's
|
|
6129
|
+
// optimizeDeps.include, which overrides exclude for the dep's own
|
|
6130
|
+
// pre-bundle entry. What exclude still controls is how *other*
|
|
6131
|
+
// pre-bundled deps treat imports of these specs (external vs inlined)
|
|
6132
|
+
// via esbuildCjsExternalPlugin. The cjs-to-esm transform in
|
|
6133
|
+
// plugins/cjs-to-esm.ts is the fallback for strict-pnpm consumers,
|
|
6134
|
+
// where client.browser's bare include fails to resolve and Vite ends up
|
|
6135
|
+
// serving the raw CJS file at dev-serve time.
|
|
5423
6136
|
"@vitejs/plugin-rsc/browser",
|
|
5424
|
-
// Keep the browser RSDW client out of Vite's dep optimizer so our
|
|
5425
|
-
// cjs-to-esm transform can patch the real file.
|
|
5426
6137
|
"@vitejs/plugin-rsc/vendor/react-server-dom/client.browser"
|
|
5427
6138
|
];
|
|
5428
6139
|
const pkg = getPublishedPackageName();
|
|
@@ -5694,6 +6405,12 @@ ${list}`);
|
|
|
5694
6405
|
preset
|
|
5695
6406
|
})
|
|
5696
6407
|
);
|
|
6408
|
+
debugConfig?.(
|
|
6409
|
+
"rango(%s) setup done: %d plugin(s) (%sms)",
|
|
6410
|
+
preset,
|
|
6411
|
+
plugins.length,
|
|
6412
|
+
(performance.now() - rangoStart).toFixed(1)
|
|
6413
|
+
);
|
|
5697
6414
|
return plugins;
|
|
5698
6415
|
}
|
|
5699
6416
|
|
|
@@ -5704,7 +6421,7 @@ function poke() {
|
|
|
5704
6421
|
apply: "serve",
|
|
5705
6422
|
configureServer(server) {
|
|
5706
6423
|
const stdin = process.stdin;
|
|
5707
|
-
const
|
|
6424
|
+
const debug11 = process.env.RANGO_POKE_DEBUG === "1";
|
|
5708
6425
|
const triggerReload = (source) => {
|
|
5709
6426
|
server.hot.send({ type: "full-reload", path: "*" });
|
|
5710
6427
|
server.config.logger.info(` browser reload (${source})`, {
|
|
@@ -5737,7 +6454,7 @@ function poke() {
|
|
|
5737
6454
|
lines.pop();
|
|
5738
6455
|
return lines;
|
|
5739
6456
|
};
|
|
5740
|
-
if (
|
|
6457
|
+
if (debug11) {
|
|
5741
6458
|
server.config.logger.info(
|
|
5742
6459
|
` poke debug enabled (isTTY=${stdin.isTTY ? "yes" : "no"}, isRaw=${stdin.isTTY ? stdin.isRaw ? "yes" : "no" : "n/a"})`,
|
|
5743
6460
|
{ timestamp: true }
|
|
@@ -5750,7 +6467,7 @@ function poke() {
|
|
|
5750
6467
|
);
|
|
5751
6468
|
}
|
|
5752
6469
|
const onData = (data) => {
|
|
5753
|
-
if (
|
|
6470
|
+
if (debug11) {
|
|
5754
6471
|
server.config.logger.info(` poke stdin ${formatChunk(data)}`, {
|
|
5755
6472
|
timestamp: true
|
|
5756
6473
|
});
|