@rangojs/router 0.0.0-experimental.20 → 0.0.0-experimental.22
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 +43 -10
- package/dist/vite/index.js +130 -84
- package/package.json +1 -1
- package/skills/caching/SKILL.md +4 -4
- package/skills/document-cache/SKILL.md +2 -2
- package/skills/hooks/SKILL.md +13 -12
- package/skills/host-router/SKILL.md +218 -0
- package/skills/loader/SKILL.md +2 -2
- package/skills/prerender/SKILL.md +2 -2
- package/skills/rango/SKILL.md +0 -1
- package/skills/router-setup/SKILL.md +2 -2
- package/skills/typesafety/SKILL.md +1 -1
- package/src/host/index.ts +0 -3
- package/src/index.ts +30 -31
- package/src/prerender/store.ts +56 -15
- package/src/route-definition/index.ts +0 -3
- package/src/router/router-options.ts +1 -1
- package/src/rsc/index.ts +0 -20
- package/src/server.ts +6 -0
- package/src/theme/index.ts +4 -13
- package/src/vite/discovery/bundle-postprocess.ts +31 -56
- package/src/vite/discovery/discover-routers.ts +2 -3
- package/src/vite/discovery/prerender-collection.ts +34 -14
- package/src/vite/discovery/state.ts +4 -7
- package/src/vite/router-discovery.ts +4 -0
- package/src/vite/utils/prerender-utils.ts +60 -0
- package/skills/testing/SKILL.md +0 -226
- package/src/route-definition/route-function.ts +0 -119
package/README.md
CHANGED
|
@@ -45,6 +45,30 @@ For Cloudflare Workers:
|
|
|
45
45
|
npm install @cloudflare/vite-plugin
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
+
## Import Paths
|
|
49
|
+
|
|
50
|
+
Use these import paths consistently:
|
|
51
|
+
|
|
52
|
+
- `@rangojs/router` — server/RSC router APIs, route DSL, `createRouter`, `urls`, `redirect`, `Prerender`, `Static`, shared types
|
|
53
|
+
- `@rangojs/router/client` — hooks and components such as `Link`, `Outlet`, `href`, `useNavigation`, `useLoader`, `useAction`, `useLocationState`
|
|
54
|
+
- `@rangojs/router/cache` — public cache APIs such as `CFCacheStore`, `MemorySegmentCacheStore`, `createDocumentCacheMiddleware`
|
|
55
|
+
- `@rangojs/router/host`, `@rangojs/router/theme`, `@rangojs/router/vite` — specialized public subpaths
|
|
56
|
+
- `@rangojs/router/rsc`, `@rangojs/router/ssr` — advanced server-only integration subpaths for custom request/HTML pipelines
|
|
57
|
+
|
|
58
|
+
Use only subpaths that are explicitly exported from the package. Avoid deep imports such as `@rangojs/router/cache/cf`.
|
|
59
|
+
|
|
60
|
+
`@rangojs/router` is conditionally resolved. Server-only root APIs such as
|
|
61
|
+
`createRouter()`, `urls()`, `redirect()`, `Prerender()`, and `cookies()` rely on
|
|
62
|
+
the `react-server` export condition and are meant to run in router definitions,
|
|
63
|
+
handlers, and other RSC/server modules. Outside that environment the root entry
|
|
64
|
+
falls back to stub implementations that throw guidance errors.
|
|
65
|
+
|
|
66
|
+
If you hit a root-entrypoint stub error:
|
|
67
|
+
|
|
68
|
+
- hooks and components like `Link`, `Outlet`, `useLoader`, `useNavigation`, and `MetaTags` belong in `@rangojs/router/client`
|
|
69
|
+
- cache APIs like `CFCacheStore` and `createDocumentCacheMiddleware` belong in `@rangojs/router/cache`
|
|
70
|
+
- host-router APIs belong in `@rangojs/router/host`
|
|
71
|
+
|
|
48
72
|
## Quick Start
|
|
49
73
|
|
|
50
74
|
### Vite Config
|
|
@@ -62,6 +86,9 @@ export default defineConfig({
|
|
|
62
86
|
|
|
63
87
|
### Router
|
|
64
88
|
|
|
89
|
+
This file is a server/RSC module and should import router construction APIs from
|
|
90
|
+
`@rangojs/router`.
|
|
91
|
+
|
|
65
92
|
```tsx
|
|
66
93
|
// src/router.tsx
|
|
67
94
|
import { createRouter, urls } from "@rangojs/router";
|
|
@@ -842,16 +869,22 @@ module, use `scopedReverse<typeof localPatterns>(ctx.reverse)` or
|
|
|
842
869
|
|
|
843
870
|
## Subpath Exports
|
|
844
871
|
|
|
845
|
-
| Export | Description
|
|
846
|
-
| ------------------------ |
|
|
847
|
-
| `@rangojs/router` |
|
|
848
|
-
| `@rangojs/router/client` | Client: `Link`, `Outlet`, `href`, `useNavigation`, `useLoader`, `MetaTags`
|
|
849
|
-
| `@rangojs/router/cache` | Cache: `CFCacheStore`, `MemorySegmentCacheStore`, `createDocumentCacheMiddleware`
|
|
850
|
-
| `@rangojs/router/theme` | Theme: `useTheme`, `ThemeProvider`, `ThemeScript`
|
|
851
|
-
| `@rangojs/router/host` | Host routing: `createHostRouter`, `defineHosts`
|
|
852
|
-
| `@rangojs/router/vite` | Vite plugin: `rango()`
|
|
853
|
-
| `@rangojs/router/server`
|
|
854
|
-
| `@rangojs/router/
|
|
872
|
+
| Export | Description |
|
|
873
|
+
| ------------------------ | -------------------------------------------------------------------------------------------------------- |
|
|
874
|
+
| `@rangojs/router` | Server/RSC core and shared types: `createRouter`, `urls`, `createLoader`, `Handler`, `Prerender`, `Meta` |
|
|
875
|
+
| `@rangojs/router/client` | Client: `Link`, `Outlet`, `href`, `useNavigation`, `useLoader`, `MetaTags` |
|
|
876
|
+
| `@rangojs/router/cache` | Cache: `CFCacheStore`, `MemorySegmentCacheStore`, `createDocumentCacheMiddleware` |
|
|
877
|
+
| `@rangojs/router/theme` | Theme: `useTheme`, `ThemeProvider`, `ThemeScript` |
|
|
878
|
+
| `@rangojs/router/host` | Host routing: `createHostRouter`, `defineHosts` |
|
|
879
|
+
| `@rangojs/router/vite` | Vite plugin: `rango()` |
|
|
880
|
+
| `@rangojs/router/rsc` | Advanced server pipeline APIs: `createRSCHandler`, request-context access |
|
|
881
|
+
| `@rangojs/router/ssr` | Advanced SSR bridge APIs: `createSSRHandler` |
|
|
882
|
+
| `@rangojs/router/server` | Internal build/runtime utilities for advanced integrations |
|
|
883
|
+
| `@rangojs/router/build` | Build utilities |
|
|
884
|
+
|
|
885
|
+
The root entrypoint is not a generic client/runtime barrel. If you need hooks
|
|
886
|
+
or components, import from `@rangojs/router/client`; if you need cache or host
|
|
887
|
+
APIs, use their dedicated subpaths.
|
|
855
888
|
|
|
856
889
|
## Examples
|
|
857
890
|
|
package/dist/vite/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/vite/rango.ts
|
|
2
2
|
import { readFileSync as readFileSync7 } from "node:fs";
|
|
3
|
-
import { resolve as
|
|
3
|
+
import { resolve as resolve9 } from "node:path";
|
|
4
4
|
|
|
5
5
|
// src/vite/plugins/expose-action-id.ts
|
|
6
6
|
import MagicString from "magic-string";
|
|
@@ -1745,7 +1745,7 @@ import { resolve } from "node:path";
|
|
|
1745
1745
|
// package.json
|
|
1746
1746
|
var package_default = {
|
|
1747
1747
|
name: "@rangojs/router",
|
|
1748
|
-
version: "0.0.0-experimental.
|
|
1748
|
+
version: "0.0.0-experimental.22",
|
|
1749
1749
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
1750
1750
|
keywords: [
|
|
1751
1751
|
"react",
|
|
@@ -3024,7 +3024,7 @@ function createCjsToEsmPlugin() {
|
|
|
3024
3024
|
|
|
3025
3025
|
// src/vite/router-discovery.ts
|
|
3026
3026
|
import { createServer as createViteServer } from "vite";
|
|
3027
|
-
import { resolve as
|
|
3027
|
+
import { resolve as resolve8 } from "node:path";
|
|
3028
3028
|
import { readFileSync as readFileSync6 } from "node:fs";
|
|
3029
3029
|
|
|
3030
3030
|
// src/vite/plugins/virtual-stub-plugin.ts
|
|
@@ -3207,8 +3207,8 @@ function createDiscoveryState(entryPath, opts) {
|
|
|
3207
3207
|
perRouterTrieMap: /* @__PURE__ */ new Map(),
|
|
3208
3208
|
perRouterPrecomputedMap: /* @__PURE__ */ new Map(),
|
|
3209
3209
|
perRouterManifestDataMap: /* @__PURE__ */ new Map(),
|
|
3210
|
-
|
|
3211
|
-
|
|
3210
|
+
prerenderManifestEntries: null,
|
|
3211
|
+
staticManifestEntries: null,
|
|
3212
3212
|
handlerChunkInfo: null,
|
|
3213
3213
|
staticHandlerChunkInfo: null,
|
|
3214
3214
|
rscEntryFileName: null,
|
|
@@ -3308,6 +3308,16 @@ function contextSet(variables, keyOrVar, value) {
|
|
|
3308
3308
|
}
|
|
3309
3309
|
|
|
3310
3310
|
// src/vite/utils/prerender-utils.ts
|
|
3311
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
3312
|
+
import {
|
|
3313
|
+
copyFileSync,
|
|
3314
|
+
existsSync as existsSync4,
|
|
3315
|
+
mkdirSync,
|
|
3316
|
+
rmSync,
|
|
3317
|
+
statSync,
|
|
3318
|
+
writeFileSync as writeFileSync2
|
|
3319
|
+
} from "node:fs";
|
|
3320
|
+
import { resolve as resolve5 } from "node:path";
|
|
3311
3321
|
function escapeRegExp2(str) {
|
|
3312
3322
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3313
3323
|
}
|
|
@@ -3386,6 +3396,37 @@ function notifyOnError(registry, error, phase, routeKey, pathname, skipped) {
|
|
|
3386
3396
|
break;
|
|
3387
3397
|
}
|
|
3388
3398
|
}
|
|
3399
|
+
function getStagedAssetDir(projectRoot) {
|
|
3400
|
+
return resolve5(projectRoot, "node_modules/.rangojs-router-build/rsc-assets");
|
|
3401
|
+
}
|
|
3402
|
+
function resetStagedBuildAssets(projectRoot) {
|
|
3403
|
+
rmSync(getStagedAssetDir(projectRoot), { recursive: true, force: true });
|
|
3404
|
+
}
|
|
3405
|
+
function stageBuildAssetModule(projectRoot, prefix, exportValue) {
|
|
3406
|
+
const stagedDir = getStagedAssetDir(projectRoot);
|
|
3407
|
+
mkdirSync(stagedDir, { recursive: true });
|
|
3408
|
+
const contentHash = createHash4("sha256").update(exportValue).digest("hex").slice(0, 8);
|
|
3409
|
+
const fileName = `${prefix}-${contentHash}.js`;
|
|
3410
|
+
const filePath = resolve5(stagedDir, fileName);
|
|
3411
|
+
if (!existsSync4(filePath)) {
|
|
3412
|
+
writeFileSync2(filePath, `export default ${exportValue};
|
|
3413
|
+
`);
|
|
3414
|
+
}
|
|
3415
|
+
return fileName;
|
|
3416
|
+
}
|
|
3417
|
+
function copyStagedBuildAssets(projectRoot, fileNames) {
|
|
3418
|
+
const stagedDir = getStagedAssetDir(projectRoot);
|
|
3419
|
+
const distAssetsDir = resolve5(projectRoot, "dist/rsc/assets");
|
|
3420
|
+
mkdirSync(distAssetsDir, { recursive: true });
|
|
3421
|
+
let totalBytes = 0;
|
|
3422
|
+
for (const fileName of new Set(fileNames)) {
|
|
3423
|
+
const stagedPath = resolve5(stagedDir, fileName);
|
|
3424
|
+
const distPath = resolve5(distAssetsDir, fileName);
|
|
3425
|
+
copyFileSync(stagedPath, distPath);
|
|
3426
|
+
totalBytes += statSync(stagedPath).size;
|
|
3427
|
+
}
|
|
3428
|
+
return totalBytes;
|
|
3429
|
+
}
|
|
3389
3430
|
|
|
3390
3431
|
// src/vite/discovery/prerender-collection.ts
|
|
3391
3432
|
async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
@@ -3487,7 +3528,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3487
3528
|
`[rsc-router] Pre-rendering ${entries.length} URL(s)${concurrencyNote}...`
|
|
3488
3529
|
);
|
|
3489
3530
|
const { hashParams } = await rscEnv.runner.import("@rangojs/router/build");
|
|
3490
|
-
const
|
|
3531
|
+
const manifestEntries = {};
|
|
3491
3532
|
let doneCount = 0;
|
|
3492
3533
|
let skipCount = 0;
|
|
3493
3534
|
const startTotal = performance.now();
|
|
@@ -3517,18 +3558,30 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3517
3558
|
break;
|
|
3518
3559
|
}
|
|
3519
3560
|
const paramHash = hashParams(result.params || {});
|
|
3520
|
-
|
|
3561
|
+
const mainKey = `${result.routeName}/${paramHash}`;
|
|
3562
|
+
const mainValue = JSON.stringify({
|
|
3521
3563
|
segments: result.segments,
|
|
3522
3564
|
handles: result.handles
|
|
3523
|
-
};
|
|
3565
|
+
});
|
|
3566
|
+
manifestEntries[mainKey] = stageBuildAssetModule(
|
|
3567
|
+
state.projectRoot,
|
|
3568
|
+
"__pr",
|
|
3569
|
+
mainValue
|
|
3570
|
+
);
|
|
3524
3571
|
if (result.interceptSegments?.length) {
|
|
3525
|
-
|
|
3572
|
+
const interceptKey = `${result.routeName}/${paramHash}/i`;
|
|
3573
|
+
const interceptValue = JSON.stringify({
|
|
3526
3574
|
segments: [...result.segments, ...result.interceptSegments],
|
|
3527
3575
|
handles: {
|
|
3528
3576
|
...result.handles,
|
|
3529
3577
|
...result.interceptHandles || {}
|
|
3530
3578
|
}
|
|
3531
|
-
};
|
|
3579
|
+
});
|
|
3580
|
+
manifestEntries[interceptKey] = stageBuildAssetModule(
|
|
3581
|
+
state.projectRoot,
|
|
3582
|
+
"__pr",
|
|
3583
|
+
interceptValue
|
|
3584
|
+
);
|
|
3532
3585
|
}
|
|
3533
3586
|
const elapsed = (performance.now() - startUrl).toFixed(0);
|
|
3534
3587
|
console.log(
|
|
@@ -3572,7 +3625,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3572
3625
|
}
|
|
3573
3626
|
const totalElapsed = (performance.now() - startTotal).toFixed(0);
|
|
3574
3627
|
if (doneCount > 0) {
|
|
3575
|
-
state.
|
|
3628
|
+
state.prerenderManifestEntries = manifestEntries;
|
|
3576
3629
|
}
|
|
3577
3630
|
const parts = [`${doneCount} done`];
|
|
3578
3631
|
if (skipCount > 0) parts.push(`${skipCount} skipped`);
|
|
@@ -3583,7 +3636,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
3583
3636
|
async function renderStaticHandlers(state, rscEnv, registry) {
|
|
3584
3637
|
if (!state.opts?.enableBuildPrerender || !state.isBuildMode || !state.resolvedStaticModules?.size)
|
|
3585
3638
|
return;
|
|
3586
|
-
const
|
|
3639
|
+
const manifestEntries = {};
|
|
3587
3640
|
let staticDone = 0;
|
|
3588
3641
|
let staticSkip = 0;
|
|
3589
3642
|
let totalStaticCount = 0;
|
|
@@ -3620,7 +3673,13 @@ async function renderStaticHandlers(state, rscEnv, registry) {
|
|
|
3620
3673
|
def.$$routePrefix
|
|
3621
3674
|
);
|
|
3622
3675
|
if (result) {
|
|
3623
|
-
|
|
3676
|
+
const hasHandles = Object.keys(result.handles).length > 0;
|
|
3677
|
+
const exportValue = hasHandles ? JSON.stringify(result) : JSON.stringify(result.encoded);
|
|
3678
|
+
manifestEntries[def.$$id] = stageBuildAssetModule(
|
|
3679
|
+
state.projectRoot,
|
|
3680
|
+
"__st",
|
|
3681
|
+
exportValue
|
|
3682
|
+
);
|
|
3624
3683
|
const elapsed = (performance.now() - startHandler).toFixed(0);
|
|
3625
3684
|
console.log(
|
|
3626
3685
|
`[rsc-router] OK ${name.padEnd(40)} (${elapsed}ms)`
|
|
@@ -3657,7 +3716,7 @@ async function renderStaticHandlers(state, rscEnv, registry) {
|
|
|
3657
3716
|
}
|
|
3658
3717
|
const totalStaticElapsed = (performance.now() - startStatic).toFixed(0);
|
|
3659
3718
|
if (staticDone > 0) {
|
|
3660
|
-
state.
|
|
3719
|
+
state.staticManifestEntries = manifestEntries;
|
|
3661
3720
|
}
|
|
3662
3721
|
const staticParts = [`${staticDone} done`];
|
|
3663
3722
|
if (staticSkip > 0) staticParts.push(`${staticSkip} skipped`);
|
|
@@ -3674,8 +3733,7 @@ async function discoverRouters(state, rscEnv) {
|
|
|
3674
3733
|
let registry = serverMod.RouterRegistry;
|
|
3675
3734
|
if (!registry || registry.size === 0) {
|
|
3676
3735
|
try {
|
|
3677
|
-
const
|
|
3678
|
-
const hostRegistry = hostMod.HostRouterRegistry;
|
|
3736
|
+
const hostRegistry = serverMod.HostRouterRegistry;
|
|
3679
3737
|
if (hostRegistry && hostRegistry.size > 0) {
|
|
3680
3738
|
console.log(
|
|
3681
3739
|
`[rsc-router] Found ${hostRegistry.size} host router(s), resolving lazy handlers...`
|
|
@@ -3879,8 +3937,8 @@ async function discoverRouters(state, rscEnv) {
|
|
|
3879
3937
|
}
|
|
3880
3938
|
|
|
3881
3939
|
// src/vite/discovery/route-types-writer.ts
|
|
3882
|
-
import { dirname as dirname3, basename, join as join3, resolve as
|
|
3883
|
-
import { readFileSync as readFileSync4, writeFileSync as
|
|
3940
|
+
import { dirname as dirname3, basename, join as join3, resolve as resolve6 } from "node:path";
|
|
3941
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync5, unlinkSync as unlinkSync2 } from "node:fs";
|
|
3884
3942
|
function filterUserNamedRoutes(manifest) {
|
|
3885
3943
|
const filtered = {};
|
|
3886
3944
|
for (const [name, pattern] of Object.entries(manifest)) {
|
|
@@ -3914,7 +3972,7 @@ function writeCombinedRouteTypesWithTracking(state, opts) {
|
|
|
3914
3972
|
""
|
|
3915
3973
|
);
|
|
3916
3974
|
const outPath = join3(routerDir, `${routerBasename}.named-routes.gen.ts`);
|
|
3917
|
-
if (!
|
|
3975
|
+
if (!existsSync5(outPath)) continue;
|
|
3918
3976
|
try {
|
|
3919
3977
|
const content = readFileSync4(outPath, "utf-8");
|
|
3920
3978
|
if (content !== preContent.get(outPath)) {
|
|
@@ -3928,10 +3986,10 @@ function writeRouteTypesFiles(state) {
|
|
|
3928
3986
|
if (state.perRouterManifests.length === 0) return;
|
|
3929
3987
|
try {
|
|
3930
3988
|
const entryDir = dirname3(
|
|
3931
|
-
|
|
3989
|
+
resolve6(state.projectRoot, state.resolvedEntryPath)
|
|
3932
3990
|
);
|
|
3933
3991
|
const oldCombinedPath = join3(entryDir, "named-routes.gen.ts");
|
|
3934
|
-
if (
|
|
3992
|
+
if (existsSync5(oldCombinedPath)) {
|
|
3935
3993
|
unlinkSync2(oldCombinedPath);
|
|
3936
3994
|
console.log(
|
|
3937
3995
|
`[rsc-router] Removed stale combined route types: ${oldCombinedPath}`
|
|
@@ -3975,10 +4033,10 @@ Set an explicit \`id\` on createRouter() or check the call site.`
|
|
|
3975
4033
|
userRoutes,
|
|
3976
4034
|
effectiveSearchSchemas && Object.keys(effectiveSearchSchemas).length > 0 ? effectiveSearchSchemas : void 0
|
|
3977
4035
|
);
|
|
3978
|
-
const existing =
|
|
4036
|
+
const existing = existsSync5(outPath) ? readFileSync4(outPath, "utf-8") : null;
|
|
3979
4037
|
if (existing !== source) {
|
|
3980
4038
|
markSelfGenWrite(state, outPath, source);
|
|
3981
|
-
|
|
4039
|
+
writeFileSync3(outPath, source);
|
|
3982
4040
|
console.log(`[rsc-router] Generated route types -> ${outPath}`);
|
|
3983
4041
|
}
|
|
3984
4042
|
}
|
|
@@ -4025,10 +4083,10 @@ function supplementGenFilesWithRuntimeRoutes(state) {
|
|
|
4025
4083
|
mergedRoutes,
|
|
4026
4084
|
Object.keys(mergedSearchSchemas).length > 0 ? mergedSearchSchemas : void 0
|
|
4027
4085
|
);
|
|
4028
|
-
const existing =
|
|
4086
|
+
const existing = existsSync5(outPath) ? readFileSync4(outPath, "utf-8") : null;
|
|
4029
4087
|
if (existing !== source) {
|
|
4030
4088
|
markSelfGenWrite(state, outPath, source);
|
|
4031
|
-
|
|
4089
|
+
writeFileSync3(outPath, source);
|
|
4032
4090
|
}
|
|
4033
4091
|
}
|
|
4034
4092
|
}
|
|
@@ -4173,14 +4231,13 @@ function generatePerRouterModule(state, routerId) {
|
|
|
4173
4231
|
}
|
|
4174
4232
|
|
|
4175
4233
|
// src/vite/discovery/bundle-postprocess.ts
|
|
4176
|
-
import { resolve as
|
|
4177
|
-
import {
|
|
4178
|
-
import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync5, mkdirSync } from "node:fs";
|
|
4234
|
+
import { resolve as resolve7 } from "node:path";
|
|
4235
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync6 } from "node:fs";
|
|
4179
4236
|
function postprocessBundle(state) {
|
|
4180
|
-
const hasPrerenderData = state.
|
|
4181
|
-
const hasStaticData = state.
|
|
4237
|
+
const hasPrerenderData = state.prerenderManifestEntries && Object.keys(state.prerenderManifestEntries).length > 0;
|
|
4238
|
+
const hasStaticData = state.staticManifestEntries && Object.keys(state.staticManifestEntries).length > 0;
|
|
4182
4239
|
if (!hasPrerenderData && !hasStaticData) return;
|
|
4183
|
-
const rscEntryPath =
|
|
4240
|
+
const rscEntryPath = resolve7(
|
|
4184
4241
|
state.projectRoot,
|
|
4185
4242
|
"dist/rsc",
|
|
4186
4243
|
state.rscEntryFileName ?? "index.js"
|
|
@@ -4201,7 +4258,7 @@ function postprocessBundle(state) {
|
|
|
4201
4258
|
];
|
|
4202
4259
|
for (const target of evictionTargets) {
|
|
4203
4260
|
if (!target.info) continue;
|
|
4204
|
-
const chunkPath =
|
|
4261
|
+
const chunkPath = resolve7(
|
|
4205
4262
|
state.projectRoot,
|
|
4206
4263
|
"dist/rsc",
|
|
4207
4264
|
target.info.fileName
|
|
@@ -4215,7 +4272,7 @@ function postprocessBundle(state) {
|
|
|
4215
4272
|
target.brand
|
|
4216
4273
|
);
|
|
4217
4274
|
if (result) {
|
|
4218
|
-
|
|
4275
|
+
writeFileSync4(chunkPath, result.code);
|
|
4219
4276
|
const savedKB = (result.savedBytes / 1024).toFixed(1);
|
|
4220
4277
|
console.log(
|
|
4221
4278
|
`[rsc-router] Evicted ${target.label} (${savedKB} KB saved): ${target.info.fileName}`
|
|
@@ -4229,44 +4286,38 @@ function postprocessBundle(state) {
|
|
|
4229
4286
|
}
|
|
4230
4287
|
state.handlerChunkInfo = null;
|
|
4231
4288
|
state.staticHandlerChunkInfo = null;
|
|
4232
|
-
if (hasPrerenderData &&
|
|
4289
|
+
if (hasPrerenderData && existsSync6(rscEntryPath)) {
|
|
4233
4290
|
const rscCode = readFileSync5(rscEntryPath, "utf-8");
|
|
4234
4291
|
if (!rscCode.includes("__prerender-manifest.js")) {
|
|
4235
4292
|
try {
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4293
|
+
let totalBytes = copyStagedBuildAssets(
|
|
4294
|
+
state.projectRoot,
|
|
4295
|
+
Object.values(state.prerenderManifestEntries)
|
|
4296
|
+
);
|
|
4297
|
+
const manifestMap = {};
|
|
4298
|
+
for (const [key, assetFileName] of Object.entries(
|
|
4299
|
+
state.prerenderManifestEntries
|
|
4242
4300
|
)) {
|
|
4243
|
-
|
|
4244
|
-
const contentHash = createHash4("sha256").update(entryJson).digest("hex").slice(0, 8);
|
|
4245
|
-
const assetFileName = `__pr-${contentHash}.js`;
|
|
4246
|
-
const assetPath = resolve6(assetsDir, assetFileName);
|
|
4247
|
-
const assetCode = `export default ${entryJson};
|
|
4248
|
-
`;
|
|
4249
|
-
writeFileSync3(assetPath, assetCode);
|
|
4250
|
-
totalBytes += Buffer.byteLength(assetCode);
|
|
4251
|
-
manifestEntries.push(
|
|
4252
|
-
`${JSON.stringify(key)}:()=>import("./assets/${assetFileName}")`
|
|
4253
|
-
);
|
|
4301
|
+
manifestMap[key] = `./assets/${assetFileName}`;
|
|
4254
4302
|
}
|
|
4255
|
-
const manifestCode =
|
|
4256
|
-
|
|
4257
|
-
|
|
4303
|
+
const manifestCode = [
|
|
4304
|
+
`const m=JSON.parse('${JSON.stringify(manifestMap).replace(/'/g, "\\'")}');`,
|
|
4305
|
+
`export function loadPrerenderAsset(s){return import(s)}`,
|
|
4306
|
+
`export default m;`,
|
|
4307
|
+
""
|
|
4308
|
+
].join("\n");
|
|
4309
|
+
const manifestPath = resolve7(
|
|
4258
4310
|
state.projectRoot,
|
|
4259
4311
|
"dist/rsc/__prerender-manifest.js"
|
|
4260
4312
|
);
|
|
4261
|
-
|
|
4313
|
+
writeFileSync4(manifestPath, manifestCode);
|
|
4262
4314
|
totalBytes += Buffer.byteLength(manifestCode);
|
|
4263
|
-
const injection = `
|
|
4264
|
-
globalThis.__PRERENDER_MANIFEST = __pm;
|
|
4315
|
+
const injection = `globalThis.__loadPrerenderManifestModule = () => import("./__prerender-manifest.js");
|
|
4265
4316
|
`;
|
|
4266
|
-
|
|
4317
|
+
writeFileSync4(rscEntryPath, injection + rscCode);
|
|
4267
4318
|
const totalKB = (totalBytes / 1024).toFixed(1);
|
|
4268
4319
|
console.log(
|
|
4269
|
-
`[rsc-router] Wrote prerender assets (${totalKB} KB total, ${Object.keys(state.
|
|
4320
|
+
`[rsc-router] Wrote prerender assets (${totalKB} KB total, ${Object.keys(state.prerenderManifestEntries).length} entries)`
|
|
4270
4321
|
);
|
|
4271
4322
|
} catch (err) {
|
|
4272
4323
|
throw new Error(
|
|
@@ -4275,44 +4326,36 @@ globalThis.__PRERENDER_MANIFEST = __pm;
|
|
|
4275
4326
|
}
|
|
4276
4327
|
}
|
|
4277
4328
|
}
|
|
4278
|
-
if (hasStaticData &&
|
|
4329
|
+
if (hasStaticData && existsSync6(rscEntryPath)) {
|
|
4279
4330
|
const rscCode = readFileSync5(rscEntryPath, "utf-8");
|
|
4280
4331
|
if (!rscCode.includes("__STATIC_MANIFEST")) {
|
|
4281
4332
|
try {
|
|
4282
|
-
const assetsDir = resolve6(state.projectRoot, "dist/rsc/assets");
|
|
4283
|
-
mkdirSync(assetsDir, { recursive: true });
|
|
4284
4333
|
const manifestEntries = [];
|
|
4285
|
-
let totalBytes =
|
|
4286
|
-
|
|
4287
|
-
state.
|
|
4334
|
+
let totalBytes = copyStagedBuildAssets(
|
|
4335
|
+
state.projectRoot,
|
|
4336
|
+
Object.values(state.staticManifestEntries)
|
|
4337
|
+
);
|
|
4338
|
+
for (const [handlerId, assetFileName] of Object.entries(
|
|
4339
|
+
state.staticManifestEntries
|
|
4288
4340
|
)) {
|
|
4289
|
-
const hasHandles = Object.keys(handles).length > 0;
|
|
4290
|
-
const exportValue = hasHandles ? JSON.stringify({ encoded, handles }) : JSON.stringify(encoded);
|
|
4291
|
-
const contentHash = createHash4("sha256").update(exportValue).digest("hex").slice(0, 8);
|
|
4292
|
-
const assetFileName = `__st-${contentHash}.js`;
|
|
4293
|
-
const assetPath = resolve6(assetsDir, assetFileName);
|
|
4294
|
-
const assetCode = `export default ${exportValue};
|
|
4295
|
-
`;
|
|
4296
|
-
writeFileSync3(assetPath, assetCode);
|
|
4297
|
-
totalBytes += Buffer.byteLength(assetCode);
|
|
4298
4341
|
manifestEntries.push(
|
|
4299
4342
|
`${JSON.stringify(handlerId)}:()=>import("./assets/${assetFileName}")`
|
|
4300
4343
|
);
|
|
4301
4344
|
}
|
|
4302
4345
|
const manifestCode = `const m={${manifestEntries.join(",")}};globalThis.__STATIC_MANIFEST=m;export default m;
|
|
4303
4346
|
`;
|
|
4304
|
-
const manifestPath =
|
|
4347
|
+
const manifestPath = resolve7(
|
|
4305
4348
|
state.projectRoot,
|
|
4306
4349
|
"dist/rsc/__static-manifest.js"
|
|
4307
4350
|
);
|
|
4308
|
-
|
|
4351
|
+
writeFileSync4(manifestPath, manifestCode);
|
|
4309
4352
|
totalBytes += Buffer.byteLength(manifestCode);
|
|
4310
4353
|
const injection = `import "./__static-manifest.js";
|
|
4311
4354
|
`;
|
|
4312
|
-
|
|
4355
|
+
writeFileSync4(rscEntryPath, injection + rscCode);
|
|
4313
4356
|
const totalKB = (totalBytes / 1024).toFixed(1);
|
|
4314
4357
|
console.log(
|
|
4315
|
-
`[rsc-router] Wrote static assets (${totalKB} KB total, ${Object.keys(state.
|
|
4358
|
+
`[rsc-router] Wrote static assets (${totalKB} KB total, ${Object.keys(state.staticManifestEntries).length} entries)`
|
|
4316
4359
|
);
|
|
4317
4360
|
} catch (err) {
|
|
4318
4361
|
throw new Error(
|
|
@@ -4427,8 +4470,8 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
4427
4470
|
if (globalThis.__rscRouterDiscoveryActive) return;
|
|
4428
4471
|
s.devServer = server;
|
|
4429
4472
|
let resolveDiscovery;
|
|
4430
|
-
const discoveryPromise = new Promise((
|
|
4431
|
-
resolveDiscovery =
|
|
4473
|
+
const discoveryPromise = new Promise((resolve10) => {
|
|
4474
|
+
resolveDiscovery = resolve10;
|
|
4432
4475
|
});
|
|
4433
4476
|
const getDevServerOrigin = () => server.resolvedUrls?.local?.[0]?.replace(/\/$/, "") || `http://localhost:${server.config.server.port || 5173}`;
|
|
4434
4477
|
let prerenderTempServer = null;
|
|
@@ -4503,8 +4546,8 @@ ${err.stack}`
|
|
|
4503
4546
|
resolveDiscovery();
|
|
4504
4547
|
}
|
|
4505
4548
|
};
|
|
4506
|
-
s.discoveryDone = new Promise((
|
|
4507
|
-
setTimeout(() => discover().then(
|
|
4549
|
+
s.discoveryDone = new Promise((resolve10) => {
|
|
4550
|
+
setTimeout(() => discover().then(resolve10, resolve10), 0);
|
|
4508
4551
|
});
|
|
4509
4552
|
let mainRegistry = null;
|
|
4510
4553
|
const propagateDiscoveryState = async (rscEnv) => {
|
|
@@ -4673,7 +4716,7 @@ ${err.stack}`
|
|
|
4673
4716
|
if (hasCreateRouter) {
|
|
4674
4717
|
const nestedRouterConflict = findNestedRouterConflict([
|
|
4675
4718
|
...s.cachedRouterFiles ?? [],
|
|
4676
|
-
|
|
4719
|
+
resolve8(filePath)
|
|
4677
4720
|
]);
|
|
4678
4721
|
if (nestedRouterConflict) {
|
|
4679
4722
|
server.config.logger.error(
|
|
@@ -4703,6 +4746,9 @@ ${err.stack}`
|
|
|
4703
4746
|
async buildStart() {
|
|
4704
4747
|
if (!s.isBuildMode) return;
|
|
4705
4748
|
if (s.mergedRouteManifest !== null) return;
|
|
4749
|
+
resetStagedBuildAssets(s.projectRoot);
|
|
4750
|
+
s.prerenderManifestEntries = null;
|
|
4751
|
+
s.staticManifestEntries = null;
|
|
4706
4752
|
let tempServer = null;
|
|
4707
4753
|
globalThis.__rscRouterDiscoveryActive = true;
|
|
4708
4754
|
try {
|
|
@@ -4944,7 +4990,7 @@ async function rango(options) {
|
|
|
4944
4990
|
name: "@rangojs/router:auto-discover",
|
|
4945
4991
|
config(userConfig) {
|
|
4946
4992
|
if (routerRef.path) return;
|
|
4947
|
-
const root = userConfig.root ?
|
|
4993
|
+
const root = userConfig.root ? resolve9(process.cwd(), userConfig.root) : process.cwd();
|
|
4948
4994
|
const filter = createScanFilter(root, {
|
|
4949
4995
|
include: resolvedOptions.include,
|
|
4950
4996
|
exclude: resolvedOptions.exclude
|
package/package.json
CHANGED
package/skills/caching/SKILL.md
CHANGED
|
@@ -89,7 +89,7 @@ Configure a cache store in the router:
|
|
|
89
89
|
|
|
90
90
|
```typescript
|
|
91
91
|
import { createRouter } from "@rangojs/router";
|
|
92
|
-
import { MemorySegmentCacheStore } from "@rangojs/router/
|
|
92
|
+
import { MemorySegmentCacheStore } from "@rangojs/router/cache";
|
|
93
93
|
|
|
94
94
|
const store = new MemorySegmentCacheStore({
|
|
95
95
|
defaults: { ttl: 60, swr: 300 },
|
|
@@ -112,7 +112,7 @@ const router = createRouter({
|
|
|
112
112
|
For single-instance deployments:
|
|
113
113
|
|
|
114
114
|
```typescript
|
|
115
|
-
import { MemorySegmentCacheStore } from "@rangojs/router/
|
|
115
|
+
import { MemorySegmentCacheStore } from "@rangojs/router/cache";
|
|
116
116
|
|
|
117
117
|
const store = new MemorySegmentCacheStore({
|
|
118
118
|
defaults: { ttl: 60, swr: 300 },
|
|
@@ -125,7 +125,7 @@ const store = new MemorySegmentCacheStore({
|
|
|
125
125
|
For distributed caching on Cloudflare Workers:
|
|
126
126
|
|
|
127
127
|
```typescript
|
|
128
|
-
import { CFCacheStore } from "@rangojs/router/cache
|
|
128
|
+
import { CFCacheStore } from "@rangojs/router/cache";
|
|
129
129
|
|
|
130
130
|
const router = createRouter<AppBindings>({
|
|
131
131
|
document: Document,
|
|
@@ -175,7 +175,7 @@ cache({ store: checkoutCache }, () => [
|
|
|
175
175
|
|
|
176
176
|
```typescript
|
|
177
177
|
import { urls } from "@rangojs/router";
|
|
178
|
-
import { MemorySegmentCacheStore } from "@rangojs/router/
|
|
178
|
+
import { MemorySegmentCacheStore } from "@rangojs/router/cache";
|
|
179
179
|
|
|
180
180
|
// Custom store for checkout (short TTL)
|
|
181
181
|
const checkoutCache = new MemorySegmentCacheStore({
|
|
@@ -14,7 +14,7 @@ Configure document cache in router:
|
|
|
14
14
|
|
|
15
15
|
```typescript
|
|
16
16
|
import { createRouter } from "@rangojs/router";
|
|
17
|
-
import { CFCacheStore } from "@rangojs/router/cache
|
|
17
|
+
import { CFCacheStore } from "@rangojs/router/cache";
|
|
18
18
|
import { urlpatterns } from "./urls";
|
|
19
19
|
|
|
20
20
|
const router = createRouter<AppBindings>({
|
|
@@ -134,7 +134,7 @@ Segment hash ensures different cached responses for navigations from different s
|
|
|
134
134
|
```typescript
|
|
135
135
|
// router.tsx
|
|
136
136
|
import { createRouter } from "@rangojs/router";
|
|
137
|
-
import { CFCacheStore } from "@rangojs/router/cache
|
|
137
|
+
import { CFCacheStore } from "@rangojs/router/cache";
|
|
138
138
|
import { urlpatterns } from "./urls";
|
|
139
139
|
|
|
140
140
|
const router = createRouter<AppBindings>({
|