@rangojs/router 0.0.0-experimental.0f44aca1
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 +5 -0
- package/README.md +899 -0
- package/dist/bin/rango.js +1601 -0
- package/dist/vite/index.js +5214 -0
- package/package.json +176 -0
- package/skills/breadcrumbs/SKILL.md +250 -0
- package/skills/cache-guide/SKILL.md +262 -0
- package/skills/caching/SKILL.md +220 -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 +645 -0
- package/src/browser/navigation-client.ts +215 -0
- package/src/browser/navigation-store.ts +806 -0
- package/src/browser/navigation-transaction.ts +295 -0
- package/src/browser/network-error-handler.ts +61 -0
- package/src/browser/partial-update.ts +550 -0
- package/src/browser/prefetch/cache.ts +146 -0
- package/src/browser/prefetch/fetch.ts +135 -0
- package/src/browser/prefetch/observer.ts +65 -0
- package/src/browser/prefetch/policy.ts +42 -0
- package/src/browser/prefetch/queue.ts +88 -0
- package/src/browser/rango-state.ts +112 -0
- package/src/browser/react/Link.tsx +360 -0
- package/src/browser/react/NavigationProvider.tsx +386 -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 +431 -0
- package/src/browser/scroll-restoration.ts +400 -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 +538 -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 +469 -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 +540 -0
- package/src/cache/cf/index.ts +25 -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 +43 -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 +275 -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 +158 -0
- package/src/router/handler-context.ts +451 -0
- package/src/router/intercept-resolution.ts +395 -0
- package/src/router/lazy-includes.ts +234 -0
- package/src/router/loader-resolution.ts +420 -0
- package/src/router/logging.ts +248 -0
- package/src/router/manifest.ts +267 -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 +192 -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 +748 -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 +316 -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 +1239 -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 +289 -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 +1002 -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 +235 -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 +914 -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 +102 -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 +110 -0
- package/src/vite/discovery/virtual-module-codegen.ts +203 -0
- package/src/vite/index.ts +16 -0
- package/src/vite/plugin-types.ts +131 -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 +365 -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 +254 -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 +510 -0
- package/src/vite/router-discovery.ts +785 -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,220 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: caching
|
|
3
|
+
description: Configure segment caching with memory or Cloudflare KV stores in @rangojs/router
|
|
4
|
+
argument-hint: [setup]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Caching
|
|
8
|
+
|
|
9
|
+
@rangojs/router supports segment-level caching with stale-while-revalidate (SWR) for optimal performance.
|
|
10
|
+
|
|
11
|
+
## Route-Level Caching with cache()
|
|
12
|
+
|
|
13
|
+
Use the `cache()` DSL function to cache routes:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { urls } from "@rangojs/router";
|
|
17
|
+
|
|
18
|
+
export const urlpatterns = urls(({ path, cache }) => [
|
|
19
|
+
// Cache these routes for 60 seconds, SWR for 5 minutes
|
|
20
|
+
cache({ ttl: 60, swr: 300 }, () => [
|
|
21
|
+
path("/blog", BlogIndex, { name: "blog" }),
|
|
22
|
+
path("/blog/:slug", BlogPost, { name: "blogPost" }),
|
|
23
|
+
]),
|
|
24
|
+
|
|
25
|
+
// Uncached routes
|
|
26
|
+
path("/account", AccountPage, { name: "account" }),
|
|
27
|
+
]);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Cache Options
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
cache(
|
|
34
|
+
{
|
|
35
|
+
ttl: 60, // Time-to-live in seconds (default: 60)
|
|
36
|
+
swr: 300, // Stale-while-revalidate window (default: 300)
|
|
37
|
+
},
|
|
38
|
+
() => [
|
|
39
|
+
// Cached routes
|
|
40
|
+
],
|
|
41
|
+
);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Named Profile Shorthand
|
|
45
|
+
|
|
46
|
+
Use a named cache profile string instead of an options object. The profile must be
|
|
47
|
+
defined in `createRouter({ cacheProfiles })`. Unknown names throw at boot time.
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// Define profiles in router
|
|
51
|
+
createRouter({
|
|
52
|
+
cacheProfiles: {
|
|
53
|
+
default: { ttl: 900, swr: 1800 },
|
|
54
|
+
short: { ttl: 60, swr: 120 },
|
|
55
|
+
long: { ttl: 3600, swr: 7200 },
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Use by name in urls
|
|
60
|
+
export const urlpatterns = urls(({ path, cache }) => [
|
|
61
|
+
cache("long", () => [path("/blog", BlogIndex, { name: "blog" })]),
|
|
62
|
+
|
|
63
|
+
// Also works without children (orphan cache boundary)
|
|
64
|
+
cache("short"),
|
|
65
|
+
path("/feed", FeedPage, { name: "feed" }),
|
|
66
|
+
]);
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
These profile names are shared with the `"use cache: <name>"` directive. See
|
|
70
|
+
`/use-cache` for function-level caching.
|
|
71
|
+
|
|
72
|
+
## Loader-Level Caching
|
|
73
|
+
|
|
74
|
+
Cache individual loaders:
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
path("/product/:slug", ProductPage, { name: "product" }, () => [
|
|
78
|
+
// Cache this loader's results
|
|
79
|
+
loader(ProductLoader, () => [cache({ ttl: 300 })]),
|
|
80
|
+
|
|
81
|
+
// This loader is not cached
|
|
82
|
+
loader(CartLoader),
|
|
83
|
+
]);
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Global Cache Configuration
|
|
87
|
+
|
|
88
|
+
Configure a cache store in the router:
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
import { createRouter } from "@rangojs/router";
|
|
92
|
+
import { MemorySegmentCacheStore } from "@rangojs/router/cache";
|
|
93
|
+
|
|
94
|
+
const store = new MemorySegmentCacheStore({
|
|
95
|
+
defaults: { ttl: 60, swr: 300 },
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const router = createRouter({
|
|
99
|
+
document: Document,
|
|
100
|
+
urls: urlpatterns,
|
|
101
|
+
cache: {
|
|
102
|
+
store,
|
|
103
|
+
enabled: true,
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Cache Stores
|
|
109
|
+
|
|
110
|
+
### Memory Store
|
|
111
|
+
|
|
112
|
+
For single-instance deployments:
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import { MemorySegmentCacheStore } from "@rangojs/router/cache";
|
|
116
|
+
|
|
117
|
+
const store = new MemorySegmentCacheStore({
|
|
118
|
+
defaults: { ttl: 60, swr: 300 },
|
|
119
|
+
maxSize: 1000, // Max entries
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Cloudflare KV Store
|
|
124
|
+
|
|
125
|
+
For distributed caching on Cloudflare Workers:
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import { CFCacheStore } from "@rangojs/router/cache";
|
|
129
|
+
|
|
130
|
+
const router = createRouter<AppBindings>({
|
|
131
|
+
document: Document,
|
|
132
|
+
urls: urlpatterns,
|
|
133
|
+
cache: (env, ctx) => ({
|
|
134
|
+
store: new CFCacheStore({
|
|
135
|
+
kv: env.CACHE_KV,
|
|
136
|
+
waitUntil: (fn) => ctx!.waitUntil(fn),
|
|
137
|
+
}),
|
|
138
|
+
enabled: true,
|
|
139
|
+
}),
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Nested Cache Boundaries
|
|
144
|
+
|
|
145
|
+
Override cache settings for specific sections:
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
// Global cache
|
|
149
|
+
cache({ ttl: 300 }, () => [
|
|
150
|
+
path("/blog", BlogIndex, { name: "blog" }),
|
|
151
|
+
|
|
152
|
+
// Override: shorter TTL for dynamic content
|
|
153
|
+
cache({ ttl: 30 }, () => [
|
|
154
|
+
path("/blog/:slug", BlogPost, { name: "blogPost" }),
|
|
155
|
+
]),
|
|
156
|
+
]);
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Custom Cache Store
|
|
160
|
+
|
|
161
|
+
Create a dedicated store for specific routes:
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
const checkoutCache = new MemorySegmentCacheStore({
|
|
165
|
+
defaults: { ttl: 10 },
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// In urls
|
|
169
|
+
cache({ store: checkoutCache }, () => [
|
|
170
|
+
path("/checkout", CheckoutPage, { name: "checkout" }),
|
|
171
|
+
]);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Complete Example
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
import { urls } from "@rangojs/router";
|
|
178
|
+
import { MemorySegmentCacheStore } from "@rangojs/router/cache";
|
|
179
|
+
|
|
180
|
+
// Custom store for checkout (short TTL)
|
|
181
|
+
const checkoutCache = new MemorySegmentCacheStore({
|
|
182
|
+
defaults: { ttl: 10 },
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
export const urlpatterns = urls(({ path, layout, cache, loader, revalidate }) => [
|
|
186
|
+
// Public routes with aggressive caching
|
|
187
|
+
cache({ ttl: 300, swr: 600 }, () => [
|
|
188
|
+
path("/", HomePage, { name: "home" }),
|
|
189
|
+
path("/about", AboutPage, { name: "about" }),
|
|
190
|
+
]),
|
|
191
|
+
|
|
192
|
+
// Blog routes with moderate caching
|
|
193
|
+
cache({ ttl: 60, swr: 300 }, () => [
|
|
194
|
+
layout(<BlogLayout />, () => [
|
|
195
|
+
path("/blog", BlogIndex, { name: "blog" }),
|
|
196
|
+
path("/blog/:slug", BlogPost, { name: "blogPost" }, () => [
|
|
197
|
+
loader(BlogPostLoader, () => [cache()]), // Use boundary cache settings
|
|
198
|
+
]),
|
|
199
|
+
]),
|
|
200
|
+
]),
|
|
201
|
+
|
|
202
|
+
// Shop routes with per-loader caching
|
|
203
|
+
layout(<ShopLayout />, () => [
|
|
204
|
+
path("/shop/product/:slug", ProductPage, { name: "product" }, () => [
|
|
205
|
+
loader(ProductLoader, () => [cache({ ttl: 120 })]),
|
|
206
|
+
loader(CartLoader, () => [
|
|
207
|
+
revalidate(({ actionId }) => actionId?.includes("Cart") ?? false),
|
|
208
|
+
]),
|
|
209
|
+
]),
|
|
210
|
+
]),
|
|
211
|
+
|
|
212
|
+
// Checkout with custom cache store
|
|
213
|
+
cache({ store: checkoutCache }, () => [
|
|
214
|
+
path("/checkout", CheckoutPage, { name: "checkout" }),
|
|
215
|
+
]),
|
|
216
|
+
|
|
217
|
+
// No cache for account pages
|
|
218
|
+
path("/account", AccountPage, { name: "account" }),
|
|
219
|
+
]);
|
|
220
|
+
```
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: composability
|
|
3
|
+
description: Reusable composition patterns with globally importable route helpers in @rangojs/router
|
|
4
|
+
argument-hint: "pattern-name"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Composability
|
|
8
|
+
|
|
9
|
+
Route helpers can be imported directly from `@rangojs/router` and used to build reusable composition factories. This enables sharing common route configurations across multiple routes and modules.
|
|
10
|
+
|
|
11
|
+
## Globally Importable Helpers
|
|
12
|
+
|
|
13
|
+
These helpers can be imported and called outside the `urls()` callback parameter:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import {
|
|
17
|
+
layout,
|
|
18
|
+
cache,
|
|
19
|
+
middleware,
|
|
20
|
+
revalidate,
|
|
21
|
+
loader,
|
|
22
|
+
loading,
|
|
23
|
+
parallel,
|
|
24
|
+
intercept,
|
|
25
|
+
when,
|
|
26
|
+
errorBoundary,
|
|
27
|
+
notFoundBoundary,
|
|
28
|
+
} from "@rangojs/router";
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
They work because they use AsyncLocalStorage internally and resolve context at call time, not import time.
|
|
32
|
+
|
|
33
|
+
## Why path() and include() Are Not Global
|
|
34
|
+
|
|
35
|
+
`path()` and `include()` remain exclusive to the `urls()` callback:
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
urls(({ path, include }) => [
|
|
39
|
+
path("/blog", BlogPage, { name: "blog" }),
|
|
40
|
+
include("/shop", shopPatterns, { name: "shop" }),
|
|
41
|
+
]);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
They define the route structure -- the URL patterns and how modules compose. Keeping them in the `urls()` callback makes the route tree readable at a glance. When scanning a URL file, `path()` and `include()` calls show what renders where. Moving them into factories would hide the routing structure and make it harder to understand which URLs exist and how they nest.
|
|
45
|
+
|
|
46
|
+
The globally importable helpers (`cache`, `middleware`, `loading`, etc.) are configuration -- they modify behavior of routes but don't define routes themselves. Extracting them into factories doesn't obscure the route structure.
|
|
47
|
+
|
|
48
|
+
## Composition Factories
|
|
49
|
+
|
|
50
|
+
Define reusable factories that return arrays of use items:
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { cache, revalidate, loading, errorBoundary, middleware } from "@rangojs/router";
|
|
54
|
+
|
|
55
|
+
// Shared caching configuration
|
|
56
|
+
const withCaching = () => [
|
|
57
|
+
cache({ ttl: 600_000 }),
|
|
58
|
+
revalidate(({ actionId }) => !!actionId),
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
// Shared loading and error handling
|
|
62
|
+
const withLoadingAndError = (skeleton: ReactNode) => [
|
|
63
|
+
loading(skeleton),
|
|
64
|
+
errorBoundary(() => <div>Something went wrong</div>),
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
// Shared auth middleware
|
|
68
|
+
const withAuth = () => [
|
|
69
|
+
middleware(authMiddleware),
|
|
70
|
+
middleware(loggingMiddleware),
|
|
71
|
+
];
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Using Factories in Routes
|
|
75
|
+
|
|
76
|
+
Place factory calls inside `path()` or `layout()` use callbacks. The returned arrays are flattened automatically (up to 3 levels):
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { urls } from "@rangojs/router";
|
|
80
|
+
import { withCaching, withLoadingAndError, withAuth } from "./route-config";
|
|
81
|
+
|
|
82
|
+
export const urlpatterns = urls(({ path, layout }) => [
|
|
83
|
+
layout(<AppLayout />, () => [
|
|
84
|
+
withAuth(),
|
|
85
|
+
|
|
86
|
+
path("/blog", BlogIndex, { name: "blog" }, () => [
|
|
87
|
+
withCaching(),
|
|
88
|
+
withLoadingAndError(<BlogSkeleton />),
|
|
89
|
+
]),
|
|
90
|
+
|
|
91
|
+
path("/shop", ShopIndex, { name: "shop" }, () => [
|
|
92
|
+
withCaching(),
|
|
93
|
+
withLoadingAndError(<ShopSkeleton />),
|
|
94
|
+
]),
|
|
95
|
+
]),
|
|
96
|
+
]);
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Sharing Across Modules
|
|
100
|
+
|
|
101
|
+
Factories can be defined in shared modules and reused across separate `urls()` definitions:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// src/route-config.ts
|
|
105
|
+
import { cache, revalidate, middleware } from "@rangojs/router";
|
|
106
|
+
import { authMiddleware } from "./middleware/auth";
|
|
107
|
+
|
|
108
|
+
export const withPublicDefaults = () => [
|
|
109
|
+
cache({ ttl: 300 }),
|
|
110
|
+
revalidate(({ actionId }) => !!actionId),
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
export const withProtectedDefaults = () => [
|
|
114
|
+
middleware(authMiddleware),
|
|
115
|
+
cache({ ttl: 60 }),
|
|
116
|
+
];
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
// src/urls/blog.ts
|
|
121
|
+
import { urls } from "@rangojs/router";
|
|
122
|
+
import { withPublicDefaults } from "../route-config";
|
|
123
|
+
|
|
124
|
+
export const blogPatterns = urls(({ path }) => [
|
|
125
|
+
path("/", BlogIndex, { name: "index" }, () => [withPublicDefaults()]),
|
|
126
|
+
]);
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
// src/urls/admin.ts
|
|
131
|
+
import { urls } from "@rangojs/router";
|
|
132
|
+
import { withProtectedDefaults } from "../route-config";
|
|
133
|
+
|
|
134
|
+
export const adminPatterns = urls(({ path }) => [
|
|
135
|
+
path("/", AdminDashboard, { name: "index" }, () => [withProtectedDefaults()]),
|
|
136
|
+
]);
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Composition Types
|
|
140
|
+
|
|
141
|
+
For typed factories, import the composition types:
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import type { RouteUseItem, LayoutUseItem, UseItems } from "@rangojs/router";
|
|
145
|
+
|
|
146
|
+
// Factory for path() use callbacks
|
|
147
|
+
const withCaching = (): RouteUseItem[] => [
|
|
148
|
+
cache({ ttl: 600_000 }),
|
|
149
|
+
];
|
|
150
|
+
|
|
151
|
+
// Factory for layout() use callbacks
|
|
152
|
+
const withAuth = (): LayoutUseItem[] => [
|
|
153
|
+
middleware(authMiddleware),
|
|
154
|
+
];
|
|
155
|
+
|
|
156
|
+
// Factory that nests other factories (use UseItems for nested arrays)
|
|
157
|
+
const withEverything = (): UseItems<RouteUseItem> => [
|
|
158
|
+
withCaching(),
|
|
159
|
+
loading(<Skeleton />),
|
|
160
|
+
];
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
- `RouteUseItem[]` -- flat array for `path()` use callbacks
|
|
164
|
+
- `LayoutUseItem[]` -- flat array for `layout()` use callbacks
|
|
165
|
+
- `UseItems<T>` -- allows nested arrays from composing factories together
|
|
166
|
+
|
|
167
|
+
## Rules
|
|
168
|
+
|
|
169
|
+
- Helpers execute lazily -- factory functions are defined anywhere, but only called inside a `urls()` context (within `path()` or `layout()` use callbacks)
|
|
170
|
+
- Calling helpers outside a `urls()` context throws an error
|
|
171
|
+
- Nested arrays from factories are flattened automatically via `.flat(3)`
|
|
172
|
+
- `path()` and `include()` cannot be used in factories -- they define route structure and must remain visible in the `urls()` callback
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: debug-manifest
|
|
3
|
+
description: Debug and inspect route manifest structure
|
|
4
|
+
argument-hint:
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Debug Manifest
|
|
8
|
+
|
|
9
|
+
Inspect the route manifest to verify parent relationships, shortCodes, and route structure.
|
|
10
|
+
|
|
11
|
+
## Quick Access
|
|
12
|
+
|
|
13
|
+
In development, visit:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
http://localhost:PORT/__debug_manifest
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Returns formatted JSON with all routes and layouts.
|
|
20
|
+
|
|
21
|
+
## Programmatic Access
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { router } from "./router.js";
|
|
25
|
+
|
|
26
|
+
// Only in development
|
|
27
|
+
if (process.env.NODE_ENV !== "production") {
|
|
28
|
+
const manifest = await router.debugManifest();
|
|
29
|
+
console.log(JSON.stringify(manifest, null, 2));
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Manifest Structure
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"routes": {
|
|
38
|
+
"home.index": {
|
|
39
|
+
"id": "debug.M0.$root.$route.0.home.index",
|
|
40
|
+
"shortCode": "M0L0R0",
|
|
41
|
+
"type": "route",
|
|
42
|
+
"parentShortCode": "M0L0",
|
|
43
|
+
"pattern": "/",
|
|
44
|
+
"hasLoader": false,
|
|
45
|
+
"hasMiddleware": false,
|
|
46
|
+
"hasErrorBoundary": false,
|
|
47
|
+
"parallelCount": 0,
|
|
48
|
+
"interceptCount": 0
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"layouts": {
|
|
52
|
+
"debug.M0.$root": {
|
|
53
|
+
"id": "debug.M0.$root",
|
|
54
|
+
"shortCode": "M0L0",
|
|
55
|
+
"type": "layout",
|
|
56
|
+
"parentShortCode": null
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"totalRoutes": 45,
|
|
60
|
+
"totalLayouts": 18
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## ShortCode Format
|
|
65
|
+
|
|
66
|
+
| Prefix | Meaning |
|
|
67
|
+
| ------ | ---------------------------------------- |
|
|
68
|
+
| **M** | Mount index (multiple `.routes()` calls) |
|
|
69
|
+
| **L** | Layout |
|
|
70
|
+
| **C** | Cache boundary |
|
|
71
|
+
| **R** | Route |
|
|
72
|
+
| **P** | Parallel slot |
|
|
73
|
+
|
|
74
|
+
Example: `M0L0L1C0R0` = Mount 0 → Root Layout → Nested Layout → Cache → Route
|
|
75
|
+
|
|
76
|
+
## Debugging Checklist
|
|
77
|
+
|
|
78
|
+
1. **Routes have parents**: `parentShortCode` should NOT be `null` (except root layout)
|
|
79
|
+
2. **Correct hierarchy**: ShortCode should reflect nesting (e.g., `M0L0R0` not `M0R0`)
|
|
80
|
+
3. **Loaders attached**: Check `hasLoader: true` for routes with data requirements
|
|
81
|
+
4. **Intercepts registered**: `interceptCount > 0` for modal/overlay patterns
|
|
82
|
+
|
|
83
|
+
## Comparing Manifests
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import {
|
|
87
|
+
serializeManifest,
|
|
88
|
+
compareManifests,
|
|
89
|
+
formatManifestDiff,
|
|
90
|
+
} from "@rangojs/router/__internal";
|
|
91
|
+
|
|
92
|
+
const oldManifest = await router.debugManifest();
|
|
93
|
+
// ... make changes ...
|
|
94
|
+
const newManifest = await router.debugManifest();
|
|
95
|
+
|
|
96
|
+
const diff = compareManifests(oldManifest, newManifest);
|
|
97
|
+
console.log(formatManifestDiff(diff));
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Common Issues
|
|
101
|
+
|
|
102
|
+
### Routes have `parentShortCode: null`
|
|
103
|
+
|
|
104
|
+
Routes should have a layout parent. Check that `urls()` handler is being wrapped in root layout.
|
|
105
|
+
|
|
106
|
+
### Missing layouts in hierarchy
|
|
107
|
+
|
|
108
|
+
Verify `layout()` calls wrap child routes correctly.
|
|
109
|
+
|
|
110
|
+
### Wrong mount index
|
|
111
|
+
|
|
112
|
+
Multiple `.routes()` calls create separate mounts (M0, M1, etc.). Use `include()` to share context.
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: document-cache
|
|
3
|
+
description: Cache full HTTP responses at the edge with Cache-Control headers
|
|
4
|
+
argument-hint: [setup]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Document Cache
|
|
8
|
+
|
|
9
|
+
Caches complete HTTP responses (HTML/RSC) at the edge based on Cache-Control headers. Routes opt-in by setting `s-maxage`.
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
Configure document cache in router:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { createRouter } from "@rangojs/router";
|
|
17
|
+
import { CFCacheStore } from "@rangojs/router/cache";
|
|
18
|
+
import { urlpatterns } from "./urls";
|
|
19
|
+
|
|
20
|
+
const router = createRouter<AppBindings>({
|
|
21
|
+
document: Document,
|
|
22
|
+
urls: urlpatterns,
|
|
23
|
+
documentCache: (_env, ctx) => ({
|
|
24
|
+
store: new CFCacheStore({ ctx: ctx! }),
|
|
25
|
+
skipPaths: ["/api", "/admin"],
|
|
26
|
+
debug: process.env.NODE_ENV === "development",
|
|
27
|
+
}),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
export default router;
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Route Opt-In with cache()
|
|
34
|
+
|
|
35
|
+
Routes opt-in to document caching using the `cache()` DSL with `documentCache` option:
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { urls } from "@rangojs/router";
|
|
39
|
+
|
|
40
|
+
export const urlpatterns = urls(({ path, cache }) => [
|
|
41
|
+
// Cache full page for 5 min, serve stale for 1 hour
|
|
42
|
+
cache({ documentCache: { sMaxAge: 300, swr: 3600 } }, () => [
|
|
43
|
+
path("/blog", BlogIndex, { name: "blog" }),
|
|
44
|
+
]),
|
|
45
|
+
|
|
46
|
+
// Long cache for individual posts
|
|
47
|
+
cache({ documentCache: { sMaxAge: 3600, swr: 86400 } }, () => [
|
|
48
|
+
path("/blog/:slug", BlogPost, { name: "blogPost" }),
|
|
49
|
+
]),
|
|
50
|
+
|
|
51
|
+
// No cache for dashboard (no documentCache option)
|
|
52
|
+
path("/dashboard", Dashboard, { name: "dashboard" }),
|
|
53
|
+
]);
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Document Cache Options
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
createRouter({
|
|
60
|
+
// ...
|
|
61
|
+
documentCache: (_env, ctx) => ({
|
|
62
|
+
// Cache store (required)
|
|
63
|
+
store: new CFCacheStore({ ctx: ctx! }),
|
|
64
|
+
|
|
65
|
+
// Skip specific paths
|
|
66
|
+
skipPaths: ["/api", "/admin"],
|
|
67
|
+
|
|
68
|
+
// Custom cache key
|
|
69
|
+
keyGenerator: (url) => url.pathname,
|
|
70
|
+
|
|
71
|
+
// Conditional caching
|
|
72
|
+
isEnabled: (ctx) => !ctx.request.headers.has("x-preview"),
|
|
73
|
+
|
|
74
|
+
// Debug logging
|
|
75
|
+
debug: true,
|
|
76
|
+
}),
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## How It Works
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
Request → Check Cache
|
|
84
|
+
↓
|
|
85
|
+
┌──────┴──────┐
|
|
86
|
+
│ │
|
|
87
|
+
HIT MISS
|
|
88
|
+
│ │
|
|
89
|
+
↓ ↓
|
|
90
|
+
Fresh? Run handler
|
|
91
|
+
│ │
|
|
92
|
+
Yes → Return Has documentCache?
|
|
93
|
+
│ │
|
|
94
|
+
No (stale) Yes → Cache + Return
|
|
95
|
+
│ │
|
|
96
|
+
↓ No → Return (no cache)
|
|
97
|
+
Return stale,
|
|
98
|
+
revalidate in
|
|
99
|
+
background (SWR)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Cache Status Header
|
|
103
|
+
|
|
104
|
+
Response includes `x-document-cache-status`:
|
|
105
|
+
|
|
106
|
+
- `HIT` - Fresh cache hit
|
|
107
|
+
- `STALE` - Served stale, revalidating in background
|
|
108
|
+
- `MISS` - Cache miss, response was generated fresh
|
|
109
|
+
|
|
110
|
+
## Cache Key Generation
|
|
111
|
+
|
|
112
|
+
Default keys differentiate:
|
|
113
|
+
|
|
114
|
+
- HTML requests: `{pathname}:html`
|
|
115
|
+
- RSC partials: `{pathname}:{segmentHash}:rsc`
|
|
116
|
+
|
|
117
|
+
Segment hash ensures different cached responses for navigations from different source pages (with different layouts).
|
|
118
|
+
|
|
119
|
+
## What Gets Cached
|
|
120
|
+
|
|
121
|
+
- Full HTML responses (document requests)
|
|
122
|
+
- RSC payloads (client navigation)
|
|
123
|
+
- Only 200 OK responses with documentCache enabled
|
|
124
|
+
|
|
125
|
+
## What's NOT Cached
|
|
126
|
+
|
|
127
|
+
- Server actions (`_rsc_action`)
|
|
128
|
+
- Loader requests (`_rsc_loader`)
|
|
129
|
+
- Routes without `documentCache` option
|
|
130
|
+
- Non-200 responses
|
|
131
|
+
|
|
132
|
+
## Complete Example
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
// router.tsx
|
|
136
|
+
import { createRouter } from "@rangojs/router";
|
|
137
|
+
import { CFCacheStore } from "@rangojs/router/cache";
|
|
138
|
+
import { urlpatterns } from "./urls";
|
|
139
|
+
|
|
140
|
+
const router = createRouter<AppBindings>({
|
|
141
|
+
document: Document,
|
|
142
|
+
urls: urlpatterns,
|
|
143
|
+
documentCache: (_env, ctx) => ({
|
|
144
|
+
store: new CFCacheStore({ ctx: ctx! }),
|
|
145
|
+
skipPaths: ["/api"],
|
|
146
|
+
debug: process.env.NODE_ENV === "development",
|
|
147
|
+
}),
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
export default router;
|
|
151
|
+
|
|
152
|
+
// urls.tsx
|
|
153
|
+
import { urls } from "@rangojs/router";
|
|
154
|
+
|
|
155
|
+
export const urlpatterns = urls(({ path, layout, cache, loader }) => [
|
|
156
|
+
// Blog with document caching
|
|
157
|
+
cache({ documentCache: { sMaxAge: 300, swr: 3600 } }, () => [
|
|
158
|
+
layout(<BlogLayout />, () => [
|
|
159
|
+
path("/blog", BlogIndex, { name: "blog" }),
|
|
160
|
+
path("/blog/:slug", BlogPost, { name: "blogPost" }, () => [
|
|
161
|
+
loader(BlogPostLoader),
|
|
162
|
+
]),
|
|
163
|
+
]),
|
|
164
|
+
]),
|
|
165
|
+
|
|
166
|
+
// Dashboard - no document cache (dynamic content)
|
|
167
|
+
layout(<DashboardLayout />, () => [
|
|
168
|
+
path("/dashboard", Dashboard, { name: "dashboard" }),
|
|
169
|
+
]),
|
|
170
|
+
]);
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Document Cache vs Segment Cache
|
|
174
|
+
|
|
175
|
+
| Feature | Document Cache | Segment Cache |
|
|
176
|
+
| ------------ | -------------------------- | --------------------- |
|
|
177
|
+
| Granularity | Full response | Individual segments |
|
|
178
|
+
| Opt-in | `documentCache` in cache() | `cache({ ttl, swr })` |
|
|
179
|
+
| Use case | Static pages | Dynamic compositions |
|
|
180
|
+
| Key includes | URL + segment hash | Route params |
|
|
181
|
+
|
|
182
|
+
Use document cache for mostly-static pages. Use segment cache when different parts of a page have different cache requirements.
|