@rangojs/router 0.0.0-experimental.002d056c
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/AGENTS.md +9 -0
- package/README.md +899 -0
- package/dist/bin/rango.js +1606 -0
- package/dist/vite/index.js +5153 -0
- package/package.json +177 -0
- package/skills/breadcrumbs/SKILL.md +250 -0
- package/skills/cache-guide/SKILL.md +262 -0
- package/skills/caching/SKILL.md +253 -0
- package/skills/composability/SKILL.md +172 -0
- package/skills/debug-manifest/SKILL.md +112 -0
- package/skills/document-cache/SKILL.md +182 -0
- package/skills/fonts/SKILL.md +167 -0
- package/skills/hooks/SKILL.md +704 -0
- package/skills/host-router/SKILL.md +218 -0
- package/skills/intercept/SKILL.md +313 -0
- package/skills/layout/SKILL.md +310 -0
- package/skills/links/SKILL.md +239 -0
- package/skills/loader/SKILL.md +596 -0
- package/skills/middleware/SKILL.md +339 -0
- package/skills/mime-routes/SKILL.md +128 -0
- package/skills/parallel/SKILL.md +305 -0
- package/skills/prerender/SKILL.md +643 -0
- package/skills/rango/SKILL.md +118 -0
- package/skills/response-routes/SKILL.md +411 -0
- package/skills/route/SKILL.md +385 -0
- package/skills/router-setup/SKILL.md +439 -0
- package/skills/tailwind/SKILL.md +129 -0
- package/skills/theme/SKILL.md +79 -0
- package/skills/typesafety/SKILL.md +623 -0
- package/skills/use-cache/SKILL.md +324 -0
- package/src/__internal.ts +273 -0
- package/src/bin/rango.ts +321 -0
- package/src/browser/action-coordinator.ts +97 -0
- package/src/browser/action-response-classifier.ts +99 -0
- package/src/browser/event-controller.ts +899 -0
- package/src/browser/history-state.ts +80 -0
- package/src/browser/index.ts +18 -0
- package/src/browser/intercept-utils.ts +52 -0
- package/src/browser/link-interceptor.ts +141 -0
- package/src/browser/logging.ts +55 -0
- package/src/browser/merge-segment-loaders.ts +134 -0
- package/src/browser/navigation-bridge.ts +638 -0
- package/src/browser/navigation-client.ts +261 -0
- package/src/browser/navigation-store.ts +806 -0
- package/src/browser/navigation-transaction.ts +297 -0
- package/src/browser/network-error-handler.ts +61 -0
- package/src/browser/partial-update.ts +582 -0
- package/src/browser/prefetch/cache.ts +206 -0
- package/src/browser/prefetch/fetch.ts +145 -0
- package/src/browser/prefetch/observer.ts +65 -0
- package/src/browser/prefetch/policy.ts +48 -0
- package/src/browser/prefetch/queue.ts +128 -0
- package/src/browser/rango-state.ts +112 -0
- package/src/browser/react/Link.tsx +368 -0
- package/src/browser/react/NavigationProvider.tsx +413 -0
- package/src/browser/react/ScrollRestoration.tsx +94 -0
- package/src/browser/react/context.ts +59 -0
- package/src/browser/react/filter-segment-order.ts +11 -0
- package/src/browser/react/index.ts +52 -0
- package/src/browser/react/location-state-shared.ts +162 -0
- package/src/browser/react/location-state.ts +107 -0
- package/src/browser/react/mount-context.ts +37 -0
- package/src/browser/react/nonce-context.ts +23 -0
- package/src/browser/react/shallow-equal.ts +27 -0
- package/src/browser/react/use-action.ts +218 -0
- package/src/browser/react/use-client-cache.ts +58 -0
- package/src/browser/react/use-handle.ts +162 -0
- package/src/browser/react/use-href.tsx +40 -0
- package/src/browser/react/use-link-status.ts +135 -0
- package/src/browser/react/use-mount.ts +31 -0
- package/src/browser/react/use-navigation.ts +99 -0
- package/src/browser/react/use-params.ts +65 -0
- package/src/browser/react/use-pathname.ts +47 -0
- package/src/browser/react/use-router.ts +63 -0
- package/src/browser/react/use-search-params.ts +56 -0
- package/src/browser/react/use-segments.ts +171 -0
- package/src/browser/response-adapter.ts +73 -0
- package/src/browser/rsc-router.tsx +464 -0
- package/src/browser/scroll-restoration.ts +397 -0
- package/src/browser/segment-reconciler.ts +216 -0
- package/src/browser/segment-structure-assert.ts +83 -0
- package/src/browser/server-action-bridge.ts +667 -0
- package/src/browser/shallow.ts +40 -0
- package/src/browser/types.ts +547 -0
- package/src/browser/validate-redirect-origin.ts +29 -0
- package/src/build/generate-manifest.ts +438 -0
- package/src/build/generate-route-types.ts +36 -0
- package/src/build/index.ts +35 -0
- package/src/build/route-trie.ts +265 -0
- package/src/build/route-types/ast-helpers.ts +25 -0
- package/src/build/route-types/ast-route-extraction.ts +98 -0
- package/src/build/route-types/codegen.ts +102 -0
- package/src/build/route-types/include-resolution.ts +411 -0
- package/src/build/route-types/param-extraction.ts +48 -0
- package/src/build/route-types/per-module-writer.ts +128 -0
- package/src/build/route-types/router-processing.ts +479 -0
- package/src/build/route-types/scan-filter.ts +78 -0
- package/src/build/runtime-discovery.ts +231 -0
- package/src/cache/background-task.ts +34 -0
- package/src/cache/cache-key-utils.ts +44 -0
- package/src/cache/cache-policy.ts +125 -0
- package/src/cache/cache-runtime.ts +338 -0
- package/src/cache/cache-scope.ts +382 -0
- package/src/cache/cf/cf-cache-store.ts +982 -0
- package/src/cache/cf/index.ts +29 -0
- package/src/cache/document-cache.ts +369 -0
- package/src/cache/handle-capture.ts +81 -0
- package/src/cache/handle-snapshot.ts +41 -0
- package/src/cache/index.ts +44 -0
- package/src/cache/memory-segment-store.ts +328 -0
- package/src/cache/profile-registry.ts +73 -0
- package/src/cache/read-through-swr.ts +134 -0
- package/src/cache/segment-codec.ts +256 -0
- package/src/cache/taint.ts +98 -0
- package/src/cache/types.ts +342 -0
- package/src/client.rsc.tsx +85 -0
- package/src/client.tsx +601 -0
- package/src/component-utils.ts +76 -0
- package/src/components/DefaultDocument.tsx +27 -0
- package/src/context-var.ts +86 -0
- package/src/debug.ts +243 -0
- package/src/default-error-boundary.tsx +88 -0
- package/src/deps/browser.ts +8 -0
- package/src/deps/html-stream-client.ts +2 -0
- package/src/deps/html-stream-server.ts +2 -0
- package/src/deps/rsc.ts +10 -0
- package/src/deps/ssr.ts +2 -0
- package/src/errors.ts +365 -0
- package/src/handle.ts +135 -0
- package/src/handles/MetaTags.tsx +246 -0
- package/src/handles/breadcrumbs.ts +66 -0
- package/src/handles/index.ts +7 -0
- package/src/handles/meta.ts +264 -0
- package/src/host/cookie-handler.ts +165 -0
- package/src/host/errors.ts +97 -0
- package/src/host/index.ts +53 -0
- package/src/host/pattern-matcher.ts +214 -0
- package/src/host/router.ts +352 -0
- package/src/host/testing.ts +79 -0
- package/src/host/types.ts +146 -0
- package/src/host/utils.ts +25 -0
- package/src/href-client.ts +222 -0
- package/src/index.rsc.ts +233 -0
- package/src/index.ts +277 -0
- package/src/internal-debug.ts +11 -0
- package/src/loader.rsc.ts +89 -0
- package/src/loader.ts +64 -0
- package/src/network-error-thrower.tsx +23 -0
- package/src/outlet-context.ts +15 -0
- package/src/outlet-provider.tsx +45 -0
- package/src/prerender/param-hash.ts +37 -0
- package/src/prerender/store.ts +185 -0
- package/src/prerender.ts +463 -0
- package/src/reverse.ts +330 -0
- package/src/root-error-boundary.tsx +289 -0
- package/src/route-content-wrapper.tsx +196 -0
- package/src/route-definition/dsl-helpers.ts +934 -0
- package/src/route-definition/helper-factories.ts +200 -0
- package/src/route-definition/helpers-types.ts +430 -0
- package/src/route-definition/index.ts +52 -0
- package/src/route-definition/redirect.ts +93 -0
- package/src/route-definition.ts +1 -0
- package/src/route-map-builder.ts +281 -0
- package/src/route-name.ts +53 -0
- package/src/route-types.ts +259 -0
- package/src/router/content-negotiation.ts +116 -0
- package/src/router/debug-manifest.ts +72 -0
- package/src/router/error-handling.ts +287 -0
- package/src/router/find-match.ts +160 -0
- package/src/router/handler-context.ts +451 -0
- package/src/router/intercept-resolution.ts +397 -0
- package/src/router/lazy-includes.ts +236 -0
- package/src/router/loader-resolution.ts +420 -0
- package/src/router/logging.ts +251 -0
- package/src/router/manifest.ts +269 -0
- package/src/router/match-api.ts +620 -0
- package/src/router/match-context.ts +266 -0
- package/src/router/match-handlers.ts +440 -0
- package/src/router/match-middleware/background-revalidation.ts +223 -0
- package/src/router/match-middleware/cache-lookup.ts +634 -0
- package/src/router/match-middleware/cache-store.ts +295 -0
- package/src/router/match-middleware/index.ts +81 -0
- package/src/router/match-middleware/intercept-resolution.ts +306 -0
- package/src/router/match-middleware/segment-resolution.ts +193 -0
- package/src/router/match-pipelines.ts +179 -0
- package/src/router/match-result.ts +219 -0
- package/src/router/metrics.ts +282 -0
- package/src/router/middleware-cookies.ts +55 -0
- package/src/router/middleware-types.ts +222 -0
- package/src/router/middleware.ts +749 -0
- package/src/router/pattern-matching.ts +563 -0
- package/src/router/prerender-match.ts +402 -0
- package/src/router/preview-match.ts +170 -0
- package/src/router/revalidation.ts +289 -0
- package/src/router/router-context.ts +320 -0
- package/src/router/router-interfaces.ts +452 -0
- package/src/router/router-options.ts +592 -0
- package/src/router/router-registry.ts +24 -0
- package/src/router/segment-resolution/fresh.ts +570 -0
- package/src/router/segment-resolution/helpers.ts +263 -0
- package/src/router/segment-resolution/loader-cache.ts +198 -0
- package/src/router/segment-resolution/revalidation.ts +1242 -0
- package/src/router/segment-resolution/static-store.ts +67 -0
- package/src/router/segment-resolution.ts +21 -0
- package/src/router/segment-wrappers.ts +291 -0
- package/src/router/telemetry-otel.ts +299 -0
- package/src/router/telemetry.ts +300 -0
- package/src/router/timeout.ts +148 -0
- package/src/router/trie-matching.ts +239 -0
- package/src/router/types.ts +170 -0
- package/src/router.ts +1006 -0
- package/src/rsc/handler-context.ts +45 -0
- package/src/rsc/handler.ts +1089 -0
- package/src/rsc/helpers.ts +198 -0
- package/src/rsc/index.ts +36 -0
- package/src/rsc/loader-fetch.ts +209 -0
- package/src/rsc/manifest-init.ts +86 -0
- package/src/rsc/nonce.ts +32 -0
- package/src/rsc/origin-guard.ts +141 -0
- package/src/rsc/progressive-enhancement.ts +379 -0
- package/src/rsc/response-error.ts +37 -0
- package/src/rsc/response-route-handler.ts +347 -0
- package/src/rsc/rsc-rendering.ts +237 -0
- package/src/rsc/runtime-warnings.ts +42 -0
- package/src/rsc/server-action.ts +348 -0
- package/src/rsc/ssr-setup.ts +128 -0
- package/src/rsc/types.ts +263 -0
- package/src/search-params.ts +230 -0
- package/src/segment-system.tsx +454 -0
- package/src/server/context.ts +591 -0
- package/src/server/cookie-store.ts +190 -0
- package/src/server/fetchable-loader-store.ts +37 -0
- package/src/server/handle-store.ts +308 -0
- package/src/server/loader-registry.ts +133 -0
- package/src/server/request-context.ts +920 -0
- package/src/server/root-layout.tsx +10 -0
- package/src/server/tsconfig.json +14 -0
- package/src/server.ts +51 -0
- package/src/ssr/index.tsx +365 -0
- package/src/static-handler.ts +114 -0
- package/src/theme/ThemeProvider.tsx +297 -0
- package/src/theme/ThemeScript.tsx +61 -0
- package/src/theme/constants.ts +62 -0
- package/src/theme/index.ts +48 -0
- package/src/theme/theme-context.ts +44 -0
- package/src/theme/theme-script.ts +155 -0
- package/src/theme/types.ts +182 -0
- package/src/theme/use-theme.ts +44 -0
- package/src/types/boundaries.ts +158 -0
- package/src/types/cache-types.ts +198 -0
- package/src/types/error-types.ts +192 -0
- package/src/types/global-namespace.ts +100 -0
- package/src/types/handler-context.ts +687 -0
- package/src/types/index.ts +88 -0
- package/src/types/loader-types.ts +183 -0
- package/src/types/route-config.ts +170 -0
- package/src/types/route-entry.ts +109 -0
- package/src/types/segments.ts +148 -0
- package/src/types.ts +1 -0
- package/src/urls/include-helper.ts +197 -0
- package/src/urls/index.ts +53 -0
- package/src/urls/path-helper-types.ts +339 -0
- package/src/urls/path-helper.ts +329 -0
- package/src/urls/pattern-types.ts +95 -0
- package/src/urls/response-types.ts +106 -0
- package/src/urls/type-extraction.ts +372 -0
- package/src/urls/urls-function.ts +98 -0
- package/src/urls.ts +1 -0
- package/src/use-loader.tsx +354 -0
- package/src/vite/discovery/bundle-postprocess.ts +184 -0
- package/src/vite/discovery/discover-routers.ts +344 -0
- package/src/vite/discovery/prerender-collection.ts +385 -0
- package/src/vite/discovery/route-types-writer.ts +258 -0
- package/src/vite/discovery/self-gen-tracking.ts +47 -0
- package/src/vite/discovery/state.ts +108 -0
- package/src/vite/discovery/virtual-module-codegen.ts +203 -0
- package/src/vite/index.ts +16 -0
- package/src/vite/plugin-types.ts +48 -0
- package/src/vite/plugins/cjs-to-esm.ts +93 -0
- package/src/vite/plugins/client-ref-dedup.ts +115 -0
- package/src/vite/plugins/client-ref-hashing.ts +105 -0
- package/src/vite/plugins/expose-action-id.ts +363 -0
- package/src/vite/plugins/expose-id-utils.ts +287 -0
- package/src/vite/plugins/expose-ids/export-analysis.ts +296 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +179 -0
- package/src/vite/plugins/expose-ids/loader-transform.ts +74 -0
- package/src/vite/plugins/expose-ids/router-transform.ts +110 -0
- package/src/vite/plugins/expose-ids/types.ts +45 -0
- package/src/vite/plugins/expose-internal-ids.ts +569 -0
- package/src/vite/plugins/refresh-cmd.ts +65 -0
- package/src/vite/plugins/use-cache-transform.ts +323 -0
- package/src/vite/plugins/version-injector.ts +83 -0
- package/src/vite/plugins/version-plugin.ts +266 -0
- package/src/vite/plugins/version.d.ts +12 -0
- package/src/vite/plugins/virtual-entries.ts +123 -0
- package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
- package/src/vite/rango.ts +445 -0
- package/src/vite/router-discovery.ts +777 -0
- package/src/vite/utils/ast-handler-extract.ts +517 -0
- package/src/vite/utils/banner.ts +36 -0
- package/src/vite/utils/bundle-analysis.ts +137 -0
- package/src/vite/utils/manifest-utils.ts +70 -0
- package/src/vite/utils/package-resolution.ts +121 -0
- package/src/vite/utils/prerender-utils.ts +189 -0
- package/src/vite/utils/shared-utils.ts +169 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: use-cache
|
|
3
|
+
description: Function-level caching with "use cache" directive for RSC data functions and components
|
|
4
|
+
argument-hint: [profile-name]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# "use cache" Directive
|
|
8
|
+
|
|
9
|
+
Function-level caching for async server functions and RSC components. Caches
|
|
10
|
+
return values with TTL + stale-while-revalidate. Complementary to the route-level
|
|
11
|
+
`cache()` DSL and build-time `Static()`/`Prerender()`.
|
|
12
|
+
|
|
13
|
+
## Basic Usage
|
|
14
|
+
|
|
15
|
+
### File-level (all exports cached with default profile)
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
"use cache";
|
|
19
|
+
|
|
20
|
+
export async function getProducts() {
|
|
21
|
+
return await db.query("SELECT * FROM products");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function getCategories() {
|
|
25
|
+
return await db.query("SELECT * FROM categories");
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Function-level (per-function profile)
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
export async function getProducts() {
|
|
33
|
+
"use cache: short";
|
|
34
|
+
return await db.query("SELECT * FROM products");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function getCategories() {
|
|
38
|
+
"use cache: long";
|
|
39
|
+
return await db.query("SELECT * FROM categories");
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### RSC component
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
export async function ProductCard({ id }: { id: string }) {
|
|
47
|
+
"use cache: products"
|
|
48
|
+
const product = await db.query('SELECT * FROM products WHERE id = ?', [id]);
|
|
49
|
+
return <div>{product.name}</div>;
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Named Cache Profiles
|
|
54
|
+
|
|
55
|
+
Define profiles in createRouter. Profile names map to `"use cache: <name>"` and
|
|
56
|
+
`cache('<name>')` in the DSL.
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
createRouter({
|
|
60
|
+
cacheProfiles: {
|
|
61
|
+
default: { ttl: 900, swr: 1800 },
|
|
62
|
+
short: { ttl: 60, swr: 120 },
|
|
63
|
+
long: { ttl: 3600, swr: 7200 },
|
|
64
|
+
products: { ttl: 300, swr: 600, tags: ["products"] },
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
- `"use cache"` (no name) resolves to `default`.
|
|
70
|
+
- `"use cache: short"` resolves to the `short` profile.
|
|
71
|
+
- Unknown profile names throw at build/boot time.
|
|
72
|
+
|
|
73
|
+
## Cache Key
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
use-cache:{functionId}:{serializedArgs}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- `functionId` -- stable ID from Vite transform (module path + export name).
|
|
80
|
+
- `serializedArgs` -- non-tainted arguments serialized via RSC `encodeReply()`.
|
|
81
|
+
|
|
82
|
+
Different functions always produce different cache keys, even for the same route.
|
|
83
|
+
This is important for intercepted routes -- the path handler and intercept handler
|
|
84
|
+
each have their own `functionId` and therefore their own cache entries.
|
|
85
|
+
|
|
86
|
+
## Tainted Arguments (ctx, env, req)
|
|
87
|
+
|
|
88
|
+
Request-scoped objects are branded with `Symbol.for('rango:nocache')` at creation.
|
|
89
|
+
When detected:
|
|
90
|
+
|
|
91
|
+
1. **Excluded from cache key** -- request-scoped, not meaningful for keying.
|
|
92
|
+
2. **Handle data captured on miss** -- side effects via `ctx.use(Handle)` are recorded.
|
|
93
|
+
3. **Handle data replayed on hit** -- restored into the current request's HandleStore.
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
export async function getProductData(ctx) {
|
|
97
|
+
"use cache: short";
|
|
98
|
+
const breadcrumb = ctx.use(Breadcrumbs);
|
|
99
|
+
breadcrumb({ label: "Products", href: "/products" });
|
|
100
|
+
return await db.query("SELECT * FROM products");
|
|
101
|
+
}
|
|
102
|
+
// On hit: return value restored, breadcrumb replayed.
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Request-Scoped Guards
|
|
106
|
+
|
|
107
|
+
### Read Guards
|
|
108
|
+
|
|
109
|
+
`cookies()` and `headers()` **throw** inside a `"use cache"` function because
|
|
110
|
+
per-request values (cookies, headers) are not reflected in the cache key. Without
|
|
111
|
+
this guard, one user's data would be served to another.
|
|
112
|
+
|
|
113
|
+
Extract the value before the cached function and pass it as an argument:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
const locale = cookies().get("locale")?.value ?? "en";
|
|
117
|
+
const data = await getCachedData(locale); // locale is now in the cache key
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Side-Effect Guards
|
|
121
|
+
|
|
122
|
+
These ctx methods **throw** inside a `"use cache"` function because their effects
|
|
123
|
+
are lost on cache hit (the function body is skipped):
|
|
124
|
+
|
|
125
|
+
- `ctx.set()` / `ctx.get()` for passing values to children
|
|
126
|
+
- `ctx.header()`
|
|
127
|
+
- `ctx.setTheme()`
|
|
128
|
+
- `ctx.setLocationState()`
|
|
129
|
+
- `ctx.onResponse()`
|
|
130
|
+
|
|
131
|
+
The error message recommends two alternatives:
|
|
132
|
+
|
|
133
|
+
1. Extract the data fetch into a separate cached function and call ctx methods outside it.
|
|
134
|
+
2. Use the route-level `cache()` DSL which caches all segments together.
|
|
135
|
+
|
|
136
|
+
**`ctx.use(Handle)` is NOT guarded** -- handle push is captured on miss and replayed
|
|
137
|
+
on hit. This is the correct way to pass data from cached functions.
|
|
138
|
+
|
|
139
|
+
### Pattern: Separate cached function from ctx side effects
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
// Cached data fetch (pure)
|
|
143
|
+
async function getNavData() {
|
|
144
|
+
"use cache: short"
|
|
145
|
+
return await db.query('SELECT * FROM nav_items');
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Handler (uncached, calls ctx methods freely)
|
|
149
|
+
async function NavLayout(ctx) {
|
|
150
|
+
const navData = await getNavData();
|
|
151
|
+
ctx.set("navItems", navData); // Works -- outside "use cache"
|
|
152
|
+
return <Nav items={navData}><Outlet /></Nav>;
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Misuse Guards
|
|
157
|
+
|
|
158
|
+
### Cannot use as middleware
|
|
159
|
+
|
|
160
|
+
Cached functions cannot be passed to `middleware()`. Middleware runs on every
|
|
161
|
+
request (onion model) and must not be cached.
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
// WRONG -- throws at boot time
|
|
165
|
+
middleware(cachedFn);
|
|
166
|
+
|
|
167
|
+
// RIGHT -- call cached function inside middleware
|
|
168
|
+
middleware(async (ctx, next) => {
|
|
169
|
+
const data = await getCachedData();
|
|
170
|
+
ctx.set("data", data);
|
|
171
|
+
await next();
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Cannot use as Static() handler
|
|
176
|
+
|
|
177
|
+
Static handlers render once at build time. `"use cache"` is redundant.
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
// WRONG -- throws at boot time
|
|
181
|
+
export const Page = Static(cachedFn);
|
|
182
|
+
|
|
183
|
+
// RIGHT -- remove "use cache", Static already caches
|
|
184
|
+
export const Page = Static(async (ctx) => {
|
|
185
|
+
return <div>Built once</div>;
|
|
186
|
+
});
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Cannot use as Prerender() handler or getParams
|
|
190
|
+
|
|
191
|
+
Prerender handlers render at build time. `"use cache"` is redundant.
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
// WRONG -- throws at boot time (handler)
|
|
195
|
+
export const Page = Prerender(getParams, cachedFn);
|
|
196
|
+
|
|
197
|
+
// WRONG -- throws at boot time (getParams)
|
|
198
|
+
export const Page = Prerender(cachedGetParams, handler);
|
|
199
|
+
|
|
200
|
+
// RIGHT -- remove "use cache"
|
|
201
|
+
export const Page = Prerender(
|
|
202
|
+
async () => [{ slug: "a" }],
|
|
203
|
+
async (ctx) => <Page slug={ctx.params.slug} />,
|
|
204
|
+
);
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Performance: waitUntil
|
|
208
|
+
|
|
209
|
+
On cache miss, the function executes and the result is serialized inline (blocking).
|
|
210
|
+
The cache **store write** (`setItem`) is deferred to `waitUntil` and does NOT block
|
|
211
|
+
the response.
|
|
212
|
+
|
|
213
|
+
On stale hit, stale data is returned immediately. Background revalidation (re-execute
|
|
214
|
+
|
|
215
|
+
- store) runs entirely inside `waitUntil`.
|
|
216
|
+
|
|
217
|
+
| Phase | Blocks response? |
|
|
218
|
+
| ------------------------------------ | ---------------- |
|
|
219
|
+
| Function execution (miss) | Yes |
|
|
220
|
+
| Result serialization (miss) | Yes |
|
|
221
|
+
| Cache store write (miss) | No (waitUntil) |
|
|
222
|
+
| Stale value return (stale hit) | No (immediate) |
|
|
223
|
+
| Background revalidation (stale) | No (waitUntil) |
|
|
224
|
+
| Cache lookup + deserialization (hit) | Yes (fast) |
|
|
225
|
+
|
|
226
|
+
## Using with Loaders
|
|
227
|
+
|
|
228
|
+
`"use cache"` works inside loaders. The loader runs every request, but the inner
|
|
229
|
+
cached function returns cached data:
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
// Cached data function
|
|
233
|
+
export async function getProductData(slug: string) {
|
|
234
|
+
"use cache";
|
|
235
|
+
return await db.query("SELECT * FROM products WHERE slug = ?", [slug]);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Loader runs every request, but inner call is cached
|
|
239
|
+
export const ProductLoader = createLoader(async (ctx) => {
|
|
240
|
+
return getProductData(ctx.params.slug);
|
|
241
|
+
});
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Using with Intercepted Routes
|
|
245
|
+
|
|
246
|
+
Path handlers and intercept handlers have different `functionId` values from the
|
|
247
|
+
Vite transform, so they naturally get distinct cache entries even for the same URL:
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
// Path handler -- cached separately
|
|
251
|
+
path("/product/:id", async (ctx) => {
|
|
252
|
+
"use cache"
|
|
253
|
+
return <FullProductPage id={ctx.params.id} />;
|
|
254
|
+
}),
|
|
255
|
+
|
|
256
|
+
// Intercept handler -- cached separately (different functionId)
|
|
257
|
+
intercept("@modal", ".product", async (ctx) => {
|
|
258
|
+
"use cache"
|
|
259
|
+
return <ProductModal id={ctx.params.id} />;
|
|
260
|
+
}),
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Vite Transform
|
|
264
|
+
|
|
265
|
+
The `rango:use-cache` Vite plugin detects the directive and wraps exports with
|
|
266
|
+
`registerCachedFunction()`:
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
// Input
|
|
270
|
+
"use cache"
|
|
271
|
+
export async function getProducts() { ... }
|
|
272
|
+
|
|
273
|
+
// Output
|
|
274
|
+
import { registerCachedFunction } from '@rangojs/router/cache-runtime';
|
|
275
|
+
export const getProducts = registerCachedFunction(
|
|
276
|
+
async function getProducts() { ... },
|
|
277
|
+
"src/data/products.ts#getProducts",
|
|
278
|
+
"default"
|
|
279
|
+
);
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Function-level directives are hoisted:
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
// Input
|
|
286
|
+
export async function getProducts() {
|
|
287
|
+
"use cache: short";
|
|
288
|
+
return await db.query("...");
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Output
|
|
292
|
+
const __rango_cached_getProducts = registerCachedFunction(
|
|
293
|
+
async function getProducts() {
|
|
294
|
+
return await db.query("...");
|
|
295
|
+
},
|
|
296
|
+
"src/data/products.ts#getProducts",
|
|
297
|
+
"short",
|
|
298
|
+
);
|
|
299
|
+
export async function getProducts() {
|
|
300
|
+
return __rango_cached_getProducts();
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Backing Store
|
|
305
|
+
|
|
306
|
+
Writes to the same `SegmentCacheStore` as `cache()` DSL, `Static()`, and `Prerender()`.
|
|
307
|
+
One store, one configuration, one invalidation API. Tag-based invalidation
|
|
308
|
+
(`revalidateTag`) works across all mechanisms.
|
|
309
|
+
|
|
310
|
+
## Interaction with Other Caching
|
|
311
|
+
|
|
312
|
+
| Mechanism | Granularity | When | Use case |
|
|
313
|
+
| ------------------ | ------------------ | ---------- | ----------------------------------------------- |
|
|
314
|
+
| `"use cache"` | Function/component | Runtime | Cache individual data fetches or components |
|
|
315
|
+
| `cache()` DSL | Route segment | Runtime | Cache entire route subtrees with children |
|
|
316
|
+
| `cache('profile')` | Route segment | Runtime | Same as cache() with a named profile |
|
|
317
|
+
| `Static()` | Route segment | Build-time | Render once, never re-render |
|
|
318
|
+
| `Prerender()` | Route segment | Build-time | Pre-render known params, optional live fallback |
|
|
319
|
+
|
|
320
|
+
## Dev Mode
|
|
321
|
+
|
|
322
|
+
In development, the Vite transform still wraps functions, but the cache store is
|
|
323
|
+
a `MemorySegmentCacheStore` that works locally. Functions cache normally in dev
|
|
324
|
+
for testing cache behavior.
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal Types - Implementation Details
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
* These types are for internal use only and should not be relied upon by consumers.
|
|
6
|
+
* They may change without notice between versions.
|
|
7
|
+
*
|
|
8
|
+
* If you find yourself needing these types, please open an issue to discuss
|
|
9
|
+
* adding them to the public API.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Segment Resolution (Internal)
|
|
14
|
+
// ============================================================================
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @internal
|
|
18
|
+
* Internal representation of a resolved route segment.
|
|
19
|
+
* Used during route matching and rendering pipeline.
|
|
20
|
+
*/
|
|
21
|
+
export type { ResolvedSegment, SegmentMetadata } from "./types.js";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @internal
|
|
25
|
+
* Internal match result from route resolution.
|
|
26
|
+
*/
|
|
27
|
+
export type { MatchResult, SlotState } from "./types.js";
|
|
28
|
+
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// Intercept System (Internal)
|
|
31
|
+
// ============================================================================
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @internal
|
|
35
|
+
* Context for intercept route selection.
|
|
36
|
+
*/
|
|
37
|
+
export type {
|
|
38
|
+
InterceptSelectorContext,
|
|
39
|
+
InterceptSegmentsState,
|
|
40
|
+
InterceptWhenFn,
|
|
41
|
+
} from "./server/context.js";
|
|
42
|
+
|
|
43
|
+
// ============================================================================
|
|
44
|
+
// Browser State (Internal)
|
|
45
|
+
// ============================================================================
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @internal
|
|
49
|
+
* RSC protocol payload structure.
|
|
50
|
+
*/
|
|
51
|
+
export type { RscPayload, ReactFormState } from "./rsc/types.js";
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @internal
|
|
55
|
+
* Internal navigation store interface.
|
|
56
|
+
*/
|
|
57
|
+
export type {
|
|
58
|
+
NavigationStore,
|
|
59
|
+
NavigationBridge,
|
|
60
|
+
RscMetadata,
|
|
61
|
+
ActionResult,
|
|
62
|
+
InflightAction,
|
|
63
|
+
NavigationState,
|
|
64
|
+
TrackedActionState,
|
|
65
|
+
ActionStateListener,
|
|
66
|
+
SegmentCache,
|
|
67
|
+
SegmentState,
|
|
68
|
+
NavigationUpdate,
|
|
69
|
+
} from "./browser/types.js";
|
|
70
|
+
|
|
71
|
+
// ============================================================================
|
|
72
|
+
// Handle System (Internal)
|
|
73
|
+
// ============================================================================
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @internal
|
|
77
|
+
* Internal handle storage mechanism.
|
|
78
|
+
*/
|
|
79
|
+
export type { HandleStore, HandleData } from "./server/handle-store.js";
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @internal
|
|
83
|
+
* Segment handle data in cache.
|
|
84
|
+
*/
|
|
85
|
+
export type { SegmentHandleData } from "./cache/types.js";
|
|
86
|
+
|
|
87
|
+
// ============================================================================
|
|
88
|
+
// Cache Internals
|
|
89
|
+
// ============================================================================
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @internal
|
|
93
|
+
* Internal cache entry data structure.
|
|
94
|
+
*/
|
|
95
|
+
export type {
|
|
96
|
+
CachedEntryData,
|
|
97
|
+
CachedEntryResult,
|
|
98
|
+
CacheGetResult,
|
|
99
|
+
SerializedSegmentData,
|
|
100
|
+
CacheDefaults,
|
|
101
|
+
} from "./cache/types.js";
|
|
102
|
+
|
|
103
|
+
// ============================================================================
|
|
104
|
+
// Router Context (Internal)
|
|
105
|
+
// ============================================================================
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @internal
|
|
109
|
+
* Router context for AsyncLocalStorage.
|
|
110
|
+
*/
|
|
111
|
+
export type {
|
|
112
|
+
RouterContext,
|
|
113
|
+
RevalidationContext,
|
|
114
|
+
InterceptResult,
|
|
115
|
+
} from "./router/router-context.js";
|
|
116
|
+
|
|
117
|
+
// ============================================================================
|
|
118
|
+
// Match Pipeline (Internal)
|
|
119
|
+
// ============================================================================
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @internal
|
|
123
|
+
* Route match context during pipeline processing.
|
|
124
|
+
*/
|
|
125
|
+
export type {
|
|
126
|
+
MatchContext,
|
|
127
|
+
MatchPipelineState,
|
|
128
|
+
} from "./router/match-context.js";
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* @internal
|
|
132
|
+
* Pattern matching result.
|
|
133
|
+
*/
|
|
134
|
+
export type { RouteMatchResult } from "./router/pattern-matching.js";
|
|
135
|
+
|
|
136
|
+
// ============================================================================
|
|
137
|
+
// Server Context (Internal)
|
|
138
|
+
// ============================================================================
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @internal
|
|
142
|
+
* Entry data during route traversal.
|
|
143
|
+
*/
|
|
144
|
+
export type {
|
|
145
|
+
EntryData,
|
|
146
|
+
InterceptEntry,
|
|
147
|
+
MetricsStore,
|
|
148
|
+
PerformanceMetric,
|
|
149
|
+
EntryCacheConfig,
|
|
150
|
+
EntryPropCommon,
|
|
151
|
+
EntryPropDatas,
|
|
152
|
+
LoaderEntry,
|
|
153
|
+
EntryPropSegments,
|
|
154
|
+
} from "./server/context.js";
|
|
155
|
+
|
|
156
|
+
// ============================================================================
|
|
157
|
+
// Handler Context (Internal)
|
|
158
|
+
// ============================================================================
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* @internal
|
|
162
|
+
* Internal handler context with additional props for router internals.
|
|
163
|
+
* Includes `_currentSegmentId` and `_responseType`.
|
|
164
|
+
*/
|
|
165
|
+
export type { InternalHandlerContext } from "./types.js";
|
|
166
|
+
|
|
167
|
+
// ============================================================================
|
|
168
|
+
// Rendering (Internal)
|
|
169
|
+
// ============================================================================
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* @internal
|
|
173
|
+
* Builds React element trees from route segments.
|
|
174
|
+
*/
|
|
175
|
+
export { renderSegments } from "./segment-system.js";
|
|
176
|
+
|
|
177
|
+
// ============================================================================
|
|
178
|
+
// Error Utilities (Internal)
|
|
179
|
+
// ============================================================================
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* @internal
|
|
183
|
+
* Error sanitization and network error utilities.
|
|
184
|
+
*/
|
|
185
|
+
export { sanitizeError, NetworkError, isNetworkError } from "./errors.js";
|
|
186
|
+
|
|
187
|
+
// ============================================================================
|
|
188
|
+
// Type Utilities (Internal)
|
|
189
|
+
// ============================================================================
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* @internal
|
|
193
|
+
* Scoped view of GeneratedRouteMap for Handler<"localName", ScopedRouteMap<"prefix">>.
|
|
194
|
+
*/
|
|
195
|
+
export type { ScopedRouteMap } from "./types.js";
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* @internal
|
|
199
|
+
* Type-level utilities for reverse URL generation.
|
|
200
|
+
*/
|
|
201
|
+
export type { MergeRoutes, SanitizePrefix } from "./reverse.js";
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* @internal
|
|
205
|
+
* Individual telemetry event types.
|
|
206
|
+
*/
|
|
207
|
+
export type {
|
|
208
|
+
RequestStartEvent,
|
|
209
|
+
RequestEndEvent,
|
|
210
|
+
RequestErrorEvent,
|
|
211
|
+
RequestTimeoutEvent,
|
|
212
|
+
LoaderStartEvent,
|
|
213
|
+
LoaderEndEvent,
|
|
214
|
+
LoaderErrorEvent,
|
|
215
|
+
HandlerErrorEvent,
|
|
216
|
+
CacheDecisionEvent,
|
|
217
|
+
RevalidationDecisionEvent,
|
|
218
|
+
} from "./router/telemetry.js";
|
|
219
|
+
|
|
220
|
+
// ============================================================================
|
|
221
|
+
// Pre-render / Static Handler Guards (Internal)
|
|
222
|
+
// ============================================================================
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* @internal
|
|
226
|
+
* Type guard for prerender handler definitions.
|
|
227
|
+
*/
|
|
228
|
+
export { isPrerenderHandler } from "./prerender.js";
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* @internal
|
|
232
|
+
* Type guard for static handler definitions.
|
|
233
|
+
*/
|
|
234
|
+
export { isStaticHandler } from "./static-handler.js";
|
|
235
|
+
|
|
236
|
+
// ============================================================================
|
|
237
|
+
// URL Pattern Internals
|
|
238
|
+
// ============================================================================
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* @internal
|
|
242
|
+
* Sentinel used to tag response-type route entries.
|
|
243
|
+
*/
|
|
244
|
+
export { RESPONSE_TYPE } from "./urls.js";
|
|
245
|
+
|
|
246
|
+
// ============================================================================
|
|
247
|
+
// Route Match Debug (Internal)
|
|
248
|
+
// ============================================================================
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* @internal
|
|
252
|
+
* Debug utilities for route matching performance analysis.
|
|
253
|
+
*/
|
|
254
|
+
export {
|
|
255
|
+
enableMatchDebug,
|
|
256
|
+
getMatchDebugStats,
|
|
257
|
+
} from "./router/pattern-matching.js";
|
|
258
|
+
|
|
259
|
+
// ============================================================================
|
|
260
|
+
// Debug Utilities (Internal)
|
|
261
|
+
// ============================================================================
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* @internal
|
|
265
|
+
* Debug utilities for manifest inspection and comparison.
|
|
266
|
+
*/
|
|
267
|
+
export {
|
|
268
|
+
serializeManifest,
|
|
269
|
+
compareManifests,
|
|
270
|
+
formatManifestDiff,
|
|
271
|
+
type SerializedEntry,
|
|
272
|
+
type SerializedManifest,
|
|
273
|
+
} from "./debug.js";
|