@rangojs/router 0.0.0-experimental.66 → 0.0.0-experimental.66cdebe3
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 +1462 -422
- 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 +151 -9
- 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 +95 -44
- 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 +69 -28
- 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 +44 -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 +545 -304
- 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,226 +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
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1402
|
+
if (wholeFile) return wholeFile;
|
|
1403
|
+
}
|
|
1404
|
+
if (hasPrerenderHandlerCode && isRscEnv && isBuild) {
|
|
1405
|
+
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1406
|
+
const exportNames = getBindings(code, fnNames).map(
|
|
1407
|
+
(b) => b.exportNames[0]
|
|
1408
|
+
);
|
|
1409
|
+
if (exportNames.length > 0) {
|
|
1410
|
+
prerenderHandlerModules.set(id, exportNames);
|
|
1299
1411
|
}
|
|
1300
1412
|
}
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
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
|
+
}
|
|
1321
1442
|
}
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
}
|
|
1328
|
-
if (hasHandleCode) {
|
|
1329
|
-
const fnNames = getFnNames("createHandle");
|
|
1330
|
-
changed = transformHandles(
|
|
1331
|
-
getBindings(code, fnNames),
|
|
1332
|
-
s,
|
|
1333
|
-
code,
|
|
1334
|
-
filePath,
|
|
1335
|
-
isBuild
|
|
1336
|
-
) || changed;
|
|
1337
|
-
}
|
|
1338
|
-
if (hasLocationStateCode) {
|
|
1339
|
-
const fnNames = getFnNames("createLocationState");
|
|
1340
|
-
changed = transformLocationState(
|
|
1341
|
-
getBindings(code, fnNames),
|
|
1342
|
-
s,
|
|
1343
|
-
filePath,
|
|
1344
|
-
isBuild
|
|
1345
|
-
) || changed;
|
|
1346
|
-
}
|
|
1347
|
-
if (hasPrerenderHandlerCode) {
|
|
1348
|
-
const fnNames = getFnNames(PRERENDER_CONFIG.fnName);
|
|
1349
|
-
const bindings = getBindings(code, fnNames);
|
|
1350
|
-
if (isRscEnv) {
|
|
1351
|
-
changed = transformHandlerIds(
|
|
1352
|
-
PRERENDER_CONFIG,
|
|
1443
|
+
if (hasStaticHandlerCode && !isRscEnv) {
|
|
1444
|
+
const fnNames = getFnNames(STATIC_CONFIG.fnName);
|
|
1445
|
+
const bindings = getBindings(code, fnNames);
|
|
1446
|
+
const wholeFile = generateWholeFileStubs(
|
|
1447
|
+
STATIC_CONFIG,
|
|
1353
1448
|
bindings,
|
|
1449
|
+
code,
|
|
1450
|
+
filePath,
|
|
1451
|
+
isBuild
|
|
1452
|
+
);
|
|
1453
|
+
if (wholeFile) return wholeFile;
|
|
1454
|
+
}
|
|
1455
|
+
if (!isRscEnv && (hasPrerenderHandlerCode || hasStaticHandlerCode)) {
|
|
1456
|
+
const prerenderFnNames = hasPrerenderHandlerCode ? getFnNames(PRERENDER_CONFIG.fnName) : [];
|
|
1457
|
+
const staticFnNames = hasStaticHandlerCode ? getFnNames(STATIC_CONFIG.fnName) : [];
|
|
1458
|
+
const loaderFnNames = hasLoaderCode ? getFnNames("createLoader") : [];
|
|
1459
|
+
const handleFnNames = hasHandleCode ? getFnNames("createHandle") : [];
|
|
1460
|
+
const lsFnNames = hasLocationStateCode ? getFnNames("createLocationState") : [];
|
|
1461
|
+
const allBindings = [];
|
|
1462
|
+
for (const fnNames of [
|
|
1463
|
+
prerenderFnNames,
|
|
1464
|
+
staticFnNames,
|
|
1465
|
+
loaderFnNames,
|
|
1466
|
+
handleFnNames,
|
|
1467
|
+
lsFnNames
|
|
1468
|
+
]) {
|
|
1469
|
+
if (fnNames.length > 0) {
|
|
1470
|
+
allBindings.push(...getBindings(code, fnNames));
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
let canStubWholeFile = allBindings.length > 0 && isExportOnlyFile(code, allBindings);
|
|
1474
|
+
if (canStubWholeFile && (handleFnNames.length > 0 || lsFnNames.length > 0)) {
|
|
1475
|
+
const exportedLocals = new Set(allBindings.map((b) => b.localName));
|
|
1476
|
+
const strippedBindings = [];
|
|
1477
|
+
const localDeclPattern = /(?:^|;|\n)\s*(?:const|let|var|function)\s+(\w+)/g;
|
|
1478
|
+
let declMatch;
|
|
1479
|
+
while ((declMatch = localDeclPattern.exec(code)) !== null) {
|
|
1480
|
+
const name = declMatch[1];
|
|
1481
|
+
if (!exportedLocals.has(name) && !/^_c\d*$/.test(name)) {
|
|
1482
|
+
strippedBindings.push(name);
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
const importPattern = /import\s*\{([^}]*)\}\s*from\s*["'](?!@rangojs\/router)[^"']*["']/g;
|
|
1486
|
+
let importMatch;
|
|
1487
|
+
while ((importMatch = importPattern.exec(code)) !== null) {
|
|
1488
|
+
for (const spec of importMatch[1].split(",")) {
|
|
1489
|
+
const m = spec.trim().match(/^[A-Za-z_$][\w$]*(?:\s+as\s+([A-Za-z_$][\w$]*))?$/);
|
|
1490
|
+
if (m)
|
|
1491
|
+
strippedBindings.push(m[1] || m[0].trim().split(/\s/)[0]);
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
const defaultImportPattern = /import\s+([A-Za-z_$][\w$]*)\s+from\s*["'](?!@rangojs\/router)[^"']*["']/g;
|
|
1495
|
+
while ((importMatch = defaultImportPattern.exec(code)) !== null) {
|
|
1496
|
+
strippedBindings.push(importMatch[1]);
|
|
1497
|
+
}
|
|
1498
|
+
const nsImportPattern = /import\s+\*\s+as\s+([A-Za-z_$][\w$]*)\s+from\s*["'](?!@rangojs\/router)[^"']*["']/g;
|
|
1499
|
+
while ((importMatch = nsImportPattern.exec(code)) !== null) {
|
|
1500
|
+
strippedBindings.push(importMatch[1]);
|
|
1501
|
+
}
|
|
1502
|
+
if (strippedBindings.length > 0) {
|
|
1503
|
+
const preservedBindings = allBindings.filter((b) => {
|
|
1504
|
+
const fc = code.slice(b.callExprStart, b.callOpenParenPos + 1);
|
|
1505
|
+
return handleFnNames.some((n) => fc.includes(n)) || lsFnNames.some((n) => fc.includes(n));
|
|
1506
|
+
});
|
|
1507
|
+
const strippedRe = new RegExp(
|
|
1508
|
+
`\\b(?:${strippedBindings.join("|")})\\b`
|
|
1509
|
+
);
|
|
1510
|
+
canStubWholeFile = !preservedBindings.some((b) => {
|
|
1511
|
+
const expr = code.slice(
|
|
1512
|
+
b.callExprStart,
|
|
1513
|
+
b.callCloseParenPos + 1
|
|
1514
|
+
);
|
|
1515
|
+
return strippedRe.test(expr);
|
|
1516
|
+
});
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
if (canStubWholeFile) {
|
|
1520
|
+
const lines = [];
|
|
1521
|
+
const neededImports = [];
|
|
1522
|
+
if (handleFnNames.length > 0) neededImports.push("createHandle");
|
|
1523
|
+
if (lsFnNames.length > 0) neededImports.push("createLocationState");
|
|
1524
|
+
if (neededImports.length > 0) {
|
|
1525
|
+
lines.push(
|
|
1526
|
+
`import { ${neededImports.join(", ")} } from "@rangojs/router";`
|
|
1527
|
+
);
|
|
1528
|
+
}
|
|
1529
|
+
for (const binding of allBindings) {
|
|
1530
|
+
const fnCall = code.slice(
|
|
1531
|
+
binding.callExprStart,
|
|
1532
|
+
binding.callOpenParenPos + 1
|
|
1533
|
+
);
|
|
1534
|
+
const isHandle = handleFnNames.some((n) => fnCall.includes(n));
|
|
1535
|
+
const isLocationState = lsFnNames.some((n) => fnCall.includes(n));
|
|
1536
|
+
const primaryName = binding.exportNames[0];
|
|
1537
|
+
const stubId = makeStubId(filePath, primaryName, isBuild);
|
|
1538
|
+
if (isHandle || isLocationState) {
|
|
1539
|
+
const rawArgs = code.slice(
|
|
1540
|
+
binding.callOpenParenPos + 1,
|
|
1541
|
+
binding.callCloseParenPos
|
|
1542
|
+
).replace(/\b_c\d*\s*=\s*/g, "");
|
|
1543
|
+
const canonicalName = isHandle ? "createHandle" : "createLocationState";
|
|
1544
|
+
const activeFnNames = isHandle ? handleFnNames : lsFnNames;
|
|
1545
|
+
let rawCallee = code.slice(
|
|
1546
|
+
binding.callExprStart,
|
|
1547
|
+
binding.callOpenParenPos
|
|
1548
|
+
);
|
|
1549
|
+
for (const alias of activeFnNames) {
|
|
1550
|
+
if (alias !== canonicalName && rawCallee.startsWith(alias)) {
|
|
1551
|
+
rawCallee = canonicalName + rawCallee.slice(alias.length);
|
|
1552
|
+
break;
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
if (isHandle) {
|
|
1556
|
+
const idParam = binding.argCount === 0 ? `undefined, "${stubId}"` : `, "${stubId}"`;
|
|
1557
|
+
lines.push(
|
|
1558
|
+
`export const ${primaryName} = ${rawCallee}(${rawArgs}${idParam});`
|
|
1559
|
+
);
|
|
1560
|
+
lines.push(`${primaryName}.$$id = "${stubId}";`);
|
|
1561
|
+
} else {
|
|
1562
|
+
lines.push(
|
|
1563
|
+
`export const ${primaryName} = ${rawCallee}(${rawArgs});`
|
|
1564
|
+
);
|
|
1565
|
+
lines.push(
|
|
1566
|
+
`${primaryName}.__rsc_ls_key = "__rsc_ls_${stubId}";`
|
|
1567
|
+
);
|
|
1568
|
+
}
|
|
1569
|
+
for (const name of binding.exportNames.slice(1)) {
|
|
1570
|
+
lines.push(`export const ${name} = ${primaryName};`);
|
|
1571
|
+
}
|
|
1572
|
+
} else {
|
|
1573
|
+
let brand = "loader";
|
|
1574
|
+
if (prerenderFnNames.some((n) => fnCall.includes(n))) {
|
|
1575
|
+
brand = PRERENDER_CONFIG.brand;
|
|
1576
|
+
} else if (staticFnNames.some((n) => fnCall.includes(n))) {
|
|
1577
|
+
brand = STATIC_CONFIG.brand;
|
|
1578
|
+
}
|
|
1579
|
+
lines.push(
|
|
1580
|
+
`export const ${primaryName} = { __brand: "${brand}", $$id: "${stubId}" };`
|
|
1581
|
+
);
|
|
1582
|
+
for (const name of binding.exportNames.slice(1)) {
|
|
1583
|
+
lines.push(`export const ${name} = ${primaryName};`);
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
return { code: lines.join("\n") + "\n", map: null };
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
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
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
const s = new MagicString4(code);
|
|
1600
|
+
if (hasLoaderCode) {
|
|
1601
|
+
const fnNames = getFnNames("createLoader");
|
|
1602
|
+
changed = transformLoaders(
|
|
1603
|
+
getBindings(code, fnNames),
|
|
1354
1604
|
s,
|
|
1355
1605
|
filePath,
|
|
1356
1606
|
isBuild
|
|
1357
1607
|
) || changed;
|
|
1358
|
-
}
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1608
|
+
}
|
|
1609
|
+
if (hasHandleCode) {
|
|
1610
|
+
const fnNames = getFnNames("createHandle");
|
|
1611
|
+
changed = transformHandles(
|
|
1612
|
+
getBindings(code, fnNames),
|
|
1362
1613
|
s,
|
|
1614
|
+
code,
|
|
1363
1615
|
filePath,
|
|
1364
1616
|
isBuild
|
|
1365
1617
|
) || changed;
|
|
1366
1618
|
}
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
if (isRscEnv) {
|
|
1372
|
-
changed = transformHandlerIds(
|
|
1373
|
-
STATIC_CONFIG,
|
|
1374
|
-
bindings,
|
|
1619
|
+
if (hasLocationStateCode) {
|
|
1620
|
+
const fnNames = getFnNames("createLocationState");
|
|
1621
|
+
changed = transformLocationState(
|
|
1622
|
+
getBindings(code, fnNames),
|
|
1375
1623
|
s,
|
|
1376
1624
|
filePath,
|
|
1377
1625
|
isBuild
|
|
1378
1626
|
) || changed;
|
|
1379
|
-
} else {
|
|
1380
|
-
changed = stubHandlerExprs(STATIC_CONFIG, bindings, s, filePath, isBuild) || changed;
|
|
1381
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);
|
|
1382
1671
|
}
|
|
1383
|
-
if (!changed) return;
|
|
1384
|
-
return {
|
|
1385
|
-
code: s.toString(),
|
|
1386
|
-
map: s.generateMap({ source: id, includeContent: true })
|
|
1387
|
-
};
|
|
1388
1672
|
}
|
|
1389
1673
|
};
|
|
1390
1674
|
}
|
|
@@ -1392,12 +1676,14 @@ ${lazyImports.join(",\n")}
|
|
|
1392
1676
|
// src/vite/plugins/use-cache-transform.ts
|
|
1393
1677
|
import path5 from "node:path";
|
|
1394
1678
|
import MagicString5 from "magic-string";
|
|
1679
|
+
var debug4 = createRangoDebugger(NS.transform);
|
|
1395
1680
|
var CACHE_RUNTIME_IMPORT = "@rangojs/router/cache-runtime";
|
|
1396
1681
|
var LAYOUT_TEMPLATE_PATTERN = /\/(layout|template)\.(tsx?|jsx?)$/;
|
|
1397
1682
|
function useCacheTransform() {
|
|
1398
1683
|
let projectRoot = "";
|
|
1399
1684
|
let isBuild = false;
|
|
1400
1685
|
let rscTransforms = null;
|
|
1686
|
+
const counter = createCounter(debug4, "use-cache");
|
|
1401
1687
|
return {
|
|
1402
1688
|
name: "@rangojs/router:use-cache",
|
|
1403
1689
|
enforce: "post",
|
|
@@ -1405,53 +1691,61 @@ function useCacheTransform() {
|
|
|
1405
1691
|
projectRoot = config.root;
|
|
1406
1692
|
isBuild = config.command === "build";
|
|
1407
1693
|
},
|
|
1694
|
+
buildEnd() {
|
|
1695
|
+
counter?.flush();
|
|
1696
|
+
},
|
|
1408
1697
|
async transform(code, id) {
|
|
1409
1698
|
if (this.environment?.name !== "rsc") return;
|
|
1410
1699
|
if (!code.includes("use cache")) return;
|
|
1411
1700
|
if (id.includes("/node_modules/") || id.startsWith("\0")) return;
|
|
1412
1701
|
if (!/\.(tsx?|jsx?|mjs)$/.test(id)) return;
|
|
1413
|
-
|
|
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;
|
|
1414
1717
|
try {
|
|
1415
|
-
|
|
1718
|
+
const { parseAst: parseAst4 } = await import("vite");
|
|
1719
|
+
ast = parseAst4(code);
|
|
1416
1720
|
} catch {
|
|
1417
1721
|
return;
|
|
1418
1722
|
}
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
hasDirective,
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
const isLayoutOrTemplate = LAYOUT_TEMPLATE_PATTERN.test(id);
|
|
1434
|
-
if (hasDirective(ast.body, "use cache")) {
|
|
1435
|
-
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(
|
|
1436
1737
|
code,
|
|
1437
1738
|
ast,
|
|
1438
1739
|
filePath,
|
|
1439
1740
|
id,
|
|
1440
1741
|
isBuild,
|
|
1441
|
-
|
|
1442
|
-
transformWrapExport
|
|
1742
|
+
transformHoistInlineDirective
|
|
1443
1743
|
);
|
|
1744
|
+
warnOnNearMissDirectives(ast, id, this.warn.bind(this));
|
|
1745
|
+
if (functionResult) return functionResult;
|
|
1746
|
+
} finally {
|
|
1747
|
+
counter?.record(id, performance.now() - start);
|
|
1444
1748
|
}
|
|
1445
|
-
const functionResult = transformFunctionLevelUseCache(
|
|
1446
|
-
code,
|
|
1447
|
-
ast,
|
|
1448
|
-
filePath,
|
|
1449
|
-
id,
|
|
1450
|
-
isBuild,
|
|
1451
|
-
transformHoistInlineDirective
|
|
1452
|
-
);
|
|
1453
|
-
warnOnNearMissDirectives(ast, id, this.warn.bind(this));
|
|
1454
|
-
if (functionResult) return functionResult;
|
|
1455
1749
|
}
|
|
1456
1750
|
};
|
|
1457
1751
|
}
|
|
@@ -1574,6 +1868,7 @@ function warnOnNearMissDirectives(ast, fileId, warn) {
|
|
|
1574
1868
|
}
|
|
1575
1869
|
|
|
1576
1870
|
// src/vite/plugins/client-ref-dedup.ts
|
|
1871
|
+
var debug5 = createRangoDebugger(NS.transform);
|
|
1577
1872
|
var CLIENT_IN_SERVER_PROXY_PREFIX = "virtual:vite-rsc/client-in-server-package-proxy/";
|
|
1578
1873
|
function extractPackageName(absolutePath) {
|
|
1579
1874
|
const marker = "/node_modules/";
|
|
@@ -1590,6 +1885,7 @@ function extractPackageName(absolutePath) {
|
|
|
1590
1885
|
}
|
|
1591
1886
|
function clientRefDedup() {
|
|
1592
1887
|
let clientExclude = [];
|
|
1888
|
+
const dedupedPackages = /* @__PURE__ */ new Set();
|
|
1593
1889
|
return {
|
|
1594
1890
|
name: "@rangojs/router:client-ref-dedup",
|
|
1595
1891
|
enforce: "pre",
|
|
@@ -1598,6 +1894,15 @@ function clientRefDedup() {
|
|
|
1598
1894
|
const clientEnv = config.environments?.["client"];
|
|
1599
1895
|
clientExclude = clientEnv?.optimizeDeps?.exclude ?? config.optimizeDeps?.exclude ?? [];
|
|
1600
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
|
+
},
|
|
1601
1906
|
resolveId(source, importer, options) {
|
|
1602
1907
|
if (this.environment?.name !== "client") return;
|
|
1603
1908
|
if (!importer?.includes(CLIENT_IN_SERVER_PROXY_PREFIX)) return;
|
|
@@ -1606,6 +1911,7 @@ function clientRefDedup() {
|
|
|
1606
1911
|
const packageName = extractPackageName(source);
|
|
1607
1912
|
if (!packageName) return;
|
|
1608
1913
|
if (clientExclude.includes(packageName)) return;
|
|
1914
|
+
if (debug5) dedupedPackages.add(packageName);
|
|
1609
1915
|
return `\0rango:dedup/${packageName}`;
|
|
1610
1916
|
},
|
|
1611
1917
|
load(id) {
|
|
@@ -1728,12 +2034,13 @@ function getVirtualVersionContent(version) {
|
|
|
1728
2034
|
|
|
1729
2035
|
// src/vite/utils/package-resolution.ts
|
|
1730
2036
|
import { existsSync } from "node:fs";
|
|
2037
|
+
import { createRequire } from "node:module";
|
|
1731
2038
|
import { resolve } from "node:path";
|
|
1732
2039
|
|
|
1733
2040
|
// package.json
|
|
1734
2041
|
var package_default = {
|
|
1735
2042
|
name: "@rangojs/router",
|
|
1736
|
-
version: "0.0.0-experimental.
|
|
2043
|
+
version: "0.0.0-experimental.66cdebe3",
|
|
1737
2044
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
1738
2045
|
keywords: [
|
|
1739
2046
|
"react",
|
|
@@ -1866,16 +2173,18 @@ var package_default = {
|
|
|
1866
2173
|
tag: "experimental"
|
|
1867
2174
|
},
|
|
1868
2175
|
scripts: {
|
|
1869
|
-
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",
|
|
1870
2177
|
prepublishOnly: "pnpm build",
|
|
1871
|
-
typecheck: "tsc --noEmit",
|
|
2178
|
+
typecheck: "tsc --noEmit && tsc -p tsconfig.strict-check.json --noEmit",
|
|
1872
2179
|
test: "playwright test",
|
|
1873
2180
|
"test:ui": "playwright test --ui",
|
|
1874
2181
|
"test:unit": "vitest run",
|
|
1875
2182
|
"test:unit:watch": "vitest"
|
|
1876
2183
|
},
|
|
1877
2184
|
dependencies: {
|
|
1878
|
-
"@
|
|
2185
|
+
"@types/debug": "^4.1.12",
|
|
2186
|
+
"@vitejs/plugin-rsc": "^0.5.23",
|
|
2187
|
+
debug: "^4.4.1",
|
|
1879
2188
|
"magic-string": "^0.30.17",
|
|
1880
2189
|
picomatch: "^4.0.3",
|
|
1881
2190
|
"rsc-html-stream": "^0.0.7"
|
|
@@ -1895,7 +2204,7 @@ var package_default = {
|
|
|
1895
2204
|
},
|
|
1896
2205
|
peerDependencies: {
|
|
1897
2206
|
"@cloudflare/vite-plugin": "^1.25.0",
|
|
1898
|
-
"@vitejs/plugin-rsc": "^0.5.
|
|
2207
|
+
"@vitejs/plugin-rsc": "^0.5.23",
|
|
1899
2208
|
react: "^18.0.0 || ^19.0.0",
|
|
1900
2209
|
vite: "^7.3.0"
|
|
1901
2210
|
},
|
|
@@ -1910,6 +2219,7 @@ var package_default = {
|
|
|
1910
2219
|
};
|
|
1911
2220
|
|
|
1912
2221
|
// src/vite/utils/package-resolution.ts
|
|
2222
|
+
var require2 = createRequire(import.meta.url);
|
|
1913
2223
|
var VIRTUAL_PACKAGE_NAME = "@rangojs/router";
|
|
1914
2224
|
function getPublishedPackageName() {
|
|
1915
2225
|
return package_default.name;
|
|
@@ -1950,6 +2260,20 @@ function getPackageAliases() {
|
|
|
1950
2260
|
}
|
|
1951
2261
|
return aliases;
|
|
1952
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
|
+
}
|
|
1953
2277
|
|
|
1954
2278
|
// src/build/route-types/param-extraction.ts
|
|
1955
2279
|
function extractParamsFromPattern(pattern) {
|
|
@@ -2847,6 +3171,7 @@ import * as Vite from "vite";
|
|
|
2847
3171
|
|
|
2848
3172
|
// src/vite/plugins/performance-tracks.ts
|
|
2849
3173
|
import { readFile } from "node:fs/promises";
|
|
3174
|
+
var debug6 = createRangoDebugger(NS.transform);
|
|
2850
3175
|
var RSDW_PATCH_RE = /((?:var|let|const)\s+\w+\s*=\s*root\._children\s*,\s*(\w+)\s*=\s*root\._debugInfo\s*[;,])/;
|
|
2851
3176
|
function buildPatchReplacement(match, debugInfoVar) {
|
|
2852
3177
|
return `${match}
|
|
@@ -2888,19 +3213,23 @@ function performanceTracksOptimizeDepsPlugin() {
|
|
|
2888
3213
|
};
|
|
2889
3214
|
}
|
|
2890
3215
|
function performanceTracksPlugin() {
|
|
3216
|
+
const counter = createCounter(debug6, "performance-tracks");
|
|
2891
3217
|
return {
|
|
2892
3218
|
name: "@rangojs/router:performance-tracks",
|
|
3219
|
+
buildEnd() {
|
|
3220
|
+
counter?.flush();
|
|
3221
|
+
},
|
|
2893
3222
|
transform(code, id) {
|
|
2894
3223
|
if (!id.includes("react-server-dom") || !id.includes("client")) return;
|
|
2895
|
-
const
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
);
|
|
2903
|
-
|
|
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
|
+
}
|
|
2904
3233
|
}
|
|
2905
3234
|
};
|
|
2906
3235
|
}
|
|
@@ -3047,11 +3376,10 @@ function createVersionInjectorPlugin(rscEntryPath) {
|
|
|
3047
3376
|
if (normalizedId !== normalizedEntry) {
|
|
3048
3377
|
return null;
|
|
3049
3378
|
}
|
|
3050
|
-
const prepend = [
|
|
3379
|
+
const prepend = [
|
|
3380
|
+
`import "virtual:rsc-router/routes-manifest";`
|
|
3381
|
+
];
|
|
3051
3382
|
let newCode = code;
|
|
3052
|
-
if (!code.includes("virtual:rsc-router/routes-manifest")) {
|
|
3053
|
-
prepend.push(`import "virtual:rsc-router/routes-manifest";`);
|
|
3054
|
-
}
|
|
3055
3383
|
const needsVersion = code.includes("createRSCHandler") && !code.includes("@rangojs/router:version") && /createRSCHandler\s*\(\s*\{/.test(code);
|
|
3056
3384
|
if (needsVersion) {
|
|
3057
3385
|
prepend.push(`import { VERSION } from "@rangojs/router:version";`);
|
|
@@ -3060,8 +3388,21 @@ function createVersionInjectorPlugin(rscEntryPath) {
|
|
|
3060
3388
|
"createRSCHandler({\n version: VERSION,"
|
|
3061
3389
|
);
|
|
3062
3390
|
}
|
|
3063
|
-
|
|
3064
|
-
|
|
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");
|
|
3065
3406
|
return {
|
|
3066
3407
|
code: newCode,
|
|
3067
3408
|
map: null
|
|
@@ -3071,6 +3412,7 @@ function createVersionInjectorPlugin(rscEntryPath) {
|
|
|
3071
3412
|
}
|
|
3072
3413
|
|
|
3073
3414
|
// src/vite/plugins/cjs-to-esm.ts
|
|
3415
|
+
var debug7 = createRangoDebugger(NS.transform);
|
|
3074
3416
|
function createCjsToEsmPlugin() {
|
|
3075
3417
|
return {
|
|
3076
3418
|
name: "@rangojs/router:cjs-to-esm",
|
|
@@ -3080,6 +3422,7 @@ function createCjsToEsmPlugin() {
|
|
|
3080
3422
|
if (cleanId.includes("vendor/react-server-dom/client.browser.js") || cleanId.includes("vendor\\react-server-dom\\client.browser.js")) {
|
|
3081
3423
|
const isProd = process.env.NODE_ENV === "production";
|
|
3082
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);
|
|
3083
3426
|
return {
|
|
3084
3427
|
code: `export * from "${cjsFile}";`,
|
|
3085
3428
|
map: null
|
|
@@ -3115,6 +3458,7 @@ function createCjsToEsmPlugin() {
|
|
|
3115
3458
|
"export const $1 ="
|
|
3116
3459
|
);
|
|
3117
3460
|
transformed = license + "\n" + transformed;
|
|
3461
|
+
debug7?.("cjs-to-esm body rewrite %s", id);
|
|
3118
3462
|
return {
|
|
3119
3463
|
code: transformed,
|
|
3120
3464
|
map: null
|
|
@@ -3129,7 +3473,7 @@ function createCjsToEsmPlugin() {
|
|
|
3129
3473
|
import { createServer as createViteServer } from "vite";
|
|
3130
3474
|
import { resolve as resolve8 } from "node:path";
|
|
3131
3475
|
import { readFileSync as readFileSync6 } from "node:fs";
|
|
3132
|
-
import { createRequire } from "node:module";
|
|
3476
|
+
import { createRequire as createRequire2, register } from "node:module";
|
|
3133
3477
|
import { pathToFileURL } from "node:url";
|
|
3134
3478
|
|
|
3135
3479
|
// src/vite/plugins/virtual-stub-plugin.ts
|
|
@@ -3156,9 +3500,117 @@ function createVirtualStubPlugin() {
|
|
|
3156
3500
|
};
|
|
3157
3501
|
}
|
|
3158
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
|
+
|
|
3159
3610
|
// src/vite/plugins/client-ref-hashing.ts
|
|
3160
3611
|
import { relative } from "node:path";
|
|
3161
3612
|
import { createHash as createHash2 } from "node:crypto";
|
|
3613
|
+
var debug8 = createRangoDebugger(NS.transform);
|
|
3162
3614
|
var CLIENT_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-package-proxy/";
|
|
3163
3615
|
var CLIENT_IN_SERVER_PKG_PROXY_PREFIX = "/@id/__x00__virtual:vite-rsc/client-in-server-package-proxy/";
|
|
3164
3616
|
var FS_PREFIX = "/@fs/";
|
|
@@ -3197,6 +3649,7 @@ function transformClientRefs(code, projectRoot) {
|
|
|
3197
3649
|
return hasReplacement ? result : null;
|
|
3198
3650
|
}
|
|
3199
3651
|
function hashClientRefs(projectRoot) {
|
|
3652
|
+
const counter = createCounter(debug8, "hash-client-refs");
|
|
3200
3653
|
return {
|
|
3201
3654
|
name: "@rangojs/router:hash-client-refs",
|
|
3202
3655
|
// Run after the RSC plugin's transform (default enforce is normal)
|
|
@@ -3204,10 +3657,18 @@ function hashClientRefs(projectRoot) {
|
|
|
3204
3657
|
applyToEnvironment(env) {
|
|
3205
3658
|
return env.name === "rsc";
|
|
3206
3659
|
},
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
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
|
+
}
|
|
3211
3672
|
}
|
|
3212
3673
|
};
|
|
3213
3674
|
}
|
|
@@ -3335,6 +3796,12 @@ function markSelfGenWrite(state, filePath, content) {
|
|
|
3335
3796
|
state.selfWrittenGenFiles.set(filePath, { at: Date.now(), hash });
|
|
3336
3797
|
}
|
|
3337
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) {
|
|
3338
3805
|
const info = state.selfWrittenGenFiles.get(filePath);
|
|
3339
3806
|
if (!info) return false;
|
|
3340
3807
|
if (Date.now() - info.at > state.SELF_WRITE_WINDOW_MS) {
|
|
@@ -3345,7 +3812,7 @@ function consumeSelfGenWrite(state, filePath) {
|
|
|
3345
3812
|
const current = readFileSync3(filePath, "utf-8");
|
|
3346
3813
|
const currentHash = createHash3("sha256").update(current).digest("hex");
|
|
3347
3814
|
if (currentHash === info.hash) {
|
|
3348
|
-
state.selfWrittenGenFiles.delete(filePath);
|
|
3815
|
+
if (consume) state.selfWrittenGenFiles.delete(filePath);
|
|
3349
3816
|
return true;
|
|
3350
3817
|
}
|
|
3351
3818
|
return false;
|
|
@@ -3449,11 +3916,19 @@ function substituteRouteParams(pattern, params, encode = encodeURIComponent) {
|
|
|
3449
3916
|
let hadOmittedOptional = false;
|
|
3450
3917
|
for (const [key, value] of Object.entries(params)) {
|
|
3451
3918
|
const escaped = escapeRegExp2(key);
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
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
|
+
}
|
|
3457
3932
|
}
|
|
3458
3933
|
result = result.replace(/:([a-zA-Z_][a-zA-Z0-9_]*)(\([^)]*\))?\?/g, () => {
|
|
3459
3934
|
hadOmittedOptional = true;
|
|
@@ -3559,8 +4034,14 @@ function copyStagedBuildAssets(projectRoot, fileNames) {
|
|
|
3559
4034
|
}
|
|
3560
4035
|
|
|
3561
4036
|
// src/vite/discovery/prerender-collection.ts
|
|
4037
|
+
var debug9 = createRangoDebugger(NS.prerender);
|
|
3562
4038
|
async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
3563
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
|
+
);
|
|
3564
4045
|
const entries = [];
|
|
3565
4046
|
const allRoutes = {};
|
|
3566
4047
|
for (const { manifest: m } of allManifests) {
|
|
@@ -3572,100 +4053,151 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3572
4053
|
if (!params) return pattern;
|
|
3573
4054
|
return substituteRouteParams(pattern, params);
|
|
3574
4055
|
};
|
|
4056
|
+
let resolvedRoutes = 0;
|
|
4057
|
+
let totalDynamic = 0;
|
|
3575
4058
|
for (const { manifest } of allManifests) {
|
|
3576
4059
|
if (!manifest.prerenderRoutes) continue;
|
|
3577
|
-
const defs = manifest._prerenderDefs || {};
|
|
3578
|
-
const passthroughSet = new Set(manifest.passthroughRoutes || []);
|
|
3579
4060
|
for (const routeName of manifest.prerenderRoutes) {
|
|
3580
4061
|
const pattern = manifest.routeManifest[routeName];
|
|
3581
|
-
if (
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
const
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
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
|
+
);
|
|
3624
4110
|
}
|
|
3625
|
-
}
|
|
3626
|
-
|
|
3627
|
-
|
|
4111
|
+
};
|
|
4112
|
+
const paramsList = await def.getParams(getParamsCtx);
|
|
4113
|
+
debug9?.(
|
|
4114
|
+
"getParams %s -> %d params (%sms)",
|
|
3628
4115
|
routeName,
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
isPassthroughRoute
|
|
3632
|
-
});
|
|
3633
|
-
}
|
|
3634
|
-
} catch (err) {
|
|
3635
|
-
if (err.name === "Skip") {
|
|
3636
|
-
console.log(
|
|
3637
|
-
`[rsc-router] SKIP route "${routeName}" - ${err.message}`
|
|
4116
|
+
paramsList.length,
|
|
4117
|
+
(performance.now() - getParamsStart).toFixed(1)
|
|
3638
4118
|
);
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
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}`
|
|
3646
4163
|
);
|
|
3647
|
-
|
|
4164
|
+
notifyOnError(registry, err, "prerender", routeName);
|
|
4165
|
+
throw err;
|
|
3648
4166
|
}
|
|
3649
|
-
|
|
3650
|
-
|
|
4167
|
+
} else {
|
|
4168
|
+
console.warn(
|
|
4169
|
+
`[rsc-router] Dynamic prerender route "${routeName}" has no getParams(), skipping`
|
|
3651
4170
|
);
|
|
3652
|
-
notifyOnError(registry, err, "prerender", routeName);
|
|
3653
|
-
throw err;
|
|
3654
4171
|
}
|
|
3655
|
-
} else {
|
|
3656
|
-
console.warn(
|
|
3657
|
-
`[rsc-router] Dynamic prerender route "${routeName}" has no getParams(), skipping`
|
|
3658
|
-
);
|
|
3659
4172
|
}
|
|
3660
4173
|
}
|
|
3661
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;
|
|
3662
4190
|
}
|
|
3663
|
-
if (entries.length === 0) return;
|
|
3664
4191
|
const maxConcurrency = Math.max(...entries.map((e) => e.concurrency));
|
|
3665
4192
|
const concurrencyNote = maxConcurrency > 1 ? ` (concurrency: ${maxConcurrency})` : "";
|
|
3666
4193
|
console.log(
|
|
3667
4194
|
`[rsc-router] Pre-rendering ${entries.length} URL(s)${concurrencyNote}...`
|
|
3668
4195
|
);
|
|
4196
|
+
debug9?.(
|
|
4197
|
+
"prerender loop: %d entries, max concurrency %d",
|
|
4198
|
+
entries.length,
|
|
4199
|
+
maxConcurrency
|
|
4200
|
+
);
|
|
3669
4201
|
const { hashParams } = await rscEnv.runner.import("@rangojs/router/build");
|
|
3670
4202
|
const manifestEntries = {};
|
|
3671
4203
|
let doneCount = 0;
|
|
@@ -3772,10 +4304,22 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3772
4304
|
console.log(
|
|
3773
4305
|
`[rsc-router] Pre-render complete: ${parts.join(", ")} (${totalElapsed}ms total)`
|
|
3774
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
|
+
);
|
|
3775
4314
|
}
|
|
3776
4315
|
async function renderStaticHandlers(state, rscEnv, registry) {
|
|
3777
4316
|
if (!state.opts?.enableBuildPrerender || !state.isBuildMode || !state.resolvedStaticModules?.size)
|
|
3778
4317
|
return;
|
|
4318
|
+
const overallStart = debug9 ? performance.now() : 0;
|
|
4319
|
+
debug9?.(
|
|
4320
|
+
"renderStaticHandlers: start (%d static module(s))",
|
|
4321
|
+
state.resolvedStaticModules.size
|
|
4322
|
+
);
|
|
3779
4323
|
const manifestEntries = {};
|
|
3780
4324
|
let staticDone = 0;
|
|
3781
4325
|
let staticSkip = 0;
|
|
@@ -3865,13 +4409,29 @@ async function renderStaticHandlers(state, rscEnv, registry) {
|
|
|
3865
4409
|
console.log(
|
|
3866
4410
|
`[rsc-router] Static render complete: ${staticParts.join(", ")} (${totalStaticElapsed}ms total)`
|
|
3867
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
|
+
);
|
|
3868
4419
|
}
|
|
3869
4420
|
|
|
3870
4421
|
// src/vite/discovery/discover-routers.ts
|
|
4422
|
+
var debug10 = createRangoDebugger(NS.discovery);
|
|
3871
4423
|
async function discoverRouters(state, rscEnv) {
|
|
3872
4424
|
if (!state.resolvedEntryPath) return;
|
|
3873
|
-
await
|
|
3874
|
-
|
|
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
|
+
);
|
|
3875
4435
|
let registry = serverMod.RouterRegistry;
|
|
3876
4436
|
if (!registry || registry.size === 0) {
|
|
3877
4437
|
try {
|
|
@@ -3913,8 +4473,13 @@ async function discoverRouters(state, rscEnv) {
|
|
|
3913
4473
|
);
|
|
3914
4474
|
}
|
|
3915
4475
|
}
|
|
3916
|
-
const buildMod = await
|
|
4476
|
+
const buildMod = await timed(
|
|
4477
|
+
debug10,
|
|
4478
|
+
"inner: import @rangojs/router/build",
|
|
4479
|
+
() => rscEnv.runner.import("@rangojs/router/build")
|
|
4480
|
+
);
|
|
3917
4481
|
const generateManifestFull = buildMod.generateManifestFull;
|
|
4482
|
+
debug10?.("inner: found %d router(s) in registry", registry.size);
|
|
3918
4483
|
const nestedRouterConflict = findNestedRouterConflict(
|
|
3919
4484
|
[...registry.values()].map((router) => router.__sourceFile).filter(
|
|
3920
4485
|
(sourceFile) => typeof sourceFile === "string"
|
|
@@ -3933,6 +4498,7 @@ async function discoverRouters(state, rscEnv) {
|
|
|
3933
4498
|
let mergedRouteTrailingSlash = {};
|
|
3934
4499
|
let routerMountIndex = 0;
|
|
3935
4500
|
const allManifests = [];
|
|
4501
|
+
const manifestGenStart = debug10 ? performance.now() : 0;
|
|
3936
4502
|
for (const [id, router] of registry) {
|
|
3937
4503
|
if (!router.urlpatterns || !generateManifestFull) {
|
|
3938
4504
|
continue;
|
|
@@ -4007,7 +4573,13 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4007
4573
|
);
|
|
4008
4574
|
}
|
|
4009
4575
|
}
|
|
4576
|
+
debug10?.(
|
|
4577
|
+
"inner: generated manifests for %d router(s) (%sms)",
|
|
4578
|
+
allManifests.length,
|
|
4579
|
+
(performance.now() - manifestGenStart).toFixed(1)
|
|
4580
|
+
);
|
|
4010
4581
|
let newMergedRouteTrie = null;
|
|
4582
|
+
const trieStart = debug10 ? performance.now() : 0;
|
|
4011
4583
|
if (Object.keys(newMergedRouteManifest).length > 0) {
|
|
4012
4584
|
const buildRouteTrie = buildMod.buildRouteTrie;
|
|
4013
4585
|
if (buildRouteTrie && mergedRouteAncestry) {
|
|
@@ -4070,6 +4642,10 @@ async function discoverRouters(state, rscEnv) {
|
|
|
4070
4642
|
}
|
|
4071
4643
|
}
|
|
4072
4644
|
}
|
|
4645
|
+
debug10?.(
|
|
4646
|
+
"inner: trie build done (%sms)",
|
|
4647
|
+
(performance.now() - trieStart).toFixed(1)
|
|
4648
|
+
);
|
|
4073
4649
|
state.mergedRouteManifest = newMergedRouteManifest;
|
|
4074
4650
|
state.mergedPrecomputedEntries = newMergedPrecomputedEntries;
|
|
4075
4651
|
state.perRouterManifests = newPerRouterManifests;
|
|
@@ -4509,8 +5085,101 @@ function postprocessBundle(state) {
|
|
|
4509
5085
|
}
|
|
4510
5086
|
}
|
|
4511
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
|
+
|
|
4512
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
|
+
}
|
|
4513
5181
|
async function createTempRscServer(state, options = {}) {
|
|
5182
|
+
ensureCloudflareProtocolLoaderRegistered();
|
|
4514
5183
|
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
4515
5184
|
return createViteServer({
|
|
4516
5185
|
root: state.projectRoot,
|
|
@@ -4533,6 +5202,7 @@ async function createTempRscServer(state, options = {}) {
|
|
|
4533
5202
|
...options.forceBuild ? [hashClientRefs(state.projectRoot)] : [],
|
|
4534
5203
|
createVersionPlugin(),
|
|
4535
5204
|
createVirtualStubPlugin(),
|
|
5205
|
+
createCloudflareProtocolStubPlugin(),
|
|
4536
5206
|
// Dev prerender must use dev-mode IDs (path-based) to match the workerd
|
|
4537
5207
|
// runtime. forceBuild produces hashed IDs for production bundle consistency.
|
|
4538
5208
|
exposeInternalIds(options.forceBuild ? { forceBuild: true } : void 0),
|
|
@@ -4549,7 +5219,7 @@ async function resolveBuildEnv(option, factoryCtx) {
|
|
|
4549
5219
|
);
|
|
4550
5220
|
}
|
|
4551
5221
|
try {
|
|
4552
|
-
const userRequire =
|
|
5222
|
+
const userRequire = createRequire2(
|
|
4553
5223
|
resolve8(factoryCtx.root, "package.json")
|
|
4554
5224
|
);
|
|
4555
5225
|
const wranglerPath = userRequire.resolve("wrangler");
|
|
@@ -4584,6 +5254,7 @@ async function acquireBuildEnv(s, command, mode) {
|
|
|
4584
5254
|
if (!result) return false;
|
|
4585
5255
|
s.resolvedBuildEnv = result.env;
|
|
4586
5256
|
s.buildEnvDispose = result.dispose ?? null;
|
|
5257
|
+
globalThis[BUILD_ENV_GLOBAL_KEY] = result.env;
|
|
4587
5258
|
return true;
|
|
4588
5259
|
}
|
|
4589
5260
|
async function releaseBuildEnv(s) {
|
|
@@ -4596,6 +5267,7 @@ async function releaseBuildEnv(s) {
|
|
|
4596
5267
|
s.buildEnvDispose = null;
|
|
4597
5268
|
}
|
|
4598
5269
|
s.resolvedBuildEnv = void 0;
|
|
5270
|
+
delete globalThis[BUILD_ENV_GLOBAL_KEY];
|
|
4599
5271
|
}
|
|
4600
5272
|
function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
4601
5273
|
const s = createDiscoveryState(entryPath, opts);
|
|
@@ -4651,6 +5323,9 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4651
5323
|
const discoveryPromise = new Promise((resolve10) => {
|
|
4652
5324
|
resolveDiscovery = resolve10;
|
|
4653
5325
|
});
|
|
5326
|
+
const gate = createDiscoveryGate(s, debugDiscovery);
|
|
5327
|
+
const beginDiscoveryGate = gate.beginGate;
|
|
5328
|
+
const resolveDiscoveryGate = gate.resolveGate;
|
|
4654
5329
|
const getDevServerOrigin = () => server.resolvedUrls?.local?.[0]?.replace(/\/$/, "") || `http://localhost:${server.config.server.port || 5173}`;
|
|
4655
5330
|
let prerenderTempServer = null;
|
|
4656
5331
|
let prerenderNodeRegistry = null;
|
|
@@ -4663,40 +5338,180 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4663
5338
|
releaseBuildEnv(s).catch(() => {
|
|
4664
5339
|
});
|
|
4665
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
|
+
}
|
|
4666
5372
|
async function getOrCreateTempServer() {
|
|
4667
|
-
if (
|
|
4668
|
-
|
|
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
|
+
}
|
|
4669
5407
|
}
|
|
5408
|
+
debugDiscovery?.(
|
|
5409
|
+
"getOrCreateTempServer: creating new temp server, entry=%s",
|
|
5410
|
+
s.resolvedEntryPath ?? "(unset)"
|
|
5411
|
+
);
|
|
4670
5412
|
try {
|
|
4671
5413
|
prerenderTempServer = await createTempRscServer(s, {
|
|
4672
5414
|
cacheDir: "node_modules/.vite_prerender"
|
|
4673
5415
|
});
|
|
4674
5416
|
const tempRscEnv = prerenderTempServer.environments?.rsc;
|
|
4675
5417
|
if (tempRscEnv?.runner) {
|
|
4676
|
-
await tempRscEnv
|
|
4677
|
-
const serverMod = await tempRscEnv.runner.import(
|
|
4678
|
-
"@rangojs/router/server"
|
|
4679
|
-
);
|
|
4680
|
-
prerenderNodeRegistry = serverMod.RouterRegistry;
|
|
5418
|
+
await importEntryAndRegistry(tempRscEnv);
|
|
4681
5419
|
return tempRscEnv;
|
|
4682
5420
|
}
|
|
5421
|
+
debugDiscovery?.(
|
|
5422
|
+
"getOrCreateTempServer: tempRscEnv.runner unavailable"
|
|
5423
|
+
);
|
|
4683
5424
|
} catch (err) {
|
|
5425
|
+
debugDiscovery?.(
|
|
5426
|
+
"getOrCreateTempServer: FAILED message=%s",
|
|
5427
|
+
err.message
|
|
5428
|
+
);
|
|
4684
5429
|
console.warn(
|
|
4685
5430
|
`[rsc-router] Failed to create temp runner: ${err.message}`
|
|
4686
5431
|
);
|
|
4687
5432
|
}
|
|
4688
5433
|
return null;
|
|
4689
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
|
+
}
|
|
4690
5484
|
const discover = async () => {
|
|
5485
|
+
const discoverStart = performance.now();
|
|
4691
5486
|
const rscEnv = server.environments?.rsc;
|
|
4692
5487
|
if (!rscEnv?.runner) {
|
|
5488
|
+
debugDiscovery?.(
|
|
5489
|
+
"dev: cloudflare path start, __rscRouterDiscoveryActive=%s",
|
|
5490
|
+
globalThis.__rscRouterDiscoveryActive ?? false
|
|
5491
|
+
);
|
|
4693
5492
|
s.devServerOrigin = getDevServerOrigin();
|
|
4694
5493
|
try {
|
|
4695
|
-
await
|
|
4696
|
-
|
|
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
|
+
);
|
|
4697
5504
|
if (tempRscEnv) {
|
|
4698
|
-
await
|
|
4699
|
-
|
|
5505
|
+
await timed(
|
|
5506
|
+
debugDiscovery,
|
|
5507
|
+
"discoverRouters (cloudflare)",
|
|
5508
|
+
() => discoverRouters(s, tempRscEnv)
|
|
5509
|
+
);
|
|
5510
|
+
timedSync(
|
|
5511
|
+
debugDiscovery,
|
|
5512
|
+
"writeRouteTypesFiles",
|
|
5513
|
+
() => writeRouteTypesFiles(s)
|
|
5514
|
+
);
|
|
4700
5515
|
}
|
|
4701
5516
|
} catch (err) {
|
|
4702
5517
|
console.warn(
|
|
@@ -4704,33 +5519,62 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4704
5519
|
${err.stack}`
|
|
4705
5520
|
);
|
|
4706
5521
|
}
|
|
5522
|
+
debugDiscovery?.(
|
|
5523
|
+
"dev discovery done (%sms)",
|
|
5524
|
+
(performance.now() - discoverStart).toFixed(1)
|
|
5525
|
+
);
|
|
4707
5526
|
resolveDiscovery();
|
|
4708
5527
|
return;
|
|
4709
5528
|
}
|
|
4710
5529
|
try {
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
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")
|
|
4714
5540
|
);
|
|
4715
5541
|
if (serverMod?.setManifestReadyPromise) {
|
|
4716
5542
|
serverMod.setManifestReadyPromise(discoveryPromise);
|
|
4717
5543
|
}
|
|
4718
|
-
await
|
|
5544
|
+
await timed(
|
|
5545
|
+
debugDiscovery,
|
|
5546
|
+
"discoverRouters",
|
|
5547
|
+
() => discoverRouters(s, rscEnv)
|
|
5548
|
+
);
|
|
4719
5549
|
s.devServerOrigin = getDevServerOrigin();
|
|
4720
|
-
|
|
4721
|
-
|
|
5550
|
+
timedSync(
|
|
5551
|
+
debugDiscovery,
|
|
5552
|
+
"writeRouteTypesFiles",
|
|
5553
|
+
() => writeRouteTypesFiles(s)
|
|
5554
|
+
);
|
|
5555
|
+
await timed(
|
|
5556
|
+
debugDiscovery,
|
|
5557
|
+
"propagateDiscoveryState",
|
|
5558
|
+
() => propagateDiscoveryState(rscEnv)
|
|
5559
|
+
);
|
|
4722
5560
|
} catch (err) {
|
|
4723
5561
|
console.warn(
|
|
4724
5562
|
`[rsc-router] Router discovery failed: ${err.message}
|
|
4725
5563
|
${err.stack}`
|
|
4726
5564
|
);
|
|
4727
5565
|
} finally {
|
|
5566
|
+
debugDiscovery?.(
|
|
5567
|
+
"dev discovery done (%sms)",
|
|
5568
|
+
(performance.now() - discoverStart).toFixed(1)
|
|
5569
|
+
);
|
|
4728
5570
|
resolveDiscovery();
|
|
4729
5571
|
}
|
|
4730
5572
|
};
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
5573
|
+
beginDiscoveryGate();
|
|
5574
|
+
setTimeout(
|
|
5575
|
+
() => discover().then(resolveDiscoveryGate, resolveDiscoveryGate),
|
|
5576
|
+
0
|
|
5577
|
+
);
|
|
4734
5578
|
let mainRegistry = null;
|
|
4735
5579
|
const propagateDiscoveryState = async (rscEnv) => {
|
|
4736
5580
|
const serverMod = await rscEnv.runner.import("@rangojs/router/server");
|
|
@@ -4765,12 +5609,23 @@ ${err.stack}`
|
|
|
4765
5609
|
}
|
|
4766
5610
|
};
|
|
4767
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
|
+
};
|
|
4768
5622
|
if (s.discoveryDone) await s.discoveryDone;
|
|
4769
5623
|
const url = new URL(req.url || "/", "http://localhost");
|
|
4770
5624
|
const pathname = url.searchParams.get("pathname");
|
|
4771
5625
|
if (!pathname) {
|
|
4772
5626
|
res.statusCode = 400;
|
|
4773
5627
|
res.end("Missing pathname");
|
|
5628
|
+
logResult(400, "missing pathname");
|
|
4774
5629
|
return;
|
|
4775
5630
|
}
|
|
4776
5631
|
const rscEnv = server.environments?.rsc;
|
|
@@ -4788,6 +5643,7 @@ ${err.stack}`
|
|
|
4788
5643
|
);
|
|
4789
5644
|
res.statusCode = 500;
|
|
4790
5645
|
res.end(`Prerender handler error: ${err.message}`);
|
|
5646
|
+
logResult(500, "module refresh failed");
|
|
4791
5647
|
return;
|
|
4792
5648
|
}
|
|
4793
5649
|
} else {
|
|
@@ -4802,6 +5658,7 @@ ${err.stack}`
|
|
|
4802
5658
|
if (!registry || registry.size === 0) {
|
|
4803
5659
|
res.statusCode = 503;
|
|
4804
5660
|
res.end("Prerender runner not available");
|
|
5661
|
+
logResult(503, "no registry");
|
|
4805
5662
|
return;
|
|
4806
5663
|
}
|
|
4807
5664
|
const wantIntercept = url.searchParams.get("intercept") === "1";
|
|
@@ -4836,6 +5693,7 @@ ${err.stack}`
|
|
|
4836
5693
|
payload = { segments: result.segments, handles: result.handles };
|
|
4837
5694
|
}
|
|
4838
5695
|
res.end(JSON.stringify(payload));
|
|
5696
|
+
logResult(200, `match ${result.routeName}`);
|
|
4839
5697
|
return;
|
|
4840
5698
|
} catch (err) {
|
|
4841
5699
|
console.warn(
|
|
@@ -4845,6 +5703,7 @@ ${err.stack}`
|
|
|
4845
5703
|
}
|
|
4846
5704
|
res.statusCode = 404;
|
|
4847
5705
|
res.end("No prerender match");
|
|
5706
|
+
logResult(404, "no match");
|
|
4848
5707
|
});
|
|
4849
5708
|
if (opts?.staticRouteTypesGeneration !== false) {
|
|
4850
5709
|
const isGeneratedRouteFile = (filePath) => filePath.endsWith(".gen.ts") && (filePath.includes("named-routes.gen.ts") || filePath.includes("urls.gen.ts"));
|
|
@@ -4864,42 +5723,96 @@ ${err.stack}`
|
|
|
4864
5723
|
return true;
|
|
4865
5724
|
};
|
|
4866
5725
|
let routeChangeTimer;
|
|
4867
|
-
let runtimeRediscoveryInProgress = false;
|
|
4868
5726
|
const refreshRuntimeDiscovery = async () => {
|
|
4869
5727
|
const rscEnv = server.environments?.rsc;
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
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
|
+
});
|
|
4883
5782
|
};
|
|
4884
5783
|
const scheduleRouteRegeneration = () => {
|
|
4885
5784
|
clearTimeout(routeChangeTimer);
|
|
4886
5785
|
routeChangeTimer = setTimeout(() => {
|
|
4887
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;
|
|
4888
5790
|
try {
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
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
|
+
}
|
|
4892
5800
|
}
|
|
4893
5801
|
} catch (err) {
|
|
4894
5802
|
console.error(
|
|
4895
5803
|
`[rsc-router] Route regeneration error: ${err.message}`
|
|
4896
5804
|
);
|
|
4897
5805
|
}
|
|
5806
|
+
debugDiscovery?.(
|
|
5807
|
+
"watcher: regenerated gen files (%sms)",
|
|
5808
|
+
(performance.now() - regenStart).toFixed(1)
|
|
5809
|
+
);
|
|
4898
5810
|
if (s.perRouterManifests.length > 0) {
|
|
4899
5811
|
refreshRuntimeDiscovery().catch((err) => {
|
|
4900
5812
|
console.warn(
|
|
4901
5813
|
`[rsc-router] Runtime re-discovery error: ${err.message}`
|
|
4902
5814
|
);
|
|
5815
|
+
resolveDiscoveryGate();
|
|
4903
5816
|
});
|
|
4904
5817
|
}
|
|
4905
5818
|
}, 100);
|
|
@@ -4917,6 +5830,12 @@ ${err.stack}`
|
|
|
4917
5830
|
const hasUrls = source.includes("urls(");
|
|
4918
5831
|
const hasCreateRouter = /\bcreateRouter\s*[<(]/.test(source);
|
|
4919
5832
|
if (!hasUrls && !hasCreateRouter) return;
|
|
5833
|
+
debugDiscovery?.(
|
|
5834
|
+
"watcher: %s matches (urls=%s, router=%s)",
|
|
5835
|
+
filePath,
|
|
5836
|
+
hasUrls,
|
|
5837
|
+
hasCreateRouter
|
|
5838
|
+
);
|
|
4920
5839
|
if (hasCreateRouter) {
|
|
4921
5840
|
const nestedRouterConflict = findNestedRouterConflict([
|
|
4922
5841
|
...s.cachedRouterFiles ?? [],
|
|
@@ -4930,6 +5849,9 @@ ${err.stack}`
|
|
|
4930
5849
|
}
|
|
4931
5850
|
s.cachedRouterFiles = void 0;
|
|
4932
5851
|
}
|
|
5852
|
+
if (s.perRouterManifests.length > 0) {
|
|
5853
|
+
gate.noteRouteEvent();
|
|
5854
|
+
}
|
|
4933
5855
|
scheduleRouteRegeneration();
|
|
4934
5856
|
} catch {
|
|
4935
5857
|
}
|
|
@@ -4949,15 +5871,31 @@ ${err.stack}`
|
|
|
4949
5871
|
// The manifest data is stored for the virtual module's load hook.
|
|
4950
5872
|
async buildStart() {
|
|
4951
5873
|
if (!s.isBuildMode) return;
|
|
4952
|
-
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 ?? "?");
|
|
4953
5883
|
resetStagedBuildAssets(s.projectRoot);
|
|
4954
5884
|
s.prerenderManifestEntries = null;
|
|
4955
5885
|
s.staticManifestEntries = null;
|
|
4956
|
-
await
|
|
5886
|
+
await timed(
|
|
5887
|
+
debugDiscovery,
|
|
5888
|
+
"build acquireBuildEnv",
|
|
5889
|
+
() => acquireBuildEnv(s, viteCommand, viteMode)
|
|
5890
|
+
);
|
|
4957
5891
|
let tempServer = null;
|
|
4958
5892
|
globalThis.__rscRouterDiscoveryActive = true;
|
|
4959
5893
|
try {
|
|
4960
|
-
tempServer = await
|
|
5894
|
+
tempServer = await timed(
|
|
5895
|
+
debugDiscovery,
|
|
5896
|
+
"build createTempRscServer",
|
|
5897
|
+
() => createTempRscServer(s, { forceBuild: true })
|
|
5898
|
+
);
|
|
4961
5899
|
const rscEnv = tempServer.environments?.rsc;
|
|
4962
5900
|
if (!rscEnv?.runner) {
|
|
4963
5901
|
console.warn(
|
|
@@ -4971,8 +5909,16 @@ ${err.stack}`
|
|
|
4971
5909
|
if (tempIdsPlugin?.api?.staticHandlerModules) {
|
|
4972
5910
|
s.resolvedStaticModules = tempIdsPlugin.api.staticHandlerModules;
|
|
4973
5911
|
}
|
|
4974
|
-
await
|
|
4975
|
-
|
|
5912
|
+
await timed(
|
|
5913
|
+
debugDiscovery,
|
|
5914
|
+
"build discoverRouters",
|
|
5915
|
+
() => discoverRouters(s, rscEnv)
|
|
5916
|
+
);
|
|
5917
|
+
timedSync(
|
|
5918
|
+
debugDiscovery,
|
|
5919
|
+
"build writeRouteTypesFiles",
|
|
5920
|
+
() => writeRouteTypesFiles(s)
|
|
5921
|
+
);
|
|
4976
5922
|
} catch (err) {
|
|
4977
5923
|
const sourceFile = err.stack?.split("\n").find(
|
|
4978
5924
|
(line) => line.includes(s.projectRoot) && !line.includes("node_modules")
|
|
@@ -4991,9 +5937,45 @@ ${details}`
|
|
|
4991
5937
|
} finally {
|
|
4992
5938
|
delete globalThis.__rscRouterDiscoveryActive;
|
|
4993
5939
|
if (tempServer) {
|
|
4994
|
-
await
|
|
5940
|
+
await timed(
|
|
5941
|
+
debugDiscovery,
|
|
5942
|
+
"build tempServer.close",
|
|
5943
|
+
() => tempServer.close()
|
|
5944
|
+
);
|
|
4995
5945
|
}
|
|
4996
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 [];
|
|
4997
5979
|
}
|
|
4998
5980
|
},
|
|
4999
5981
|
// Virtual module: provides the pre-generated route manifest as a JS module
|
|
@@ -5010,17 +5992,36 @@ ${details}`
|
|
|
5010
5992
|
async load(id) {
|
|
5011
5993
|
if (id === "\0" + VIRTUAL_ROUTES_MANIFEST_ID) {
|
|
5012
5994
|
if (s.discoveryDone) {
|
|
5013
|
-
await
|
|
5995
|
+
await timed(
|
|
5996
|
+
debugRoutes,
|
|
5997
|
+
"await discoveryDone (manifest)",
|
|
5998
|
+
() => s.discoveryDone
|
|
5999
|
+
);
|
|
5014
6000
|
}
|
|
5015
|
-
|
|
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;
|
|
5016
6008
|
}
|
|
5017
6009
|
const perRouterPrefix = "\0" + VIRTUAL_ROUTES_MANIFEST_ID + "/";
|
|
5018
6010
|
if (id.startsWith(perRouterPrefix)) {
|
|
5019
6011
|
if (s.discoveryDone) {
|
|
5020
|
-
await
|
|
6012
|
+
await timed(
|
|
6013
|
+
debugRoutes,
|
|
6014
|
+
"await discoveryDone (per-router)",
|
|
6015
|
+
() => s.discoveryDone
|
|
6016
|
+
);
|
|
5021
6017
|
}
|
|
5022
6018
|
const routerId = id.slice(perRouterPrefix.length);
|
|
5023
|
-
|
|
6019
|
+
const code = await timed(
|
|
6020
|
+
debugRoutes,
|
|
6021
|
+
`generatePerRouterModule ${routerId}`,
|
|
6022
|
+
() => generatePerRouterModule(s, routerId)
|
|
6023
|
+
);
|
|
6024
|
+
return code;
|
|
5024
6025
|
}
|
|
5025
6026
|
return null;
|
|
5026
6027
|
},
|
|
@@ -5028,14 +6029,20 @@ ${details}`
|
|
|
5028
6029
|
// Used by closeBundle for handler code eviction and prerender data injection.
|
|
5029
6030
|
generateBundle(_options, bundle) {
|
|
5030
6031
|
if (this.environment?.name !== "rsc") return;
|
|
6032
|
+
const genStart = debugBuild ? performance.now() : 0;
|
|
5031
6033
|
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
5032
6034
|
if (chunk.type === "chunk" && chunk.isEntry) {
|
|
5033
6035
|
s.rscEntryFileName = fileName;
|
|
5034
6036
|
break;
|
|
5035
6037
|
}
|
|
5036
6038
|
}
|
|
5037
|
-
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
|
+
);
|
|
5038
6044
|
return;
|
|
6045
|
+
}
|
|
5039
6046
|
s.handlerChunkInfoMap.clear();
|
|
5040
6047
|
s.staticHandlerChunkInfoMap.clear();
|
|
5041
6048
|
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
@@ -5079,6 +6086,13 @@ ${details}`
|
|
|
5079
6086
|
}
|
|
5080
6087
|
}
|
|
5081
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
|
+
);
|
|
5082
6096
|
},
|
|
5083
6097
|
// Build-time pre-rendering: evict handler code and inject collected prerender data.
|
|
5084
6098
|
// Collection now happens in-process during discoverRouters() via RSC runner.
|
|
@@ -5089,29 +6103,41 @@ ${details}`
|
|
|
5089
6103
|
async handler() {
|
|
5090
6104
|
if (!s.isBuildMode) return;
|
|
5091
6105
|
if (this.environment && this.environment.name !== "rsc") return;
|
|
5092
|
-
|
|
6106
|
+
timedSync(
|
|
6107
|
+
debugBuild,
|
|
6108
|
+
"closeBundle postprocessBundle",
|
|
6109
|
+
() => postprocessBundle(s)
|
|
6110
|
+
);
|
|
5093
6111
|
}
|
|
5094
6112
|
}
|
|
5095
6113
|
};
|
|
5096
6114
|
}
|
|
5097
6115
|
|
|
5098
6116
|
// src/vite/rango.ts
|
|
6117
|
+
var debugConfig = createRangoDebugger(NS.config);
|
|
5099
6118
|
async function rango(options) {
|
|
6119
|
+
const rangoStart = performance.now();
|
|
5100
6120
|
const resolvedOptions = options ?? { preset: "node" };
|
|
5101
6121
|
const preset = resolvedOptions.preset ?? "node";
|
|
5102
6122
|
const showBanner = resolvedOptions.banner ?? true;
|
|
6123
|
+
debugConfig?.("rango(%s) setup start", preset);
|
|
5103
6124
|
const plugins = [];
|
|
5104
|
-
const rangoAliases = getPackageAliases();
|
|
6125
|
+
const rangoAliases = { ...getPackageAliases(), ...getVendorAliases() };
|
|
5105
6126
|
const excludeDeps = [
|
|
5106
6127
|
...getExcludeDeps(),
|
|
5107
|
-
//
|
|
5108
|
-
//
|
|
5109
|
-
// .
|
|
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.
|
|
5110
6136
|
"@vitejs/plugin-rsc/browser",
|
|
5111
|
-
// Keep the browser RSDW client out of Vite's dep optimizer so our
|
|
5112
|
-
// cjs-to-esm transform can patch the real file.
|
|
5113
6137
|
"@vitejs/plugin-rsc/vendor/react-server-dom/client.browser"
|
|
5114
6138
|
];
|
|
6139
|
+
const pkg = getPublishedPackageName();
|
|
6140
|
+
const nested = (spec) => `${pkg} > ${spec}`;
|
|
5115
6141
|
const routerRef = { path: void 0 };
|
|
5116
6142
|
const prerenderEnabled = true;
|
|
5117
6143
|
if (preset === "cloudflare") {
|
|
@@ -5149,7 +6175,7 @@ async function rango(options) {
|
|
|
5149
6175
|
// Pre-bundle rsc-html-stream to prevent discovery during first request
|
|
5150
6176
|
// Exclude rsc-router modules to ensure same Context instance
|
|
5151
6177
|
optimizeDeps: {
|
|
5152
|
-
include: ["rsc-html-stream/client"],
|
|
6178
|
+
include: [nested("rsc-html-stream/client")],
|
|
5153
6179
|
exclude: excludeDeps,
|
|
5154
6180
|
esbuildOptions: sharedEsbuildOptions
|
|
5155
6181
|
}
|
|
@@ -5174,8 +6200,10 @@ async function rango(options) {
|
|
|
5174
6200
|
"react-dom/static.edge",
|
|
5175
6201
|
"react/jsx-runtime",
|
|
5176
6202
|
"react/jsx-dev-runtime",
|
|
5177
|
-
"rsc-html-stream/server",
|
|
5178
|
-
|
|
6203
|
+
nested("rsc-html-stream/server"),
|
|
6204
|
+
nested(
|
|
6205
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge"
|
|
6206
|
+
)
|
|
5179
6207
|
],
|
|
5180
6208
|
exclude: excludeDeps,
|
|
5181
6209
|
esbuildOptions: sharedEsbuildOptions
|
|
@@ -5190,7 +6218,9 @@ async function rango(options) {
|
|
|
5190
6218
|
"react",
|
|
5191
6219
|
"react/jsx-runtime",
|
|
5192
6220
|
"react/jsx-dev-runtime",
|
|
5193
|
-
|
|
6221
|
+
nested(
|
|
6222
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge"
|
|
6223
|
+
)
|
|
5194
6224
|
],
|
|
5195
6225
|
exclude: excludeDeps,
|
|
5196
6226
|
esbuildOptions: sharedEsbuildOptions
|
|
@@ -5271,7 +6301,7 @@ ${list}`);
|
|
|
5271
6301
|
"react-dom",
|
|
5272
6302
|
"react/jsx-runtime",
|
|
5273
6303
|
"react/jsx-dev-runtime",
|
|
5274
|
-
"rsc-html-stream/client"
|
|
6304
|
+
nested("rsc-html-stream/client")
|
|
5275
6305
|
],
|
|
5276
6306
|
exclude: excludeDeps,
|
|
5277
6307
|
esbuildOptions: sharedEsbuildOptions,
|
|
@@ -5288,7 +6318,9 @@ ${list}`);
|
|
|
5288
6318
|
"react-dom/static.edge",
|
|
5289
6319
|
"react/jsx-runtime",
|
|
5290
6320
|
"react/jsx-dev-runtime",
|
|
5291
|
-
|
|
6321
|
+
nested(
|
|
6322
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge"
|
|
6323
|
+
)
|
|
5292
6324
|
],
|
|
5293
6325
|
exclude: excludeDeps,
|
|
5294
6326
|
esbuildOptions: sharedEsbuildOptions
|
|
@@ -5301,7 +6333,9 @@ ${list}`);
|
|
|
5301
6333
|
"react",
|
|
5302
6334
|
"react/jsx-runtime",
|
|
5303
6335
|
"react/jsx-dev-runtime",
|
|
5304
|
-
|
|
6336
|
+
nested(
|
|
6337
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge"
|
|
6338
|
+
)
|
|
5305
6339
|
],
|
|
5306
6340
|
esbuildOptions: sharedEsbuildOptions
|
|
5307
6341
|
}
|
|
@@ -5371,6 +6405,12 @@ ${list}`);
|
|
|
5371
6405
|
preset
|
|
5372
6406
|
})
|
|
5373
6407
|
);
|
|
6408
|
+
debugConfig?.(
|
|
6409
|
+
"rango(%s) setup done: %d plugin(s) (%sms)",
|
|
6410
|
+
preset,
|
|
6411
|
+
plugins.length,
|
|
6412
|
+
(performance.now() - rangoStart).toFixed(1)
|
|
6413
|
+
);
|
|
5374
6414
|
return plugins;
|
|
5375
6415
|
}
|
|
5376
6416
|
|
|
@@ -5381,7 +6421,7 @@ function poke() {
|
|
|
5381
6421
|
apply: "serve",
|
|
5382
6422
|
configureServer(server) {
|
|
5383
6423
|
const stdin = process.stdin;
|
|
5384
|
-
const
|
|
6424
|
+
const debug11 = process.env.RANGO_POKE_DEBUG === "1";
|
|
5385
6425
|
const triggerReload = (source) => {
|
|
5386
6426
|
server.hot.send({ type: "full-reload", path: "*" });
|
|
5387
6427
|
server.config.logger.info(` browser reload (${source})`, {
|
|
@@ -5414,7 +6454,7 @@ function poke() {
|
|
|
5414
6454
|
lines.pop();
|
|
5415
6455
|
return lines;
|
|
5416
6456
|
};
|
|
5417
|
-
if (
|
|
6457
|
+
if (debug11) {
|
|
5418
6458
|
server.config.logger.info(
|
|
5419
6459
|
` poke debug enabled (isTTY=${stdin.isTTY ? "yes" : "no"}, isRaw=${stdin.isTTY ? stdin.isRaw ? "yes" : "no" : "n/a"})`,
|
|
5420
6460
|
{ timestamp: true }
|
|
@@ -5427,7 +6467,7 @@ function poke() {
|
|
|
5427
6467
|
);
|
|
5428
6468
|
}
|
|
5429
6469
|
const onData = (data) => {
|
|
5430
|
-
if (
|
|
6470
|
+
if (debug11) {
|
|
5431
6471
|
server.config.logger.info(` poke stdin ${formatChunk(data)}`, {
|
|
5432
6472
|
timestamp: true
|
|
5433
6473
|
});
|