@rangojs/router 0.0.0-experimental.69 → 0.0.0-experimental.6c70a2ab
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 +112 -17
- package/dist/vite/index.js +1456 -467
- 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 +364 -0
- package/skills/hooks/SKILL.md +54 -20
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +45 -0
- package/skills/layout/SKILL.md +24 -0
- package/skills/links/SKILL.md +234 -16
- package/skills/loader/SKILL.md +70 -3
- package/skills/middleware/SKILL.md +34 -3
- package/skills/migrate-nextjs/SKILL.md +562 -0
- package/skills/migrate-react-router/SKILL.md +769 -0
- package/skills/parallel/SKILL.md +68 -0
- package/skills/rango/SKILL.md +26 -22
- package/skills/response-routes/SKILL.md +8 -0
- package/skills/route/SKILL.md +48 -0
- package/skills/server-actions/SKILL.md +739 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/typesafety/SKILL.md +9 -1
- package/skills/view-transitions/SKILL.md +212 -0
- package/src/browser/app-shell.ts +52 -0
- package/src/browser/event-controller.ts +44 -4
- package/src/browser/navigation-bridge.ts +80 -5
- package/src/browser/navigation-client.ts +64 -13
- package/src/browser/navigation-store.ts +25 -1
- package/src/browser/partial-update.ts +58 -12
- 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 +70 -18
- package/src/browser/react/filter-segment-order.ts +51 -7
- package/src/browser/react/index.ts +3 -0
- package/src/browser/react/use-navigation.ts +22 -2
- package/src/browser/react/use-params.ts +17 -4
- package/src/browser/react/use-reverse.ts +99 -0
- package/src/browser/react/use-router.ts +8 -1
- package/src/browser/react/use-segments.ts +11 -8
- package/src/browser/rsc-router.tsx +34 -6
- package/src/browser/scroll-restoration.ts +22 -14
- package/src/browser/segment-reconciler.ts +36 -14
- package/src/browser/types.ts +19 -0
- package/src/build/route-trie.ts +52 -25
- package/src/cache/cf/cf-cache-store.ts +5 -7
- package/src/client.rsc.tsx +3 -0
- package/src/client.tsx +87 -175
- package/src/href-client.ts +4 -1
- package/src/index.rsc.ts +3 -0
- package/src/index.ts +40 -9
- package/src/outlet-context.ts +1 -1
- package/src/response-utils.ts +28 -0
- package/src/reverse.ts +62 -36
- package/src/route-definition/dsl-helpers.ts +175 -23
- package/src/route-definition/helpers-types.ts +63 -14
- package/src/route-definition/resolve-handler-use.ts +6 -0
- package/src/route-types.ts +7 -0
- package/src/router/handler-context.ts +21 -38
- package/src/router/lazy-includes.ts +6 -6
- package/src/router/loader-resolution.ts +3 -0
- package/src/router/manifest.ts +22 -13
- package/src/router/match-api.ts +4 -3
- package/src/router/match-handlers.ts +1 -0
- package/src/router/match-middleware/cache-lookup.ts +2 -1
- package/src/router/match-result.ts +101 -4
- package/src/router/middleware-types.ts +14 -25
- package/src/router/middleware.ts +54 -7
- package/src/router/pattern-matching.ts +101 -17
- package/src/router/revalidation.ts +15 -1
- package/src/router/segment-resolution/fresh.ts +13 -0
- package/src/router/segment-resolution/revalidation.ts +135 -101
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/trie-matching.ts +18 -13
- package/src/router/url-params.ts +49 -0
- package/src/router.ts +1 -2
- package/src/rsc/handler.ts +16 -8
- package/src/rsc/helpers.ts +69 -41
- package/src/rsc/progressive-enhancement.ts +4 -0
- package/src/rsc/response-route-handler.ts +14 -1
- package/src/rsc/rsc-rendering.ts +10 -0
- package/src/rsc/server-action.ts +4 -0
- package/src/rsc/types.ts +6 -0
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +122 -0
- package/src/segment-system.tsx +71 -70
- package/src/server/context.ts +26 -3
- package/src/server/request-context.ts +10 -42
- package/src/ssr/index.tsx +5 -1
- package/src/types/handler-context.ts +12 -39
- 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 +18 -1
- package/src/urls/include-helper.ts +24 -14
- package/src/urls/path-helper-types.ts +30 -4
- package/src/urls/response-types.ts +2 -10
- package/src/use-loader.tsx +4 -1
- 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 +172 -84
- 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/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/router-transform.ts +20 -3
- package/src/vite/plugins/expose-internal-ids.ts +540 -376
- 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 +49 -14
- package/src/vite/router-discovery.ts +558 -53
- package/src/vite/utils/banner.ts +1 -1
- package/src/vite/utils/package-resolution.ts +41 -1
- package/src/vite/utils/prerender-utils.ts +21 -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
|
}
|
|
@@ -950,6 +1065,7 @@ ${binding.localName}.$$id = "${handlerId}";`;
|
|
|
950
1065
|
import MagicString3 from "magic-string";
|
|
951
1066
|
import path3 from "node:path";
|
|
952
1067
|
import { createHash } from "node:crypto";
|
|
1068
|
+
var debug2 = createRangoDebugger(NS.transform);
|
|
953
1069
|
function transformRouter(code, filePath, routerFnNames, absolutePath) {
|
|
954
1070
|
const pat = new RegExp(
|
|
955
1071
|
`\\b(?:${routerFnNames.map((n) => n.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})\\s*(?:<[^>]*>)?\\s*\\(`,
|
|
@@ -992,11 +1108,15 @@ function transformRouter(code, filePath, routerFnNames, absolutePath) {
|
|
|
992
1108
|
}
|
|
993
1109
|
function exposeRouterId() {
|
|
994
1110
|
let projectRoot = "";
|
|
1111
|
+
const counter = createCounter(debug2, "expose-router-id");
|
|
995
1112
|
return {
|
|
996
1113
|
name: "@rangojs/router:expose-router-id",
|
|
997
1114
|
configResolved(config) {
|
|
998
1115
|
projectRoot = config.root;
|
|
999
1116
|
},
|
|
1117
|
+
buildEnd() {
|
|
1118
|
+
counter?.flush();
|
|
1119
|
+
},
|
|
1000
1120
|
transform(code, id) {
|
|
1001
1121
|
if (!code.includes("createRouter")) return null;
|
|
1002
1122
|
if (!/import\s*\{[^}]*\bcreateRouter\b[^}]*\}\s*from\s*["']@rangojs\/router(?:\/server)?["']/.test(
|
|
@@ -1005,14 +1125,25 @@ function exposeRouterId() {
|
|
|
1005
1125
|
return null;
|
|
1006
1126
|
}
|
|
1007
1127
|
if (id.includes("node_modules")) return null;
|
|
1008
|
-
const
|
|
1009
|
-
|
|
1010
|
-
|
|
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
|
+
}
|
|
1011
1141
|
}
|
|
1012
1142
|
};
|
|
1013
1143
|
}
|
|
1014
1144
|
|
|
1015
1145
|
// src/vite/plugins/expose-internal-ids.ts
|
|
1146
|
+
var debug3 = createRangoDebugger(NS.transform);
|
|
1016
1147
|
var VIRTUAL_LOADER_MANIFEST = "virtual:rsc-router/loader-manifest";
|
|
1017
1148
|
var RESOLVED_VIRTUAL_LOADER_MANIFEST = "\0" + VIRTUAL_LOADER_MANIFEST;
|
|
1018
1149
|
var VIRTUAL_HANDLER_PREFIX = "virtual:handler-extract:";
|
|
@@ -1025,9 +1156,13 @@ function exposeInternalIds(options) {
|
|
|
1025
1156
|
const staticHandlerModules = /* @__PURE__ */ new Map();
|
|
1026
1157
|
const virtualHandlers = /* @__PURE__ */ new Map();
|
|
1027
1158
|
const unsupportedShapeWarnings = /* @__PURE__ */ new Set();
|
|
1159
|
+
const counter = createCounter(debug3, "expose-internal-ids");
|
|
1028
1160
|
return {
|
|
1029
1161
|
name: "@rangojs/router:expose-internal-ids",
|
|
1030
1162
|
enforce: "post",
|
|
1163
|
+
buildEnd() {
|
|
1164
|
+
counter?.flush();
|
|
1165
|
+
},
|
|
1031
1166
|
api: {
|
|
1032
1167
|
prerenderHandlerModules,
|
|
1033
1168
|
staticHandlerModules
|
|
@@ -1141,11 +1276,13 @@ ${lazyImports.join(",\n")}
|
|
|
1141
1276
|
// --------------- Unified transform ---------------
|
|
1142
1277
|
transform(code, id) {
|
|
1143
1278
|
if (id.includes("/node_modules/")) return;
|
|
1144
|
-
const
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
this.
|
|
1148
|
-
|
|
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
|
+
`
|
|
1149
1286
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
1150
1287
|
!! !!
|
|
1151
1288
|
!! WARNING: NamedRoutes imported in a CLIENT component! !!
|
|
@@ -1165,277 +1302,373 @@ ${lazyImports.join(",\n")}
|
|
|
1165
1302
|
!! !!
|
|
1166
1303
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
1167
1304
|
`
|
|
1168
|
-
|
|
1169
|
-
}
|
|
1170
|
-
if (!code.includes("@rangojs/router")) return;
|
|
1171
|
-
const has = detectImports(code);
|
|
1172
|
-
const hasLoaderCode = has.loader && code.includes("createLoader");
|
|
1173
|
-
const hasHandleCode = has.handle && code.includes("createHandle");
|
|
1174
|
-
const hasLocationStateCode = has.locationState && code.includes("createLocationState");
|
|
1175
|
-
const hasPrerenderHandlerCode = has.prerenderHandler && code.includes("Prerender");
|
|
1176
|
-
const hasStaticHandlerCode = has.staticHandler && code.includes("Static");
|
|
1177
|
-
if (!hasLoaderCode && !hasHandleCode && !hasLocationStateCode && !hasPrerenderHandlerCode && !hasStaticHandlerCode) {
|
|
1178
|
-
return;
|
|
1179
|
-
}
|
|
1180
|
-
const _fnNamesCache = /* @__PURE__ */ new Map();
|
|
1181
|
-
const _bindingsCache = /* @__PURE__ */ new Map();
|
|
1182
|
-
let _cachedAst;
|
|
1183
|
-
let _astParseFailed = false;
|
|
1184
|
-
let _astCodeRef = code;
|
|
1185
|
-
const getFnNames = (canonicalName) => {
|
|
1186
|
-
let result = _fnNamesCache.get(canonicalName);
|
|
1187
|
-
if (!result) {
|
|
1188
|
-
result = getImportedFnNames(code, canonicalName);
|
|
1189
|
-
_fnNamesCache.set(canonicalName, result);
|
|
1305
|
+
);
|
|
1190
1306
|
}
|
|
1191
|
-
return
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
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;
|
|
1198
1316
|
}
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
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));
|
|
1204
1368
|
}
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
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
|
+
}
|
|
1213
1380
|
}
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
const totalCalls = countCreateCallsForNames(code, fnNames);
|
|
1221
|
-
const supportedBindings = getBindings(code, fnNames).length;
|
|
1222
|
-
if (totalCalls <= supportedBindings) continue;
|
|
1223
|
-
const warnKey = `${id}::${cfg.fnName}`;
|
|
1224
|
-
if (unsupportedShapeWarnings.has(warnKey)) continue;
|
|
1225
|
-
unsupportedShapeWarnings.add(warnKey);
|
|
1226
|
-
this.warn(buildUnsupportedShapeWarning(filePath, cfg.fnName));
|
|
1227
|
-
}
|
|
1228
|
-
if (hasLoaderCode && isRscEnv) {
|
|
1229
|
-
const fnNames = getFnNames("createLoader");
|
|
1230
|
-
const bindings = getBindings(code, fnNames);
|
|
1231
|
-
for (const binding of bindings) {
|
|
1232
|
-
const exportName = binding.exportNames[0];
|
|
1233
|
-
const hashedId = hashId(filePath, exportName);
|
|
1234
|
-
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,
|
|
1235
1387
|
filePath,
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
}
|
|
1240
|
-
if (hasLoaderCode && !isRscEnv) {
|
|
1241
|
-
const fnNames = getFnNames("createLoader");
|
|
1242
|
-
const bindings = getBindings(code, fnNames);
|
|
1243
|
-
const stubResult = generateClientLoaderStubs(
|
|
1244
|
-
bindings,
|
|
1245
|
-
code,
|
|
1246
|
-
filePath,
|
|
1247
|
-
isBuild
|
|
1248
|
-
);
|
|
1249
|
-
if (stubResult) return stubResult;
|
|
1250
|
-
}
|
|
1251
|
-
if (hasPrerenderHandlerCode && !isRscEnv) {
|
|
1252
|
-
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1253
|
-
const bindings = getBindings(code, fnNames);
|
|
1254
|
-
const wholeFile = generateWholeFileStubs(
|
|
1255
|
-
PRERENDER_CONFIG,
|
|
1256
|
-
bindings,
|
|
1257
|
-
code,
|
|
1258
|
-
filePath,
|
|
1259
|
-
isBuild
|
|
1260
|
-
);
|
|
1261
|
-
if (wholeFile) return wholeFile;
|
|
1262
|
-
}
|
|
1263
|
-
if (hasPrerenderHandlerCode && isRscEnv && isBuild) {
|
|
1264
|
-
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1265
|
-
const exportNames = getBindings(code, fnNames).map(
|
|
1266
|
-
(b) => b.exportNames[0]
|
|
1267
|
-
);
|
|
1268
|
-
if (exportNames.length > 0) {
|
|
1269
|
-
prerenderHandlerModules.set(id, exportNames);
|
|
1388
|
+
isBuild
|
|
1389
|
+
);
|
|
1390
|
+
if (stubResult) return stubResult;
|
|
1270
1391
|
}
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
const fnNames = getFnNames(cfg.fnName);
|
|
1278
|
-
return { cfg, fnNames };
|
|
1279
|
-
});
|
|
1280
|
-
for (const { cfg, fnNames } of handlerConfigs) {
|
|
1281
|
-
const totalCalls = countCreateCallsForNames(code, fnNames);
|
|
1282
|
-
const supportedBindings = getBindings(code, fnNames).length;
|
|
1283
|
-
if (totalCalls > supportedBindings) {
|
|
1284
|
-
const iterS = new MagicString4(code);
|
|
1285
|
-
const result = transformInlineHandlers(
|
|
1286
|
-
cfg.fnName,
|
|
1287
|
-
VIRTUAL_HANDLER_PREFIX,
|
|
1288
|
-
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,
|
|
1289
1398
|
code,
|
|
1290
1399
|
filePath,
|
|
1291
|
-
|
|
1292
|
-
id,
|
|
1293
|
-
parseAst2
|
|
1400
|
+
isBuild
|
|
1294
1401
|
);
|
|
1295
|
-
if (
|
|
1296
|
-
changed = true;
|
|
1297
|
-
code = iterS.toString();
|
|
1298
|
-
_bindingsCache.clear();
|
|
1299
|
-
}
|
|
1300
|
-
}
|
|
1301
|
-
}
|
|
1302
|
-
if (hasStaticHandlerCode && !isRscEnv) {
|
|
1303
|
-
const fnNames = getFnNames(STATIC_CONFIG.fnName);
|
|
1304
|
-
const bindings = getBindings(code, fnNames);
|
|
1305
|
-
const wholeFile = generateWholeFileStubs(
|
|
1306
|
-
STATIC_CONFIG,
|
|
1307
|
-
bindings,
|
|
1308
|
-
code,
|
|
1309
|
-
filePath,
|
|
1310
|
-
isBuild
|
|
1311
|
-
);
|
|
1312
|
-
if (wholeFile) return wholeFile;
|
|
1313
|
-
}
|
|
1314
|
-
if (!isRscEnv && (hasPrerenderHandlerCode || hasStaticHandlerCode)) {
|
|
1315
|
-
const allBindings = [];
|
|
1316
|
-
if (hasLoaderCode) {
|
|
1317
|
-
allBindings.push(...getBindings(code, getFnNames("createLoader")));
|
|
1318
|
-
}
|
|
1319
|
-
if (hasHandleCode) {
|
|
1320
|
-
allBindings.push(...getBindings(code, getFnNames("createHandle")));
|
|
1402
|
+
if (wholeFile) return wholeFile;
|
|
1321
1403
|
}
|
|
1322
|
-
if (
|
|
1323
|
-
|
|
1324
|
-
|
|
1404
|
+
if (hasPrerenderHandlerCode && isRscEnv && isBuild) {
|
|
1405
|
+
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1406
|
+
const exportNames = getBindings(code, fnNames).map(
|
|
1407
|
+
(b) => b.exportNames[0]
|
|
1325
1408
|
);
|
|
1409
|
+
if (exportNames.length > 0) {
|
|
1410
|
+
prerenderHandlerModules.set(id, exportNames);
|
|
1411
|
+
}
|
|
1326
1412
|
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
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
|
+
}
|
|
1331
1442
|
}
|
|
1332
|
-
if (hasStaticHandlerCode) {
|
|
1333
|
-
|
|
1334
|
-
|
|
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
|
|
1335
1452
|
);
|
|
1453
|
+
if (wholeFile) return wholeFile;
|
|
1336
1454
|
}
|
|
1337
|
-
if (
|
|
1338
|
-
const
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
} else if (hasHandleCode && getFnNames("createHandle").some((n) => fnCall.includes(n))) {
|
|
1354
|
-
brand = "handle";
|
|
1355
|
-
} else if (hasLocationStateCode && getFnNames("createLocationState").some((n) => fnCall.includes(n))) {
|
|
1356
|
-
brand = "locationState";
|
|
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));
|
|
1357
1471
|
}
|
|
1358
|
-
stubs.push(
|
|
1359
|
-
`export const ${name} = { __brand: "${brand}", $$id: "${stubId}" };`
|
|
1360
|
-
);
|
|
1361
1472
|
}
|
|
1362
|
-
|
|
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 };
|
|
1588
|
+
}
|
|
1363
1589
|
}
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
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
|
+
}
|
|
1372
1598
|
}
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
}
|
|
1379
|
-
if (hasHandleCode) {
|
|
1380
|
-
const fnNames = getFnNames("createHandle");
|
|
1381
|
-
changed = transformHandles(
|
|
1382
|
-
getBindings(code, fnNames),
|
|
1383
|
-
s,
|
|
1384
|
-
code,
|
|
1385
|
-
filePath,
|
|
1386
|
-
isBuild
|
|
1387
|
-
) || changed;
|
|
1388
|
-
}
|
|
1389
|
-
if (hasLocationStateCode) {
|
|
1390
|
-
const fnNames = getFnNames("createLocationState");
|
|
1391
|
-
changed = transformLocationState(
|
|
1392
|
-
getBindings(code, fnNames),
|
|
1393
|
-
s,
|
|
1394
|
-
filePath,
|
|
1395
|
-
isBuild
|
|
1396
|
-
) || changed;
|
|
1397
|
-
}
|
|
1398
|
-
if (hasPrerenderHandlerCode) {
|
|
1399
|
-
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1400
|
-
const bindings = getBindings(code, fnNames);
|
|
1401
|
-
if (isRscEnv) {
|
|
1402
|
-
changed = transformHandlerIds(
|
|
1403
|
-
PRERENDER_CONFIG,
|
|
1404
|
-
bindings,
|
|
1599
|
+
const s = new MagicString4(code);
|
|
1600
|
+
if (hasLoaderCode) {
|
|
1601
|
+
const fnNames = getFnNames("createLoader");
|
|
1602
|
+
changed = transformLoaders(
|
|
1603
|
+
getBindings(code, fnNames),
|
|
1405
1604
|
s,
|
|
1406
1605
|
filePath,
|
|
1407
1606
|
isBuild
|
|
1408
1607
|
) || changed;
|
|
1409
|
-
}
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1608
|
+
}
|
|
1609
|
+
if (hasHandleCode) {
|
|
1610
|
+
const fnNames = getFnNames("createHandle");
|
|
1611
|
+
changed = transformHandles(
|
|
1612
|
+
getBindings(code, fnNames),
|
|
1413
1613
|
s,
|
|
1614
|
+
code,
|
|
1414
1615
|
filePath,
|
|
1415
1616
|
isBuild
|
|
1416
1617
|
) || changed;
|
|
1417
1618
|
}
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
if (isRscEnv) {
|
|
1423
|
-
changed = transformHandlerIds(
|
|
1424
|
-
STATIC_CONFIG,
|
|
1425
|
-
bindings,
|
|
1619
|
+
if (hasLocationStateCode) {
|
|
1620
|
+
const fnNames = getFnNames("createLocationState");
|
|
1621
|
+
changed = transformLocationState(
|
|
1622
|
+
getBindings(code, fnNames),
|
|
1426
1623
|
s,
|
|
1427
1624
|
filePath,
|
|
1428
1625
|
isBuild
|
|
1429
1626
|
) || changed;
|
|
1430
|
-
} else {
|
|
1431
|
-
changed = stubHandlerExprs(STATIC_CONFIG, bindings, s, filePath, isBuild) || changed;
|
|
1432
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);
|
|
1433
1671
|
}
|
|
1434
|
-
if (!changed) return;
|
|
1435
|
-
return {
|
|
1436
|
-
code: s.toString(),
|
|
1437
|
-
map: s.generateMap({ source: id, includeContent: true })
|
|
1438
|
-
};
|
|
1439
1672
|
}
|
|
1440
1673
|
};
|
|
1441
1674
|
}
|
|
@@ -1443,12 +1676,14 @@ ${lazyImports.join(",\n")}
|
|
|
1443
1676
|
// src/vite/plugins/use-cache-transform.ts
|
|
1444
1677
|
import path5 from "node:path";
|
|
1445
1678
|
import MagicString5 from "magic-string";
|
|
1679
|
+
var debug4 = createRangoDebugger(NS.transform);
|
|
1446
1680
|
var CACHE_RUNTIME_IMPORT = "@rangojs/router/cache-runtime";
|
|
1447
1681
|
var LAYOUT_TEMPLATE_PATTERN = /\/(layout|template)\.(tsx?|jsx?)$/;
|
|
1448
1682
|
function useCacheTransform() {
|
|
1449
1683
|
let projectRoot = "";
|
|
1450
1684
|
let isBuild = false;
|
|
1451
1685
|
let rscTransforms = null;
|
|
1686
|
+
const counter = createCounter(debug4, "use-cache");
|
|
1452
1687
|
return {
|
|
1453
1688
|
name: "@rangojs/router:use-cache",
|
|
1454
1689
|
enforce: "post",
|
|
@@ -1456,53 +1691,61 @@ function useCacheTransform() {
|
|
|
1456
1691
|
projectRoot = config.root;
|
|
1457
1692
|
isBuild = config.command === "build";
|
|
1458
1693
|
},
|
|
1694
|
+
buildEnd() {
|
|
1695
|
+
counter?.flush();
|
|
1696
|
+
},
|
|
1459
1697
|
async transform(code, id) {
|
|
1460
1698
|
if (this.environment?.name !== "rsc") return;
|
|
1461
1699
|
if (!code.includes("use cache")) return;
|
|
1462
1700
|
if (id.includes("/node_modules/") || id.startsWith("\0")) return;
|
|
1463
1701
|
if (!/\.(tsx?|jsx?|mjs)$/.test(id)) return;
|
|
1464
|
-
|
|
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;
|
|
1465
1717
|
try {
|
|
1466
|
-
|
|
1718
|
+
const { parseAst: parseAst4 } = await import("vite");
|
|
1719
|
+
ast = parseAst4(code);
|
|
1467
1720
|
} catch {
|
|
1468
1721
|
return;
|
|
1469
1722
|
}
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
hasDirective,
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
const isLayoutOrTemplate = LAYOUT_TEMPLATE_PATTERN.test(id);
|
|
1485
|
-
if (hasDirective(ast.body, "use cache")) {
|
|
1486
|
-
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(
|
|
1487
1737
|
code,
|
|
1488
1738
|
ast,
|
|
1489
1739
|
filePath,
|
|
1490
1740
|
id,
|
|
1491
1741
|
isBuild,
|
|
1492
|
-
|
|
1493
|
-
transformWrapExport
|
|
1742
|
+
transformHoistInlineDirective
|
|
1494
1743
|
);
|
|
1744
|
+
warnOnNearMissDirectives(ast, id, this.warn.bind(this));
|
|
1745
|
+
if (functionResult) return functionResult;
|
|
1746
|
+
} finally {
|
|
1747
|
+
counter?.record(id, performance.now() - start);
|
|
1495
1748
|
}
|
|
1496
|
-
const functionResult = transformFunctionLevelUseCache(
|
|
1497
|
-
code,
|
|
1498
|
-
ast,
|
|
1499
|
-
filePath,
|
|
1500
|
-
id,
|
|
1501
|
-
isBuild,
|
|
1502
|
-
transformHoistInlineDirective
|
|
1503
|
-
);
|
|
1504
|
-
warnOnNearMissDirectives(ast, id, this.warn.bind(this));
|
|
1505
|
-
if (functionResult) return functionResult;
|
|
1506
1749
|
}
|
|
1507
1750
|
};
|
|
1508
1751
|
}
|
|
@@ -1625,6 +1868,7 @@ function warnOnNearMissDirectives(ast, fileId, warn) {
|
|
|
1625
1868
|
}
|
|
1626
1869
|
|
|
1627
1870
|
// src/vite/plugins/client-ref-dedup.ts
|
|
1871
|
+
var debug5 = createRangoDebugger(NS.transform);
|
|
1628
1872
|
var CLIENT_IN_SERVER_PROXY_PREFIX = "virtual:vite-rsc/client-in-server-package-proxy/";
|
|
1629
1873
|
function extractPackageName(absolutePath) {
|
|
1630
1874
|
const marker = "/node_modules/";
|
|
@@ -1641,6 +1885,7 @@ function extractPackageName(absolutePath) {
|
|
|
1641
1885
|
}
|
|
1642
1886
|
function clientRefDedup() {
|
|
1643
1887
|
let clientExclude = [];
|
|
1888
|
+
const dedupedPackages = /* @__PURE__ */ new Set();
|
|
1644
1889
|
return {
|
|
1645
1890
|
name: "@rangojs/router:client-ref-dedup",
|
|
1646
1891
|
enforce: "pre",
|
|
@@ -1649,6 +1894,15 @@ function clientRefDedup() {
|
|
|
1649
1894
|
const clientEnv = config.environments?.["client"];
|
|
1650
1895
|
clientExclude = clientEnv?.optimizeDeps?.exclude ?? config.optimizeDeps?.exclude ?? [];
|
|
1651
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
|
+
},
|
|
1652
1906
|
resolveId(source, importer, options) {
|
|
1653
1907
|
if (this.environment?.name !== "client") return;
|
|
1654
1908
|
if (!importer?.includes(CLIENT_IN_SERVER_PROXY_PREFIX)) return;
|
|
@@ -1657,6 +1911,7 @@ function clientRefDedup() {
|
|
|
1657
1911
|
const packageName = extractPackageName(source);
|
|
1658
1912
|
if (!packageName) return;
|
|
1659
1913
|
if (clientExclude.includes(packageName)) return;
|
|
1914
|
+
if (debug5) dedupedPackages.add(packageName);
|
|
1660
1915
|
return `\0rango:dedup/${packageName}`;
|
|
1661
1916
|
},
|
|
1662
1917
|
load(id) {
|
|
@@ -1779,12 +2034,13 @@ function getVirtualVersionContent(version) {
|
|
|
1779
2034
|
|
|
1780
2035
|
// src/vite/utils/package-resolution.ts
|
|
1781
2036
|
import { existsSync } from "node:fs";
|
|
2037
|
+
import { createRequire } from "node:module";
|
|
1782
2038
|
import { resolve } from "node:path";
|
|
1783
2039
|
|
|
1784
2040
|
// package.json
|
|
1785
2041
|
var package_default = {
|
|
1786
2042
|
name: "@rangojs/router",
|
|
1787
|
-
version: "0.0.0-experimental.
|
|
2043
|
+
version: "0.0.0-experimental.6c70a2ab",
|
|
1788
2044
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
1789
2045
|
keywords: [
|
|
1790
2046
|
"react",
|
|
@@ -1917,16 +2173,18 @@ var package_default = {
|
|
|
1917
2173
|
tag: "experimental"
|
|
1918
2174
|
},
|
|
1919
2175
|
scripts: {
|
|
1920
|
-
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",
|
|
1921
2177
|
prepublishOnly: "pnpm build",
|
|
1922
|
-
typecheck: "tsc --noEmit",
|
|
2178
|
+
typecheck: "tsc --noEmit && tsc -p tsconfig.strict-check.json --noEmit",
|
|
1923
2179
|
test: "playwright test",
|
|
1924
2180
|
"test:ui": "playwright test --ui",
|
|
1925
2181
|
"test:unit": "vitest run",
|
|
1926
2182
|
"test:unit:watch": "vitest"
|
|
1927
2183
|
},
|
|
1928
2184
|
dependencies: {
|
|
1929
|
-
"@
|
|
2185
|
+
"@types/debug": "^4.1.12",
|
|
2186
|
+
"@vitejs/plugin-rsc": "^0.5.23",
|
|
2187
|
+
debug: "^4.4.1",
|
|
1930
2188
|
"magic-string": "^0.30.17",
|
|
1931
2189
|
picomatch: "^4.0.3",
|
|
1932
2190
|
"rsc-html-stream": "^0.0.7"
|
|
@@ -1946,7 +2204,7 @@ var package_default = {
|
|
|
1946
2204
|
},
|
|
1947
2205
|
peerDependencies: {
|
|
1948
2206
|
"@cloudflare/vite-plugin": "^1.25.0",
|
|
1949
|
-
"@vitejs/plugin-rsc": "^0.5.
|
|
2207
|
+
"@vitejs/plugin-rsc": "^0.5.23",
|
|
1950
2208
|
react: "^18.0.0 || ^19.0.0",
|
|
1951
2209
|
vite: "^7.3.0"
|
|
1952
2210
|
},
|
|
@@ -1961,6 +2219,7 @@ var package_default = {
|
|
|
1961
2219
|
};
|
|
1962
2220
|
|
|
1963
2221
|
// src/vite/utils/package-resolution.ts
|
|
2222
|
+
var require2 = createRequire(import.meta.url);
|
|
1964
2223
|
var VIRTUAL_PACKAGE_NAME = "@rangojs/router";
|
|
1965
2224
|
function getPublishedPackageName() {
|
|
1966
2225
|
return package_default.name;
|
|
@@ -2001,6 +2260,20 @@ function getPackageAliases() {
|
|
|
2001
2260
|
}
|
|
2002
2261
|
return aliases;
|
|
2003
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
|
+
}
|
|
2004
2277
|
|
|
2005
2278
|
// src/build/route-types/param-extraction.ts
|
|
2006
2279
|
function extractParamsFromPattern(pattern) {
|
|
@@ -2898,6 +3171,7 @@ import * as Vite from "vite";
|
|
|
2898
3171
|
|
|
2899
3172
|
// src/vite/plugins/performance-tracks.ts
|
|
2900
3173
|
import { readFile } from "node:fs/promises";
|
|
3174
|
+
var debug6 = createRangoDebugger(NS.transform);
|
|
2901
3175
|
var RSDW_PATCH_RE = /((?:var|let|const)\s+\w+\s*=\s*root\._children\s*,\s*(\w+)\s*=\s*root\._debugInfo\s*[;,])/;
|
|
2902
3176
|
function buildPatchReplacement(match, debugInfoVar) {
|
|
2903
3177
|
return `${match}
|
|
@@ -2939,19 +3213,23 @@ function performanceTracksOptimizeDepsPlugin() {
|
|
|
2939
3213
|
};
|
|
2940
3214
|
}
|
|
2941
3215
|
function performanceTracksPlugin() {
|
|
3216
|
+
const counter = createCounter(debug6, "performance-tracks");
|
|
2942
3217
|
return {
|
|
2943
3218
|
name: "@rangojs/router:performance-tracks",
|
|
3219
|
+
buildEnd() {
|
|
3220
|
+
counter?.flush();
|
|
3221
|
+
},
|
|
2944
3222
|
transform(code, id) {
|
|
2945
3223
|
if (!id.includes("react-server-dom") || !id.includes("client")) return;
|
|
2946
|
-
const
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
);
|
|
2954
|
-
|
|
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
|
+
}
|
|
2955
3233
|
}
|
|
2956
3234
|
};
|
|
2957
3235
|
}
|
|
@@ -3098,11 +3376,10 @@ function createVersionInjectorPlugin(rscEntryPath) {
|
|
|
3098
3376
|
if (normalizedId !== normalizedEntry) {
|
|
3099
3377
|
return null;
|
|
3100
3378
|
}
|
|
3101
|
-
const prepend = [
|
|
3379
|
+
const prepend = [
|
|
3380
|
+
`import "virtual:rsc-router/routes-manifest";`
|
|
3381
|
+
];
|
|
3102
3382
|
let newCode = code;
|
|
3103
|
-
if (!code.includes("virtual:rsc-router/routes-manifest")) {
|
|
3104
|
-
prepend.push(`import "virtual:rsc-router/routes-manifest";`);
|
|
3105
|
-
}
|
|
3106
3383
|
const needsVersion = code.includes("createRSCHandler") && !code.includes("@rangojs/router:version") && /createRSCHandler\s*\(\s*\{/.test(code);
|
|
3107
3384
|
if (needsVersion) {
|
|
3108
3385
|
prepend.push(`import { VERSION } from "@rangojs/router:version";`);
|
|
@@ -3111,8 +3388,21 @@ function createVersionInjectorPlugin(rscEntryPath) {
|
|
|
3111
3388
|
"createRSCHandler({\n version: VERSION,"
|
|
3112
3389
|
);
|
|
3113
3390
|
}
|
|
3114
|
-
|
|
3115
|
-
|
|
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");
|
|
3116
3406
|
return {
|
|
3117
3407
|
code: newCode,
|
|
3118
3408
|
map: null
|
|
@@ -3122,6 +3412,7 @@ function createVersionInjectorPlugin(rscEntryPath) {
|
|
|
3122
3412
|
}
|
|
3123
3413
|
|
|
3124
3414
|
// src/vite/plugins/cjs-to-esm.ts
|
|
3415
|
+
var debug7 = createRangoDebugger(NS.transform);
|
|
3125
3416
|
function createCjsToEsmPlugin() {
|
|
3126
3417
|
return {
|
|
3127
3418
|
name: "@rangojs/router:cjs-to-esm",
|
|
@@ -3131,6 +3422,7 @@ function createCjsToEsmPlugin() {
|
|
|
3131
3422
|
if (cleanId.includes("vendor/react-server-dom/client.browser.js") || cleanId.includes("vendor\\react-server-dom\\client.browser.js")) {
|
|
3132
3423
|
const isProd = process.env.NODE_ENV === "production";
|
|
3133
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);
|
|
3134
3426
|
return {
|
|
3135
3427
|
code: `export * from "${cjsFile}";`,
|
|
3136
3428
|
map: null
|
|
@@ -3166,6 +3458,7 @@ function createCjsToEsmPlugin() {
|
|
|
3166
3458
|
"export const $1 ="
|
|
3167
3459
|
);
|
|
3168
3460
|
transformed = license + "\n" + transformed;
|
|
3461
|
+
debug7?.("cjs-to-esm body rewrite %s", id);
|
|
3169
3462
|
return {
|
|
3170
3463
|
code: transformed,
|
|
3171
3464
|
map: null
|
|
@@ -3180,7 +3473,7 @@ function createCjsToEsmPlugin() {
|
|
|
3180
3473
|
import { createServer as createViteServer } from "vite";
|
|
3181
3474
|
import { resolve as resolve8 } from "node:path";
|
|
3182
3475
|
import { readFileSync as readFileSync6 } from "node:fs";
|
|
3183
|
-
import { createRequire } from "node:module";
|
|
3476
|
+
import { createRequire as createRequire2, register } from "node:module";
|
|
3184
3477
|
import { pathToFileURL } from "node:url";
|
|
3185
3478
|
|
|
3186
3479
|
// src/vite/plugins/virtual-stub-plugin.ts
|
|
@@ -3207,9 +3500,117 @@ function createVirtualStubPlugin() {
|
|
|
3207
3500
|
};
|
|
3208
3501
|
}
|
|
3209
3502
|
|
|
3503
|
+
// src/vite/plugins/cloudflare-protocol-stub.ts
|
|
3504
|
+
var VIRTUAL_PREFIX = "virtual:rango-cloudflare-stub-";
|
|
3505
|
+
var NULL_PREFIX = "\0" + VIRTUAL_PREFIX;
|
|
3506
|
+
var CF_PREFIX = "cloudflare:";
|
|
3507
|
+
var BUILD_ENV_GLOBAL_KEY = "__rango_build_env__";
|
|
3508
|
+
var SOURCE_EXT_RE = /\.[mc]?[jt]sx?$/;
|
|
3509
|
+
var IMPORT_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
3510
|
+
"ImportDeclaration",
|
|
3511
|
+
"ImportExpression",
|
|
3512
|
+
"ExportNamedDeclaration",
|
|
3513
|
+
"ExportAllDeclaration"
|
|
3514
|
+
]);
|
|
3515
|
+
var STUBS = {
|
|
3516
|
+
"cloudflare:workers": `
|
|
3517
|
+
export class DurableObject { constructor(_ctx, _env) {} }
|
|
3518
|
+
export class WorkerEntrypoint { constructor(_ctx, _env) {} }
|
|
3519
|
+
export class WorkflowEntrypoint { constructor(_ctx, _env) {} }
|
|
3520
|
+
export class RpcTarget {}
|
|
3521
|
+
export const env = globalThis[${JSON.stringify(BUILD_ENV_GLOBAL_KEY)}] ?? {};
|
|
3522
|
+
export default {};
|
|
3523
|
+
`,
|
|
3524
|
+
"cloudflare:email": `
|
|
3525
|
+
export class EmailMessage { constructor(_from, _to, _raw) {} }
|
|
3526
|
+
export default {};
|
|
3527
|
+
`,
|
|
3528
|
+
"cloudflare:sockets": `
|
|
3529
|
+
export function connect() { return {}; }
|
|
3530
|
+
export default {};
|
|
3531
|
+
`,
|
|
3532
|
+
"cloudflare:workflows": `
|
|
3533
|
+
export class NonRetryableError extends Error {
|
|
3534
|
+
constructor(message, name) { super(message); this.name = name ?? "NonRetryableError"; }
|
|
3535
|
+
}
|
|
3536
|
+
export default {};
|
|
3537
|
+
`
|
|
3538
|
+
};
|
|
3539
|
+
var FALLBACK_STUB = `export default {};
|
|
3540
|
+
`;
|
|
3541
|
+
function createCloudflareProtocolStubPlugin() {
|
|
3542
|
+
return {
|
|
3543
|
+
name: "@rangojs/router:cloudflare-protocol-stub",
|
|
3544
|
+
transform(code, id) {
|
|
3545
|
+
const cleanId = id.split("?")[0] ?? id;
|
|
3546
|
+
if (!SOURCE_EXT_RE.test(cleanId)) return null;
|
|
3547
|
+
if (!code.includes(CF_PREFIX)) return null;
|
|
3548
|
+
let ast;
|
|
3549
|
+
try {
|
|
3550
|
+
ast = this.parse(code);
|
|
3551
|
+
} catch {
|
|
3552
|
+
return null;
|
|
3553
|
+
}
|
|
3554
|
+
const hits = [];
|
|
3555
|
+
walk(ast, (node) => {
|
|
3556
|
+
if (!IMPORT_NODE_TYPES.has(node.type)) return;
|
|
3557
|
+
const source = node.source;
|
|
3558
|
+
if (!source || source.type !== "Literal") return;
|
|
3559
|
+
if (typeof source.value !== "string") return;
|
|
3560
|
+
if (!source.value.startsWith(CF_PREFIX)) return;
|
|
3561
|
+
if (typeof source.start !== "number" || typeof source.end !== "number")
|
|
3562
|
+
return;
|
|
3563
|
+
hits.push({
|
|
3564
|
+
start: source.start,
|
|
3565
|
+
end: source.end,
|
|
3566
|
+
value: source.value
|
|
3567
|
+
});
|
|
3568
|
+
});
|
|
3569
|
+
if (hits.length === 0) return null;
|
|
3570
|
+
hits.sort((a, b) => b.start - a.start);
|
|
3571
|
+
let out = code;
|
|
3572
|
+
for (const hit of hits) {
|
|
3573
|
+
const submodule = hit.value.slice(CF_PREFIX.length);
|
|
3574
|
+
const quote = code[hit.start] === "'" ? "'" : '"';
|
|
3575
|
+
out = out.slice(0, hit.start) + quote + VIRTUAL_PREFIX + submodule + quote + out.slice(hit.end);
|
|
3576
|
+
}
|
|
3577
|
+
return { code: out, map: null };
|
|
3578
|
+
},
|
|
3579
|
+
resolveId(id) {
|
|
3580
|
+
if (id.startsWith(VIRTUAL_PREFIX)) {
|
|
3581
|
+
return "\0" + id;
|
|
3582
|
+
}
|
|
3583
|
+
return null;
|
|
3584
|
+
},
|
|
3585
|
+
load(id) {
|
|
3586
|
+
if (!id.startsWith(NULL_PREFIX)) return null;
|
|
3587
|
+
const submodule = id.slice(NULL_PREFIX.length);
|
|
3588
|
+
const specifier = CF_PREFIX + submodule;
|
|
3589
|
+
return STUBS[specifier] ?? FALLBACK_STUB;
|
|
3590
|
+
}
|
|
3591
|
+
};
|
|
3592
|
+
}
|
|
3593
|
+
function walk(node, visit) {
|
|
3594
|
+
if (!node || typeof node !== "object") return;
|
|
3595
|
+
if (Array.isArray(node)) {
|
|
3596
|
+
for (const child of node) walk(child, visit);
|
|
3597
|
+
return;
|
|
3598
|
+
}
|
|
3599
|
+
const n = node;
|
|
3600
|
+
if (typeof n.type !== "string") return;
|
|
3601
|
+
visit(n);
|
|
3602
|
+
for (const key in n) {
|
|
3603
|
+
if (key === "loc" || key === "start" || key === "end" || key === "range") {
|
|
3604
|
+
continue;
|
|
3605
|
+
}
|
|
3606
|
+
walk(n[key], visit);
|
|
3607
|
+
}
|
|
3608
|
+
}
|
|
3609
|
+
|
|
3210
3610
|
// src/vite/plugins/client-ref-hashing.ts
|
|
3211
3611
|
import { relative } from "node:path";
|
|
3212
3612
|
import { createHash as createHash2 } from "node:crypto";
|
|
3613
|
+
var debug8 = createRangoDebugger(NS.transform);
|
|
3213
3614
|
var CLIENT_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-package-proxy/";
|
|
3214
3615
|
var CLIENT_IN_SERVER_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-in-server-package-proxy/";
|
|
3215
3616
|
var FS_PREFIX = "/@fs/";
|
|
@@ -3248,6 +3649,7 @@ function transformClientRefs(code, projectRoot) {
|
|
|
3248
3649
|
return hasReplacement ? result : null;
|
|
3249
3650
|
}
|
|
3250
3651
|
function hashClientRefs(projectRoot) {
|
|
3652
|
+
const counter = createCounter(debug8, "hash-client-refs");
|
|
3251
3653
|
return {
|
|
3252
3654
|
name: "@rangojs/router:hash-client-refs",
|
|
3253
3655
|
// Run after the RSC plugin's transform (default enforce is normal)
|
|
@@ -3255,10 +3657,18 @@ function hashClientRefs(projectRoot) {
|
|
|
3255
3657
|
applyToEnvironment(env) {
|
|
3256
3658
|
return env.name === "rsc";
|
|
3257
3659
|
},
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
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
|
+
}
|
|
3262
3672
|
}
|
|
3263
3673
|
};
|
|
3264
3674
|
}
|
|
@@ -3386,6 +3796,12 @@ function markSelfGenWrite(state, filePath, content) {
|
|
|
3386
3796
|
state.selfWrittenGenFiles.set(filePath, { at: Date.now(), hash });
|
|
3387
3797
|
}
|
|
3388
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) {
|
|
3389
3805
|
const info = state.selfWrittenGenFiles.get(filePath);
|
|
3390
3806
|
if (!info) return false;
|
|
3391
3807
|
if (Date.now() - info.at > state.SELF_WRITE_WINDOW_MS) {
|
|
@@ -3396,7 +3812,7 @@ function consumeSelfGenWrite(state, filePath) {
|
|
|
3396
3812
|
const current = readFileSync3(filePath, "utf-8");
|
|
3397
3813
|
const currentHash = createHash3("sha256").update(current).digest("hex");
|
|
3398
3814
|
if (currentHash === info.hash) {
|
|
3399
|
-
state.selfWrittenGenFiles.delete(filePath);
|
|
3815
|
+
if (consume) state.selfWrittenGenFiles.delete(filePath);
|
|
3400
3816
|
return true;
|
|
3401
3817
|
}
|
|
3402
3818
|
return false;
|
|
@@ -3500,11 +3916,19 @@ function substituteRouteParams(pattern, params, encode = encodeURIComponent) {
|
|
|
3500
3916
|
let hadOmittedOptional = false;
|
|
3501
3917
|
for (const [key, value] of Object.entries(params)) {
|
|
3502
3918
|
const escaped = escapeRegExp2(key);
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3919
|
+
if (value === "") {
|
|
3920
|
+
result = result.replace(
|
|
3921
|
+
new RegExp(`:${escaped}(\\([^)]*\\))?(?!\\?)`),
|
|
3922
|
+
""
|
|
3923
|
+
);
|
|
3924
|
+
result = result.replace(`*${key}`, "");
|
|
3925
|
+
} else {
|
|
3926
|
+
result = result.replace(
|
|
3927
|
+
new RegExp(`:${escaped}(\\([^)]*\\))?\\??`),
|
|
3928
|
+
encode(value)
|
|
3929
|
+
);
|
|
3930
|
+
result = result.replace(`*${key}`, encode(value));
|
|
3931
|
+
}
|
|
3508
3932
|
}
|
|
3509
3933
|
result = result.replace(/:([a-zA-Z_][a-zA-Z0-9_]*)(\([^)]*\))?\?/g, () => {
|
|
3510
3934
|
hadOmittedOptional = true;
|
|
@@ -3610,8 +4034,14 @@ function copyStagedBuildAssets(projectRoot, fileNames) {
|
|
|
3610
4034
|
}
|
|
3611
4035
|
|
|
3612
4036
|
// src/vite/discovery/prerender-collection.ts
|
|
4037
|
+
var debug9 = createRangoDebugger(NS.prerender);
|
|
3613
4038
|
async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
3614
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
|
+
);
|
|
3615
4045
|
const entries = [];
|
|
3616
4046
|
const allRoutes = {};
|
|
3617
4047
|
for (const { manifest: m } of allManifests) {
|
|
@@ -3623,100 +4053,151 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3623
4053
|
if (!params) return pattern;
|
|
3624
4054
|
return substituteRouteParams(pattern, params);
|
|
3625
4055
|
};
|
|
4056
|
+
let resolvedRoutes = 0;
|
|
4057
|
+
let totalDynamic = 0;
|
|
3626
4058
|
for (const { manifest } of allManifests) {
|
|
3627
4059
|
if (!manifest.prerenderRoutes) continue;
|
|
3628
|
-
const defs = manifest._prerenderDefs || {};
|
|
3629
|
-
const passthroughSet = new Set(manifest.passthroughRoutes || []);
|
|
3630
4060
|
for (const routeName of manifest.prerenderRoutes) {
|
|
3631
4061
|
const pattern = manifest.routeManifest[routeName];
|
|
3632
|
-
if (
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
const
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
4062
|
+
if (pattern && (pattern.includes(":") || pattern.includes("*"))) {
|
|
4063
|
+
totalDynamic++;
|
|
4064
|
+
}
|
|
4065
|
+
}
|
|
4066
|
+
}
|
|
4067
|
+
const paramsStart = performance.now();
|
|
4068
|
+
const progressInterval = totalDynamic > 0 ? setInterval(() => {
|
|
4069
|
+
const elapsed = ((performance.now() - paramsStart) / 1e3).toFixed(1);
|
|
4070
|
+
console.log(
|
|
4071
|
+
`[rsc-router] Resolving prerender params... ${resolvedRoutes}/${totalDynamic} routes (${elapsed}s)`
|
|
4072
|
+
);
|
|
4073
|
+
}, 5e3) : void 0;
|
|
4074
|
+
try {
|
|
4075
|
+
for (const { manifest } of allManifests) {
|
|
4076
|
+
if (!manifest.prerenderRoutes) continue;
|
|
4077
|
+
const defs = manifest._prerenderDefs || {};
|
|
4078
|
+
const passthroughSet = new Set(manifest.passthroughRoutes || []);
|
|
4079
|
+
for (const routeName of manifest.prerenderRoutes) {
|
|
4080
|
+
const pattern = manifest.routeManifest[routeName];
|
|
4081
|
+
if (!pattern) continue;
|
|
4082
|
+
const def = defs[routeName];
|
|
4083
|
+
const isPassthroughRoute = passthroughSet.has(routeName);
|
|
4084
|
+
const hasDynamic = pattern.includes(":") || pattern.includes("*");
|
|
4085
|
+
if (!hasDynamic) {
|
|
4086
|
+
entries.push({
|
|
4087
|
+
urlPath: pattern.replace(/\/$/, "") || "/",
|
|
4088
|
+
routeName,
|
|
4089
|
+
concurrency: 1,
|
|
4090
|
+
isPassthroughRoute
|
|
4091
|
+
});
|
|
4092
|
+
} else {
|
|
4093
|
+
if (def?.getParams) {
|
|
4094
|
+
const getParamsStart = debug9 ? performance.now() : 0;
|
|
4095
|
+
try {
|
|
4096
|
+
const buildVars = {};
|
|
4097
|
+
const buildEnv = state.resolvedBuildEnv;
|
|
4098
|
+
const getParamsCtx = {
|
|
4099
|
+
build: true,
|
|
4100
|
+
dev: !state.isBuildMode,
|
|
4101
|
+
set: ((keyOrVar, value) => {
|
|
4102
|
+
contextSet(buildVars, keyOrVar, value);
|
|
4103
|
+
}),
|
|
4104
|
+
reverse: getParamsReverse,
|
|
4105
|
+
get env() {
|
|
4106
|
+
if (buildEnv !== void 0) return buildEnv;
|
|
4107
|
+
throw new Error(
|
|
4108
|
+
"[rsc-router] ctx.env is not available during build-time getParams(). Configure buildEnv in your rango() plugin options to enable build-time env access."
|
|
4109
|
+
);
|
|
3675
4110
|
}
|
|
3676
|
-
}
|
|
3677
|
-
|
|
3678
|
-
|
|
4111
|
+
};
|
|
4112
|
+
const paramsList = await def.getParams(getParamsCtx);
|
|
4113
|
+
debug9?.(
|
|
4114
|
+
"getParams %s -> %d params (%sms)",
|
|
3679
4115
|
routeName,
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
isPassthroughRoute
|
|
3683
|
-
});
|
|
3684
|
-
}
|
|
3685
|
-
} catch (err) {
|
|
3686
|
-
if (err.name === "Skip") {
|
|
3687
|
-
console.log(
|
|
3688
|
-
`[rsc-router] SKIP route "${routeName}" - ${err.message}`
|
|
4116
|
+
paramsList.length,
|
|
4117
|
+
(performance.now() - getParamsStart).toFixed(1)
|
|
3689
4118
|
);
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
4119
|
+
const concurrency = def.options?.concurrency ?? 1;
|
|
4120
|
+
const hasBuildVars = Object.keys(buildVars).length > 0 || Object.getOwnPropertySymbols(buildVars).length > 0;
|
|
4121
|
+
for (const params of paramsList) {
|
|
4122
|
+
let url = substituteRouteParams(
|
|
4123
|
+
pattern,
|
|
4124
|
+
params,
|
|
4125
|
+
encodePathParam
|
|
4126
|
+
);
|
|
4127
|
+
if (url.includes("*")) {
|
|
4128
|
+
const wildcardValue = params["*"] ?? params.splat;
|
|
4129
|
+
if (wildcardValue !== void 0) {
|
|
4130
|
+
url = url.replace(
|
|
4131
|
+
/\*[^/]*$/,
|
|
4132
|
+
encodePathParam(wildcardValue)
|
|
4133
|
+
);
|
|
4134
|
+
}
|
|
4135
|
+
}
|
|
4136
|
+
entries.push({
|
|
4137
|
+
urlPath: url.replace(/\/$/, "") || "/",
|
|
4138
|
+
routeName,
|
|
4139
|
+
concurrency,
|
|
4140
|
+
...hasBuildVars ? { buildVars } : {},
|
|
4141
|
+
isPassthroughRoute
|
|
4142
|
+
});
|
|
4143
|
+
}
|
|
4144
|
+
resolvedRoutes++;
|
|
4145
|
+
} catch (err) {
|
|
4146
|
+
resolvedRoutes++;
|
|
4147
|
+
if (err.name === "Skip") {
|
|
4148
|
+
console.log(
|
|
4149
|
+
`[rsc-router] SKIP route "${routeName}" - ${err.message}`
|
|
4150
|
+
);
|
|
4151
|
+
notifyOnError(
|
|
4152
|
+
registry,
|
|
4153
|
+
err,
|
|
4154
|
+
"prerender",
|
|
4155
|
+
routeName,
|
|
4156
|
+
void 0,
|
|
4157
|
+
true
|
|
4158
|
+
);
|
|
4159
|
+
continue;
|
|
4160
|
+
}
|
|
4161
|
+
console.error(
|
|
4162
|
+
`[rsc-router] Failed to get params for prerender route "${routeName}": ${err.message}`
|
|
3697
4163
|
);
|
|
3698
|
-
|
|
4164
|
+
notifyOnError(registry, err, "prerender", routeName);
|
|
4165
|
+
throw err;
|
|
3699
4166
|
}
|
|
3700
|
-
|
|
3701
|
-
|
|
4167
|
+
} else {
|
|
4168
|
+
console.warn(
|
|
4169
|
+
`[rsc-router] Dynamic prerender route "${routeName}" has no getParams(), skipping`
|
|
3702
4170
|
);
|
|
3703
|
-
notifyOnError(registry, err, "prerender", routeName);
|
|
3704
|
-
throw err;
|
|
3705
4171
|
}
|
|
3706
|
-
} else {
|
|
3707
|
-
console.warn(
|
|
3708
|
-
`[rsc-router] Dynamic prerender route "${routeName}" has no getParams(), skipping`
|
|
3709
|
-
);
|
|
3710
4172
|
}
|
|
3711
4173
|
}
|
|
3712
4174
|
}
|
|
4175
|
+
} finally {
|
|
4176
|
+
if (progressInterval) {
|
|
4177
|
+
clearInterval(progressInterval);
|
|
4178
|
+
const elapsed = ((performance.now() - paramsStart) / 1e3).toFixed(1);
|
|
4179
|
+
console.log(
|
|
4180
|
+
`[rsc-router] Resolved prerender params: ${resolvedRoutes}/${totalDynamic} routes (${elapsed}s)`
|
|
4181
|
+
);
|
|
4182
|
+
}
|
|
4183
|
+
}
|
|
4184
|
+
if (entries.length === 0) {
|
|
4185
|
+
debug9?.(
|
|
4186
|
+
"no prerender entries (done in %sms)",
|
|
4187
|
+
(performance.now() - overallStart).toFixed(1)
|
|
4188
|
+
);
|
|
4189
|
+
return;
|
|
3713
4190
|
}
|
|
3714
|
-
if (entries.length === 0) return;
|
|
3715
4191
|
const maxConcurrency = Math.max(...entries.map((e) => e.concurrency));
|
|
3716
4192
|
const concurrencyNote = maxConcurrency > 1 ? ` (concurrency: ${maxConcurrency})` : "";
|
|
3717
4193
|
console.log(
|
|
3718
4194
|
`[rsc-router] Pre-rendering ${entries.length} URL(s)${concurrencyNote}...`
|
|
3719
4195
|
);
|
|
4196
|
+
debug9?.(
|
|
4197
|
+
"prerender loop: %d entries, max concurrency %d",
|
|
4198
|
+
entries.length,
|
|
4199
|
+
maxConcurrency
|
|
4200
|
+
);
|
|
3720
4201
|
const { hashParams } = await rscEnv.runner.import("@rangojs/router/build");
|
|
3721
4202
|
const manifestEntries = {};
|
|
3722
4203
|
let doneCount = 0;
|
|
@@ -3823,10 +4304,22 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3823
4304
|
console.log(
|
|
3824
4305
|
`[rsc-router] Pre-render complete: ${parts.join(", ")} (${totalElapsed}ms total)`
|
|
3825
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
|
+
);
|
|
3826
4314
|
}
|
|
3827
4315
|
async function renderStaticHandlers(state, rscEnv, registry) {
|
|
3828
4316
|
if (!state.opts?.enableBuildPrerender || !state.isBuildMode || !state.resolvedStaticModules?.size)
|
|
3829
4317
|
return;
|
|
4318
|
+
const overallStart = debug9 ? performance.now() : 0;
|
|
4319
|
+
debug9?.(
|
|
4320
|
+
"renderStaticHandlers: start (%d static module(s))",
|
|
4321
|
+
state.resolvedStaticModules.size
|
|
4322
|
+
);
|
|
3830
4323
|
const manifestEntries = {};
|
|
3831
4324
|
let staticDone = 0;
|
|
3832
4325
|
let staticSkip = 0;
|
|
@@ -3916,13 +4409,29 @@ async function renderStaticHandlers(state, rscEnv, registry) {
|
|
|
3916
4409
|
console.log(
|
|
3917
4410
|
`[rsc-router] Static render complete: ${staticParts.join(", ")} (${totalStaticElapsed}ms total)`
|
|
3918
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
|
+
);
|
|
3919
4419
|
}
|
|
3920
4420
|
|
|
3921
4421
|
// src/vite/discovery/discover-routers.ts
|
|
4422
|
+
var debug10 = createRangoDebugger(NS.discovery);
|
|
3922
4423
|
async function discoverRouters(state, rscEnv) {
|
|
3923
4424
|
if (!state.resolvedEntryPath) return;
|
|
3924
|
-
await
|
|
3925
|
-
|
|
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
|
+
);
|
|
3926
4435
|
let registry = serverMod.RouterRegistry;
|
|
3927
4436
|
if (!registry || registry.size === 0) {
|
|
3928
4437
|
try {
|
|
@@ -3964,8 +4473,13 @@ async function discoverRouters(state, rscEnv) {
|
|
|
3964
4473
|
);
|
|
3965
4474
|
}
|
|
3966
4475
|
}
|
|
3967
|
-
const buildMod = await
|
|
4476
|
+
const buildMod = await timed(
|
|
4477
|
+
debug10,
|
|
4478
|
+
"inner: import @rangojs/router/build",
|
|
4479
|
+
() => rscEnv.runner.import("@rangojs/router/build")
|
|
4480
|
+
);
|
|
3968
4481
|
const generateManifestFull = buildMod.generateManifestFull;
|
|
4482
|
+
debug10?.("inner: found %d router(s) in registry", registry.size);
|
|
3969
4483
|
const nestedRouterConflict = findNestedRouterConflict(
|
|
3970
4484
|
[...registry.values()].map((router) => router.__sourceFile).filter(
|
|
3971
4485
|
(sourceFile) => typeof sourceFile === "string"
|
|
@@ -3984,6 +4498,7 @@ async function discoverRouters(state, rscEnv) {
|
|
|
3984
4498
|
let mergedRouteTrailingSlash = {};
|
|
3985
4499
|
let routerMountIndex = 0;
|
|
3986
4500
|
const allManifests = [];
|
|
4501
|
+
const manifestGenStart = debug10 ? performance.now() : 0;
|
|
3987
4502
|
for (const [id, router] of registry) {
|
|
3988
4503
|
if (!router.urlpatterns || !generateManifestFull) {
|
|
3989
4504
|
continue;
|
|
@@ -4058,7 +4573,13 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4058
4573
|
);
|
|
4059
4574
|
}
|
|
4060
4575
|
}
|
|
4576
|
+
debug10?.(
|
|
4577
|
+
"inner: generated manifests for %d router(s) (%sms)",
|
|
4578
|
+
allManifests.length,
|
|
4579
|
+
(performance.now() - manifestGenStart).toFixed(1)
|
|
4580
|
+
);
|
|
4061
4581
|
let newMergedRouteTrie = null;
|
|
4582
|
+
const trieStart = debug10 ? performance.now() : 0;
|
|
4062
4583
|
if (Object.keys(newMergedRouteManifest).length > 0) {
|
|
4063
4584
|
const buildRouteTrie = buildMod.buildRouteTrie;
|
|
4064
4585
|
if (buildRouteTrie && mergedRouteAncestry) {
|
|
@@ -4121,6 +4642,10 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4121
4642
|
}
|
|
4122
4643
|
}
|
|
4123
4644
|
}
|
|
4645
|
+
debug10?.(
|
|
4646
|
+
"inner: trie build done (%sms)",
|
|
4647
|
+
(performance.now() - trieStart).toFixed(1)
|
|
4648
|
+
);
|
|
4124
4649
|
state.mergedRouteManifest = newMergedRouteManifest;
|
|
4125
4650
|
state.mergedPrecomputedEntries = newMergedPrecomputedEntries;
|
|
4126
4651
|
state.perRouterManifests = newPerRouterManifests;
|
|
@@ -4560,8 +5085,101 @@ function postprocessBundle(state) {
|
|
|
4560
5085
|
}
|
|
4561
5086
|
}
|
|
4562
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
|
+
|
|
4563
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);
|
|
5167
|
+
var loaderHookRegistered = false;
|
|
5168
|
+
function ensureCloudflareProtocolLoaderRegistered() {
|
|
5169
|
+
if (loaderHookRegistered) return;
|
|
5170
|
+
loaderHookRegistered = true;
|
|
5171
|
+
try {
|
|
5172
|
+
register(
|
|
5173
|
+
new URL("./plugins/cloudflare-protocol-loader-hook.mjs", import.meta.url)
|
|
5174
|
+
);
|
|
5175
|
+
} catch (err) {
|
|
5176
|
+
console.warn(
|
|
5177
|
+
`[rsc-router] Could not register Node ESM loader hook for cloudflare:* imports (${err?.message ?? err}). Falling back to Vite transform only.`
|
|
5178
|
+
);
|
|
5179
|
+
}
|
|
5180
|
+
}
|
|
4564
5181
|
async function createTempRscServer(state, options = {}) {
|
|
5182
|
+
ensureCloudflareProtocolLoaderRegistered();
|
|
4565
5183
|
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
4566
5184
|
return createViteServer({
|
|
4567
5185
|
root: state.projectRoot,
|
|
@@ -4584,6 +5202,7 @@ async function createTempRscServer(state, options = {}) {
|
|
|
4584
5202
|
...options.forceBuild ? [hashClientRefs(state.projectRoot)] : [],
|
|
4585
5203
|
createVersionPlugin(),
|
|
4586
5204
|
createVirtualStubPlugin(),
|
|
5205
|
+
createCloudflareProtocolStubPlugin(),
|
|
4587
5206
|
// Dev prerender must use dev-mode IDs (path-based) to match the workerd
|
|
4588
5207
|
// runtime. forceBuild produces hashed IDs for production bundle consistency.
|
|
4589
5208
|
exposeInternalIds(options.forceBuild ? { forceBuild: true } : void 0),
|
|
@@ -4600,7 +5219,7 @@ async function resolveBuildEnv(option, factoryCtx) {
|
|
|
4600
5219
|
);
|
|
4601
5220
|
}
|
|
4602
5221
|
try {
|
|
4603
|
-
const userRequire =
|
|
5222
|
+
const userRequire = createRequire2(
|
|
4604
5223
|
resolve8(factoryCtx.root, "package.json")
|
|
4605
5224
|
);
|
|
4606
5225
|
const wranglerPath = userRequire.resolve("wrangler");
|
|
@@ -4635,6 +5254,7 @@ async function acquireBuildEnv(s, command, mode) {
|
|
|
4635
5254
|
if (!result) return false;
|
|
4636
5255
|
s.resolvedBuildEnv = result.env;
|
|
4637
5256
|
s.buildEnvDispose = result.dispose ?? null;
|
|
5257
|
+
globalThis[BUILD_ENV_GLOBAL_KEY] = result.env;
|
|
4638
5258
|
return true;
|
|
4639
5259
|
}
|
|
4640
5260
|
async function releaseBuildEnv(s) {
|
|
@@ -4647,6 +5267,7 @@ async function releaseBuildEnv(s) {
|
|
|
4647
5267
|
s.buildEnvDispose = null;
|
|
4648
5268
|
}
|
|
4649
5269
|
s.resolvedBuildEnv = void 0;
|
|
5270
|
+
delete globalThis[BUILD_ENV_GLOBAL_KEY];
|
|
4650
5271
|
}
|
|
4651
5272
|
function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
4652
5273
|
const s = createDiscoveryState(entryPath, opts);
|
|
@@ -4702,6 +5323,9 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4702
5323
|
const discoveryPromise = new Promise((resolve10) => {
|
|
4703
5324
|
resolveDiscovery = resolve10;
|
|
4704
5325
|
});
|
|
5326
|
+
const gate = createDiscoveryGate(s, debugDiscovery);
|
|
5327
|
+
const beginDiscoveryGate = gate.beginGate;
|
|
5328
|
+
const resolveDiscoveryGate = gate.resolveGate;
|
|
4705
5329
|
const getDevServerOrigin = () => server.resolvedUrls?.local?.[0]?.replace(/\/$/, "") || `http://localhost:${server.config.server.port || 5173}`;
|
|
4706
5330
|
let prerenderTempServer = null;
|
|
4707
5331
|
let prerenderNodeRegistry = null;
|
|
@@ -4714,40 +5338,180 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4714
5338
|
releaseBuildEnv(s).catch(() => {
|
|
4715
5339
|
});
|
|
4716
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
|
+
}
|
|
4717
5372
|
async function getOrCreateTempServer() {
|
|
4718
|
-
if (
|
|
4719
|
-
|
|
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
|
+
}
|
|
4720
5407
|
}
|
|
5408
|
+
debugDiscovery?.(
|
|
5409
|
+
"getOrCreateTempServer: creating new temp server, entry=%s",
|
|
5410
|
+
s.resolvedEntryPath ?? "(unset)"
|
|
5411
|
+
);
|
|
4721
5412
|
try {
|
|
4722
5413
|
prerenderTempServer = await createTempRscServer(s, {
|
|
4723
5414
|
cacheDir: "node_modules/.vite_prerender"
|
|
4724
5415
|
});
|
|
4725
5416
|
const tempRscEnv = prerenderTempServer.environments?.rsc;
|
|
4726
5417
|
if (tempRscEnv?.runner) {
|
|
4727
|
-
await tempRscEnv
|
|
4728
|
-
const serverMod = await tempRscEnv.runner.import(
|
|
4729
|
-
"@rangojs/router/server"
|
|
4730
|
-
);
|
|
4731
|
-
prerenderNodeRegistry = serverMod.RouterRegistry;
|
|
5418
|
+
await importEntryAndRegistry(tempRscEnv);
|
|
4732
5419
|
return tempRscEnv;
|
|
4733
5420
|
}
|
|
5421
|
+
debugDiscovery?.(
|
|
5422
|
+
"getOrCreateTempServer: tempRscEnv.runner unavailable"
|
|
5423
|
+
);
|
|
4734
5424
|
} catch (err) {
|
|
5425
|
+
debugDiscovery?.(
|
|
5426
|
+
"getOrCreateTempServer: FAILED message=%s",
|
|
5427
|
+
err.message
|
|
5428
|
+
);
|
|
4735
5429
|
console.warn(
|
|
4736
5430
|
`[rsc-router] Failed to create temp runner: ${err.message}`
|
|
4737
5431
|
);
|
|
4738
5432
|
}
|
|
4739
5433
|
return null;
|
|
4740
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
|
+
}
|
|
4741
5484
|
const discover = async () => {
|
|
5485
|
+
const discoverStart = performance.now();
|
|
4742
5486
|
const rscEnv = server.environments?.rsc;
|
|
4743
5487
|
if (!rscEnv?.runner) {
|
|
5488
|
+
debugDiscovery?.(
|
|
5489
|
+
"dev: cloudflare path start, __rscRouterDiscoveryActive=%s",
|
|
5490
|
+
globalThis.__rscRouterDiscoveryActive ?? false
|
|
5491
|
+
);
|
|
4744
5492
|
s.devServerOrigin = getDevServerOrigin();
|
|
4745
5493
|
try {
|
|
4746
|
-
await
|
|
4747
|
-
|
|
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
|
+
);
|
|
4748
5504
|
if (tempRscEnv) {
|
|
4749
|
-
await
|
|
4750
|
-
|
|
5505
|
+
await timed(
|
|
5506
|
+
debugDiscovery,
|
|
5507
|
+
"discoverRouters (cloudflare)",
|
|
5508
|
+
() => discoverRouters(s, tempRscEnv)
|
|
5509
|
+
);
|
|
5510
|
+
timedSync(
|
|
5511
|
+
debugDiscovery,
|
|
5512
|
+
"writeRouteTypesFiles",
|
|
5513
|
+
() => writeRouteTypesFiles(s)
|
|
5514
|
+
);
|
|
4751
5515
|
}
|
|
4752
5516
|
} catch (err) {
|
|
4753
5517
|
console.warn(
|
|
@@ -4755,33 +5519,62 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4755
5519
|
${err.stack}`
|
|
4756
5520
|
);
|
|
4757
5521
|
}
|
|
5522
|
+
debugDiscovery?.(
|
|
5523
|
+
"dev discovery done (%sms)",
|
|
5524
|
+
(performance.now() - discoverStart).toFixed(1)
|
|
5525
|
+
);
|
|
4758
5526
|
resolveDiscovery();
|
|
4759
5527
|
return;
|
|
4760
5528
|
}
|
|
4761
5529
|
try {
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
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")
|
|
4765
5540
|
);
|
|
4766
5541
|
if (serverMod?.setManifestReadyPromise) {
|
|
4767
5542
|
serverMod.setManifestReadyPromise(discoveryPromise);
|
|
4768
5543
|
}
|
|
4769
|
-
await
|
|
5544
|
+
await timed(
|
|
5545
|
+
debugDiscovery,
|
|
5546
|
+
"discoverRouters",
|
|
5547
|
+
() => discoverRouters(s, rscEnv)
|
|
5548
|
+
);
|
|
4770
5549
|
s.devServerOrigin = getDevServerOrigin();
|
|
4771
|
-
|
|
4772
|
-
|
|
5550
|
+
timedSync(
|
|
5551
|
+
debugDiscovery,
|
|
5552
|
+
"writeRouteTypesFiles",
|
|
5553
|
+
() => writeRouteTypesFiles(s)
|
|
5554
|
+
);
|
|
5555
|
+
await timed(
|
|
5556
|
+
debugDiscovery,
|
|
5557
|
+
"propagateDiscoveryState",
|
|
5558
|
+
() => propagateDiscoveryState(rscEnv)
|
|
5559
|
+
);
|
|
4773
5560
|
} catch (err) {
|
|
4774
5561
|
console.warn(
|
|
4775
5562
|
`[rsc-router] Router discovery failed: ${err.message}
|
|
4776
5563
|
${err.stack}`
|
|
4777
5564
|
);
|
|
4778
5565
|
} finally {
|
|
5566
|
+
debugDiscovery?.(
|
|
5567
|
+
"dev discovery done (%sms)",
|
|
5568
|
+
(performance.now() - discoverStart).toFixed(1)
|
|
5569
|
+
);
|
|
4779
5570
|
resolveDiscovery();
|
|
4780
5571
|
}
|
|
4781
5572
|
};
|
|
4782
|
-
|
|
4783
|
-
|
|
4784
|
-
|
|
5573
|
+
beginDiscoveryGate();
|
|
5574
|
+
setTimeout(
|
|
5575
|
+
() => discover().then(resolveDiscoveryGate, resolveDiscoveryGate),
|
|
5576
|
+
0
|
|
5577
|
+
);
|
|
4785
5578
|
let mainRegistry = null;
|
|
4786
5579
|
const propagateDiscoveryState = async (rscEnv) => {
|
|
4787
5580
|
const serverMod = await rscEnv.runner.import("@rangojs/router/server");
|
|
@@ -4816,12 +5609,23 @@ ${err.stack}`
|
|
|
4816
5609
|
}
|
|
4817
5610
|
};
|
|
4818
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
|
+
};
|
|
4819
5622
|
if (s.discoveryDone) await s.discoveryDone;
|
|
4820
5623
|
const url = new URL(req.url || "/", "http://localhost");
|
|
4821
5624
|
const pathname = url.searchParams.get("pathname");
|
|
4822
5625
|
if (!pathname) {
|
|
4823
5626
|
res.statusCode = 400;
|
|
4824
5627
|
res.end("Missing pathname");
|
|
5628
|
+
logResult(400, "missing pathname");
|
|
4825
5629
|
return;
|
|
4826
5630
|
}
|
|
4827
5631
|
const rscEnv = server.environments?.rsc;
|
|
@@ -4839,6 +5643,7 @@ ${err.stack}`
|
|
|
4839
5643
|
);
|
|
4840
5644
|
res.statusCode = 500;
|
|
4841
5645
|
res.end(`Prerender handler error: ${err.message}`);
|
|
5646
|
+
logResult(500, "module refresh failed");
|
|
4842
5647
|
return;
|
|
4843
5648
|
}
|
|
4844
5649
|
} else {
|
|
@@ -4853,6 +5658,7 @@ ${err.stack}`
|
|
|
4853
5658
|
if (!registry || registry.size === 0) {
|
|
4854
5659
|
res.statusCode = 503;
|
|
4855
5660
|
res.end("Prerender runner not available");
|
|
5661
|
+
logResult(503, "no registry");
|
|
4856
5662
|
return;
|
|
4857
5663
|
}
|
|
4858
5664
|
const wantIntercept = url.searchParams.get("intercept") === "1";
|
|
@@ -4887,6 +5693,7 @@ ${err.stack}`
|
|
|
4887
5693
|
payload = { segments: result.segments, handles: result.handles };
|
|
4888
5694
|
}
|
|
4889
5695
|
res.end(JSON.stringify(payload));
|
|
5696
|
+
logResult(200, `match ${result.routeName}`);
|
|
4890
5697
|
return;
|
|
4891
5698
|
} catch (err) {
|
|
4892
5699
|
console.warn(
|
|
@@ -4896,6 +5703,7 @@ ${err.stack}`
|
|
|
4896
5703
|
}
|
|
4897
5704
|
res.statusCode = 404;
|
|
4898
5705
|
res.end("No prerender match");
|
|
5706
|
+
logResult(404, "no match");
|
|
4899
5707
|
});
|
|
4900
5708
|
if (opts?.staticRouteTypesGeneration !== false) {
|
|
4901
5709
|
const isGeneratedRouteFile = (filePath) => filePath.endsWith(".gen.ts") && (filePath.includes("named-routes.gen.ts") || filePath.includes("urls.gen.ts"));
|
|
@@ -4915,42 +5723,96 @@ ${err.stack}`
|
|
|
4915
5723
|
return true;
|
|
4916
5724
|
};
|
|
4917
5725
|
let routeChangeTimer;
|
|
4918
|
-
let runtimeRediscoveryInProgress = false;
|
|
4919
5726
|
const refreshRuntimeDiscovery = async () => {
|
|
4920
5727
|
const rscEnv = server.environments?.rsc;
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
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
|
+
});
|
|
4934
5782
|
};
|
|
4935
5783
|
const scheduleRouteRegeneration = () => {
|
|
4936
5784
|
clearTimeout(routeChangeTimer);
|
|
4937
5785
|
routeChangeTimer = setTimeout(() => {
|
|
4938
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;
|
|
4939
5790
|
try {
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
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
|
+
}
|
|
4943
5800
|
}
|
|
4944
5801
|
} catch (err) {
|
|
4945
5802
|
console.error(
|
|
4946
5803
|
`[rsc-router] Route regeneration error: ${err.message}`
|
|
4947
5804
|
);
|
|
4948
5805
|
}
|
|
5806
|
+
debugDiscovery?.(
|
|
5807
|
+
"watcher: regenerated gen files (%sms)",
|
|
5808
|
+
(performance.now() - regenStart).toFixed(1)
|
|
5809
|
+
);
|
|
4949
5810
|
if (s.perRouterManifests.length > 0) {
|
|
4950
5811
|
refreshRuntimeDiscovery().catch((err) => {
|
|
4951
5812
|
console.warn(
|
|
4952
5813
|
`[rsc-router] Runtime re-discovery error: ${err.message}`
|
|
4953
5814
|
);
|
|
5815
|
+
resolveDiscoveryGate();
|
|
4954
5816
|
});
|
|
4955
5817
|
}
|
|
4956
5818
|
}, 100);
|
|
@@ -4968,6 +5830,12 @@ ${err.stack}`
|
|
|
4968
5830
|
const hasUrls = source.includes("urls(");
|
|
4969
5831
|
const hasCreateRouter = /\bcreateRouter\s*[<(]/.test(source);
|
|
4970
5832
|
if (!hasUrls && !hasCreateRouter) return;
|
|
5833
|
+
debugDiscovery?.(
|
|
5834
|
+
"watcher: %s matches (urls=%s, router=%s)",
|
|
5835
|
+
filePath,
|
|
5836
|
+
hasUrls,
|
|
5837
|
+
hasCreateRouter
|
|
5838
|
+
);
|
|
4971
5839
|
if (hasCreateRouter) {
|
|
4972
5840
|
const nestedRouterConflict = findNestedRouterConflict([
|
|
4973
5841
|
...s.cachedRouterFiles ?? [],
|
|
@@ -4981,6 +5849,9 @@ ${err.stack}`
|
|
|
4981
5849
|
}
|
|
4982
5850
|
s.cachedRouterFiles = void 0;
|
|
4983
5851
|
}
|
|
5852
|
+
if (s.perRouterManifests.length > 0) {
|
|
5853
|
+
gate.noteRouteEvent();
|
|
5854
|
+
}
|
|
4984
5855
|
scheduleRouteRegeneration();
|
|
4985
5856
|
} catch {
|
|
4986
5857
|
}
|
|
@@ -5000,15 +5871,31 @@ ${err.stack}`
|
|
|
5000
5871
|
// The manifest data is stored for the virtual module's load hook.
|
|
5001
5872
|
async buildStart() {
|
|
5002
5873
|
if (!s.isBuildMode) return;
|
|
5003
|
-
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 ?? "?");
|
|
5004
5883
|
resetStagedBuildAssets(s.projectRoot);
|
|
5005
5884
|
s.prerenderManifestEntries = null;
|
|
5006
5885
|
s.staticManifestEntries = null;
|
|
5007
|
-
await
|
|
5886
|
+
await timed(
|
|
5887
|
+
debugDiscovery,
|
|
5888
|
+
"build acquireBuildEnv",
|
|
5889
|
+
() => acquireBuildEnv(s, viteCommand, viteMode)
|
|
5890
|
+
);
|
|
5008
5891
|
let tempServer = null;
|
|
5009
5892
|
globalThis.__rscRouterDiscoveryActive = true;
|
|
5010
5893
|
try {
|
|
5011
|
-
tempServer = await
|
|
5894
|
+
tempServer = await timed(
|
|
5895
|
+
debugDiscovery,
|
|
5896
|
+
"build createTempRscServer",
|
|
5897
|
+
() => createTempRscServer(s, { forceBuild: true })
|
|
5898
|
+
);
|
|
5012
5899
|
const rscEnv = tempServer.environments?.rsc;
|
|
5013
5900
|
if (!rscEnv?.runner) {
|
|
5014
5901
|
console.warn(
|
|
@@ -5022,8 +5909,16 @@ ${err.stack}`
|
|
|
5022
5909
|
if (tempIdsPlugin?.api?.staticHandlerModules) {
|
|
5023
5910
|
s.resolvedStaticModules = tempIdsPlugin.api.staticHandlerModules;
|
|
5024
5911
|
}
|
|
5025
|
-
await
|
|
5026
|
-
|
|
5912
|
+
await timed(
|
|
5913
|
+
debugDiscovery,
|
|
5914
|
+
"build discoverRouters",
|
|
5915
|
+
() => discoverRouters(s, rscEnv)
|
|
5916
|
+
);
|
|
5917
|
+
timedSync(
|
|
5918
|
+
debugDiscovery,
|
|
5919
|
+
"build writeRouteTypesFiles",
|
|
5920
|
+
() => writeRouteTypesFiles(s)
|
|
5921
|
+
);
|
|
5027
5922
|
} catch (err) {
|
|
5028
5923
|
const sourceFile = err.stack?.split("\n").find(
|
|
5029
5924
|
(line) => line.includes(s.projectRoot) && !line.includes("node_modules")
|
|
@@ -5042,9 +5937,45 @@ ${details}`
|
|
|
5042
5937
|
} finally {
|
|
5043
5938
|
delete globalThis.__rscRouterDiscoveryActive;
|
|
5044
5939
|
if (tempServer) {
|
|
5045
|
-
await
|
|
5940
|
+
await timed(
|
|
5941
|
+
debugDiscovery,
|
|
5942
|
+
"build tempServer.close",
|
|
5943
|
+
() => tempServer.close()
|
|
5944
|
+
);
|
|
5046
5945
|
}
|
|
5047
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 [];
|
|
5048
5979
|
}
|
|
5049
5980
|
},
|
|
5050
5981
|
// Virtual module: provides the pre-generated route manifest as a JS module
|
|
@@ -5061,17 +5992,36 @@ ${details}`
|
|
|
5061
5992
|
async load(id) {
|
|
5062
5993
|
if (id === "\0" + VIRTUAL_ROUTES_MANIFEST_ID) {
|
|
5063
5994
|
if (s.discoveryDone) {
|
|
5064
|
-
await
|
|
5995
|
+
await timed(
|
|
5996
|
+
debugRoutes,
|
|
5997
|
+
"await discoveryDone (manifest)",
|
|
5998
|
+
() => s.discoveryDone
|
|
5999
|
+
);
|
|
5065
6000
|
}
|
|
5066
|
-
|
|
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;
|
|
5067
6008
|
}
|
|
5068
6009
|
const perRouterPrefix = "\0" + VIRTUAL_ROUTES_MANIFEST_ID + "/";
|
|
5069
6010
|
if (id.startsWith(perRouterPrefix)) {
|
|
5070
6011
|
if (s.discoveryDone) {
|
|
5071
|
-
await
|
|
6012
|
+
await timed(
|
|
6013
|
+
debugRoutes,
|
|
6014
|
+
"await discoveryDone (per-router)",
|
|
6015
|
+
() => s.discoveryDone
|
|
6016
|
+
);
|
|
5072
6017
|
}
|
|
5073
6018
|
const routerId = id.slice(perRouterPrefix.length);
|
|
5074
|
-
|
|
6019
|
+
const code = await timed(
|
|
6020
|
+
debugRoutes,
|
|
6021
|
+
`generatePerRouterModule ${routerId}`,
|
|
6022
|
+
() => generatePerRouterModule(s, routerId)
|
|
6023
|
+
);
|
|
6024
|
+
return code;
|
|
5075
6025
|
}
|
|
5076
6026
|
return null;
|
|
5077
6027
|
},
|
|
@@ -5079,14 +6029,20 @@ ${details}`
|
|
|
5079
6029
|
// Used by closeBundle for handler code eviction and prerender data injection.
|
|
5080
6030
|
generateBundle(_options, bundle) {
|
|
5081
6031
|
if (this.environment?.name !== "rsc") return;
|
|
6032
|
+
const genStart = debugBuild ? performance.now() : 0;
|
|
5082
6033
|
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
5083
6034
|
if (chunk.type === "chunk" && chunk.isEntry) {
|
|
5084
6035
|
s.rscEntryFileName = fileName;
|
|
5085
6036
|
break;
|
|
5086
6037
|
}
|
|
5087
6038
|
}
|
|
5088
|
-
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
|
+
);
|
|
5089
6044
|
return;
|
|
6045
|
+
}
|
|
5090
6046
|
s.handlerChunkInfoMap.clear();
|
|
5091
6047
|
s.staticHandlerChunkInfoMap.clear();
|
|
5092
6048
|
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
@@ -5130,6 +6086,13 @@ ${details}`
|
|
|
5130
6086
|
}
|
|
5131
6087
|
}
|
|
5132
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
|
+
);
|
|
5133
6096
|
},
|
|
5134
6097
|
// Build-time pre-rendering: evict handler code and inject collected prerender data.
|
|
5135
6098
|
// Collection now happens in-process during discoverRouters() via RSC runner.
|
|
@@ -5140,29 +6103,41 @@ ${details}`
|
|
|
5140
6103
|
async handler() {
|
|
5141
6104
|
if (!s.isBuildMode) return;
|
|
5142
6105
|
if (this.environment && this.environment.name !== "rsc") return;
|
|
5143
|
-
|
|
6106
|
+
timedSync(
|
|
6107
|
+
debugBuild,
|
|
6108
|
+
"closeBundle postprocessBundle",
|
|
6109
|
+
() => postprocessBundle(s)
|
|
6110
|
+
);
|
|
5144
6111
|
}
|
|
5145
6112
|
}
|
|
5146
6113
|
};
|
|
5147
6114
|
}
|
|
5148
6115
|
|
|
5149
6116
|
// src/vite/rango.ts
|
|
6117
|
+
var debugConfig = createRangoDebugger(NS.config);
|
|
5150
6118
|
async function rango(options) {
|
|
6119
|
+
const rangoStart = performance.now();
|
|
5151
6120
|
const resolvedOptions = options ?? { preset: "node" };
|
|
5152
6121
|
const preset = resolvedOptions.preset ?? "node";
|
|
5153
6122
|
const showBanner = resolvedOptions.banner ?? true;
|
|
6123
|
+
debugConfig?.("rango(%s) setup start", preset);
|
|
5154
6124
|
const plugins = [];
|
|
5155
|
-
const rangoAliases = getPackageAliases();
|
|
6125
|
+
const rangoAliases = { ...getPackageAliases(), ...getVendorAliases() };
|
|
5156
6126
|
const excludeDeps = [
|
|
5157
6127
|
...getExcludeDeps(),
|
|
5158
|
-
//
|
|
5159
|
-
//
|
|
5160
|
-
// .
|
|
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.
|
|
5161
6136
|
"@vitejs/plugin-rsc/browser",
|
|
5162
|
-
// Keep the browser RSDW client out of Vite's dep optimizer so our
|
|
5163
|
-
// cjs-to-esm transform can patch the real file.
|
|
5164
6137
|
"@vitejs/plugin-rsc/vendor/react-server-dom/client.browser"
|
|
5165
6138
|
];
|
|
6139
|
+
const pkg = getPublishedPackageName();
|
|
6140
|
+
const nested = (spec) => `${pkg} > ${spec}`;
|
|
5166
6141
|
const routerRef = { path: void 0 };
|
|
5167
6142
|
const prerenderEnabled = true;
|
|
5168
6143
|
if (preset === "cloudflare") {
|
|
@@ -5200,7 +6175,7 @@ async function rango(options) {
|
|
|
5200
6175
|
// Pre-bundle rsc-html-stream to prevent discovery during first request
|
|
5201
6176
|
// Exclude rsc-router modules to ensure same Context instance
|
|
5202
6177
|
optimizeDeps: {
|
|
5203
|
-
include: ["rsc-html-stream/client"],
|
|
6178
|
+
include: [nested("rsc-html-stream/client")],
|
|
5204
6179
|
exclude: excludeDeps,
|
|
5205
6180
|
esbuildOptions: sharedEsbuildOptions
|
|
5206
6181
|
}
|
|
@@ -5225,8 +6200,10 @@ async function rango(options) {
|
|
|
5225
6200
|
"react-dom/static.edge",
|
|
5226
6201
|
"react/jsx-runtime",
|
|
5227
6202
|
"react/jsx-dev-runtime",
|
|
5228
|
-
"rsc-html-stream/server",
|
|
5229
|
-
|
|
6203
|
+
nested("rsc-html-stream/server"),
|
|
6204
|
+
nested(
|
|
6205
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge"
|
|
6206
|
+
)
|
|
5230
6207
|
],
|
|
5231
6208
|
exclude: excludeDeps,
|
|
5232
6209
|
esbuildOptions: sharedEsbuildOptions
|
|
@@ -5241,7 +6218,9 @@ async function rango(options) {
|
|
|
5241
6218
|
"react",
|
|
5242
6219
|
"react/jsx-runtime",
|
|
5243
6220
|
"react/jsx-dev-runtime",
|
|
5244
|
-
|
|
6221
|
+
nested(
|
|
6222
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge"
|
|
6223
|
+
)
|
|
5245
6224
|
],
|
|
5246
6225
|
exclude: excludeDeps,
|
|
5247
6226
|
esbuildOptions: sharedEsbuildOptions
|
|
@@ -5322,7 +6301,7 @@ ${list}`);
|
|
|
5322
6301
|
"react-dom",
|
|
5323
6302
|
"react/jsx-runtime",
|
|
5324
6303
|
"react/jsx-dev-runtime",
|
|
5325
|
-
"rsc-html-stream/client"
|
|
6304
|
+
nested("rsc-html-stream/client")
|
|
5326
6305
|
],
|
|
5327
6306
|
exclude: excludeDeps,
|
|
5328
6307
|
esbuildOptions: sharedEsbuildOptions,
|
|
@@ -5339,7 +6318,9 @@ ${list}`);
|
|
|
5339
6318
|
"react-dom/static.edge",
|
|
5340
6319
|
"react/jsx-runtime",
|
|
5341
6320
|
"react/jsx-dev-runtime",
|
|
5342
|
-
|
|
6321
|
+
nested(
|
|
6322
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge"
|
|
6323
|
+
)
|
|
5343
6324
|
],
|
|
5344
6325
|
exclude: excludeDeps,
|
|
5345
6326
|
esbuildOptions: sharedEsbuildOptions
|
|
@@ -5352,7 +6333,9 @@ ${list}`);
|
|
|
5352
6333
|
"react",
|
|
5353
6334
|
"react/jsx-runtime",
|
|
5354
6335
|
"react/jsx-dev-runtime",
|
|
5355
|
-
|
|
6336
|
+
nested(
|
|
6337
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge"
|
|
6338
|
+
)
|
|
5356
6339
|
],
|
|
5357
6340
|
esbuildOptions: sharedEsbuildOptions
|
|
5358
6341
|
}
|
|
@@ -5422,6 +6405,12 @@ ${list}`);
|
|
|
5422
6405
|
preset
|
|
5423
6406
|
})
|
|
5424
6407
|
);
|
|
6408
|
+
debugConfig?.(
|
|
6409
|
+
"rango(%s) setup done: %d plugin(s) (%sms)",
|
|
6410
|
+
preset,
|
|
6411
|
+
plugins.length,
|
|
6412
|
+
(performance.now() - rangoStart).toFixed(1)
|
|
6413
|
+
);
|
|
5425
6414
|
return plugins;
|
|
5426
6415
|
}
|
|
5427
6416
|
|
|
@@ -5432,7 +6421,7 @@ function poke() {
|
|
|
5432
6421
|
apply: "serve",
|
|
5433
6422
|
configureServer(server) {
|
|
5434
6423
|
const stdin = process.stdin;
|
|
5435
|
-
const
|
|
6424
|
+
const debug11 = process.env.RANGO_POKE_DEBUG === "1";
|
|
5436
6425
|
const triggerReload = (source) => {
|
|
5437
6426
|
server.hot.send({ type: "full-reload", path: "*" });
|
|
5438
6427
|
server.config.logger.info(` browser reload (${source})`, {
|
|
@@ -5465,7 +6454,7 @@ function poke() {
|
|
|
5465
6454
|
lines.pop();
|
|
5466
6455
|
return lines;
|
|
5467
6456
|
};
|
|
5468
|
-
if (
|
|
6457
|
+
if (debug11) {
|
|
5469
6458
|
server.config.logger.info(
|
|
5470
6459
|
` poke debug enabled (isTTY=${stdin.isTTY ? "yes" : "no"}, isRaw=${stdin.isTTY ? stdin.isRaw ? "yes" : "no" : "n/a"})`,
|
|
5471
6460
|
{ timestamp: true }
|
|
@@ -5478,7 +6467,7 @@ function poke() {
|
|
|
5478
6467
|
);
|
|
5479
6468
|
}
|
|
5480
6469
|
const onData = (data) => {
|
|
5481
|
-
if (
|
|
6470
|
+
if (debug11) {
|
|
5482
6471
|
server.config.logger.info(` poke stdin ${formatChunk(data)}`, {
|
|
5483
6472
|
timestamp: true
|
|
5484
6473
|
});
|