@rangojs/router 0.16.0 → 0.18.0
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 +255 -89
- package/dist/testing/vitest.js +252 -0
- package/dist/types/browser/cookie-name.d.ts +6 -0
- package/dist/types/browser/history-state.d.ts +16 -0
- package/dist/types/browser/navigation-transaction.d.ts +6 -0
- package/dist/types/browser/partial-update.d.ts +11 -0
- package/dist/types/browser/react/ScrollRestoration.d.ts +6 -6
- package/dist/types/browser/rsc-router.d.ts +1 -1
- package/dist/types/browser/scroll-restoration.d.ts +7 -0
- package/dist/types/cache/cache-exec-scope.d.ts +18 -1
- package/dist/types/cache/cache-key-utils.d.ts +17 -2
- package/dist/types/cache/cache-policy.d.ts +17 -0
- package/dist/types/cache/cache-scope.d.ts +132 -19
- package/dist/types/cache/cache-tag.d.ts +92 -7
- package/dist/types/cache/cf/cf-base64.d.ts +6 -0
- package/dist/types/cache/cf/cf-cache-constants.d.ts +11 -0
- package/dist/types/cache/cf/cf-cache-store.d.ts +185 -44
- package/dist/types/cache/cf/cf-cache-types.d.ts +31 -4
- package/dist/types/cache/cf/cf-shell-frame.d.ts +95 -0
- package/dist/types/cache/cf/cf-tag-marker-memo.d.ts +34 -0
- package/dist/types/cache/handle-capture.d.ts +41 -3
- package/dist/types/cache/handle-snapshot.d.ts +54 -13
- package/dist/types/cache/index.d.ts +1 -0
- package/dist/types/cache/isolate-tag-memo.d.ts +149 -0
- package/dist/types/cache/segment-codec.d.ts +10 -3
- package/dist/types/cache/shell-memo.d.ts +178 -0
- package/dist/types/cache/shell-snapshot.d.ts +110 -21
- package/dist/types/cache/tag-invalidation.d.ts +30 -3
- package/dist/types/cache/taint.d.ts +1 -1
- package/dist/types/cache/types.d.ts +220 -44
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +111 -13
- package/dist/types/client.d.ts +4 -4
- package/dist/types/client.rsc.d.ts +4 -5
- package/dist/types/components/DefaultDocument.d.ts +5 -2
- package/dist/types/context-var.d.ts +6 -5
- package/dist/types/escape-script.d.ts +1 -1
- package/dist/types/handles/MetaTags.d.ts +5 -4
- package/dist/types/handles/Scripts.d.ts +8 -7
- package/dist/types/handles/meta.d.ts +2 -2
- package/dist/types/handles/script.d.ts +17 -16
- package/dist/types/href-client.d.ts +1 -1
- package/dist/types/html.d.ts +12 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.rsc.d.ts +3 -2
- package/dist/types/loader-store.d.ts +7 -4
- package/dist/types/prerender/build-shell-capture.d.ts +11 -4
- package/dist/types/reverse.d.ts +36 -4
- package/dist/types/route-definition/dsl-helpers.d.ts +3 -3
- package/dist/types/route-definition/helpers-types.d.ts +33 -9
- package/dist/types/route-definition/resolve-handler-use.d.ts +23 -1
- package/dist/types/route-types.d.ts +1 -1
- package/dist/types/router/debug-manifest.d.ts +3 -2
- package/dist/types/router/error-handling.d.ts +20 -0
- package/dist/types/router/handler-context.d.ts +6 -0
- package/dist/types/router/instrument.d.ts +8 -0
- package/dist/types/router/match-middleware/background-revalidation.d.ts +46 -5
- package/dist/types/router/middleware-types.d.ts +9 -3
- package/dist/types/router/router-context.d.ts +3 -1
- package/dist/types/router/router-interfaces.d.ts +24 -2
- package/dist/types/router/router-options.d.ts +8 -5
- package/dist/types/router/segment-resolution/fresh.d.ts +10 -0
- package/dist/types/router/segment-resolution/loader-cache.d.ts +66 -1
- package/dist/types/router/segment-resolution/loader-mask.d.ts +9 -19
- package/dist/types/router/segment-resolution/loader-snapshot.d.ts +23 -12
- package/dist/types/router/segment-resolution/mask-nested.d.ts +67 -26
- package/dist/types/router/segment-resolution/revalidation.d.ts +6 -2
- package/dist/types/router/segment-wrappers.d.ts +1 -1
- package/dist/types/rsc/full-payload.d.ts +14 -0
- package/dist/types/rsc/handler.d.ts +1 -1
- package/dist/types/rsc/response-route-handler.d.ts +1 -1
- package/dist/types/rsc/rsc-rendering.d.ts +1 -2
- package/dist/types/rsc/shell-build-manifest.d.ts +8 -0
- package/dist/types/rsc/shell-capture-constants.d.ts +61 -6
- package/dist/types/rsc/shell-capture.d.ts +151 -19
- package/dist/types/rsc/shell-serve.d.ts +140 -17
- package/dist/types/rsc/ssr-setup.d.ts +6 -6
- package/dist/types/rsc/types.d.ts +17 -0
- package/dist/types/server/context.d.ts +139 -15
- package/dist/types/server/cookie-store.d.ts +21 -0
- package/dist/types/server/handle-store.d.ts +26 -2
- package/dist/types/server/request-context.d.ts +182 -53
- package/dist/types/ssr/index.d.ts +24 -0
- package/dist/types/ssr/ssr-root.d.ts +9 -8
- package/dist/types/static-handler.d.ts +4 -1
- package/dist/types/testing/flight.entry.d.ts +7 -0
- package/dist/types/testing/generated-routes.d.ts +2 -2
- package/dist/types/testing/internal/context.d.ts +1 -1
- package/dist/types/testing/render-route.d.ts +32 -6
- package/dist/types/testing/run-loader.d.ts +18 -3
- package/dist/types/testing/serve-shell-request.d.ts +132 -0
- package/dist/types/testing/shell-status.d.ts +23 -10
- package/dist/types/testing/vitest-stubs/plugin-rsc.d.ts +28 -5
- package/dist/types/testing/vitest.d.ts +35 -1
- package/dist/types/theme/ThemeScript.d.ts +3 -3
- package/dist/types/types/cache-types.d.ts +14 -10
- package/dist/types/types/handler-context.d.ts +28 -1
- package/dist/types/types/loader-types.d.ts +8 -6
- package/dist/types/urls/pattern-types.d.ts +22 -18
- package/dist/types/urls/response-types.d.ts +3 -12
- package/dist/types/use-loader.d.ts +12 -3
- package/dist/types/vite/plugins/use-cache-transform.d.ts +33 -2
- package/dist/types/vite/rango.d.ts +1 -1
- package/dist/types/vite/router-discovery.d.ts +29 -2
- package/dist/vite/index.js +1420 -1348
- package/package.json +2 -2
- package/skills/api-client/SKILL.md +22 -10
- package/skills/breadcrumbs/SKILL.md +75 -22
- package/skills/bundle-analysis/SKILL.md +22 -22
- package/skills/cache-guide/SKILL.md +306 -124
- package/skills/caching/SKILL.md +530 -98
- package/skills/catalog.json +16 -16
- package/skills/client-urls/SKILL.md +65 -38
- package/skills/cloudflare/SKILL.md +87 -20
- package/skills/cloudflare/references/d1-and-local-dev.md +15 -2
- package/skills/cloudflare/references/streaming-and-deploy.md +10 -3
- package/skills/cloudflare/references/webhooks-and-crypto.md +9 -2
- package/skills/comparison/SKILL.md +5 -0
- package/skills/comparison/references/framework-comparison.md +75 -57
- package/skills/composability/SKILL.md +38 -29
- package/skills/css/SKILL.md +10 -13
- package/skills/debug-manifest/SKILL.md +74 -31
- package/skills/defer-hydration/SKILL.md +52 -31
- package/skills/deployment-caching/SKILL.md +11 -3
- package/skills/document-cache/SKILL.md +98 -28
- package/skills/fonts/SKILL.md +16 -8
- package/skills/handler-use/SKILL.md +55 -17
- package/skills/hooks/SKILL.md +28 -20
- package/skills/hooks/data.md +23 -3
- package/skills/hooks/handle-and-actions.md +34 -17
- package/skills/hooks/navigation.md +39 -10
- package/skills/hooks/outlets.md +13 -6
- package/skills/hooks/state.md +39 -15
- package/skills/hooks/urls.md +7 -5
- package/skills/host-router/SKILL.md +64 -12
- package/skills/i18n/SKILL.md +60 -34
- package/skills/intercept/SKILL.md +161 -26
- package/skills/layout/SKILL.md +106 -50
- package/skills/links/SKILL.md +51 -19
- package/skills/loader/SKILL.md +386 -128
- package/skills/middleware/SKILL.md +129 -26
- package/skills/migrate-nextjs/SKILL.md +156 -70
- package/skills/migrate-nextjs/backend-host-swap.md +5 -2
- package/skills/migrate-react-router/SKILL.md +51 -39
- package/skills/migrate-react-router/component-migration.md +28 -7
- package/skills/migrate-react-router/data-and-actions.md +21 -6
- package/skills/migrate-react-router/route-mapping.md +19 -10
- package/skills/mime-routes/SKILL.md +12 -7
- package/skills/observability/SKILL.md +92 -14
- package/skills/parallel/SKILL.md +88 -47
- package/skills/ppr/SKILL.md +866 -379
- package/skills/prerender/SKILL.md +210 -108
- package/skills/rango/SKILL.md +115 -65
- package/skills/react-compiler/SKILL.md +6 -5
- package/skills/response-routes/SKILL.md +133 -25
- package/skills/route/SKILL.md +170 -60
- package/skills/router-setup/SKILL.md +420 -240
- package/skills/scripts/SKILL.md +39 -21
- package/skills/server-actions/SKILL.md +231 -59
- package/skills/shell-manifest/SKILL.md +28 -14
- package/skills/streams-and-websockets/SKILL.md +32 -14
- package/skills/tailwind/SKILL.md +37 -33
- package/skills/testing/SKILL.md +73 -33
- package/skills/testing/cache-prerender.md +60 -33
- package/skills/testing/client-components.md +59 -6
- package/skills/testing/e2e-parity.md +12 -2
- package/skills/testing/flight.md +19 -11
- package/skills/testing/handles.md +8 -5
- package/skills/testing/loader.md +26 -6
- package/skills/testing/middleware.md +8 -3
- package/skills/testing/predicates.md +120 -0
- package/skills/testing/render-handler.md +70 -22
- package/skills/testing/response-routes.md +11 -4
- package/skills/testing/reverse-and-types.md +20 -14
- package/skills/testing/serve-shell-request.md +188 -0
- package/skills/testing/server-actions.md +12 -3
- package/skills/testing/server-tree.md +9 -0
- package/skills/testing/setup.md +9 -5
- package/skills/theme/SKILL.md +155 -30
- package/skills/typesafety/SKILL.md +20 -9
- package/skills/typesafety/env-and-bindings.md +137 -50
- package/skills/typesafety/generated-files-and-cli.md +26 -14
- package/skills/typesafety/params-and-search.md +44 -19
- package/skills/typesafety/route-types.md +50 -14
- package/skills/use-cache/SKILL.md +224 -83
- package/skills/vercel/SKILL.md +35 -13
- package/skills/view-transitions/SKILL.md +42 -21
- package/src/__augment-tests__/augmented.check.ts +26 -1
- package/src/browser/cookie-name.ts +23 -0
- package/src/browser/history-state.ts +23 -0
- package/src/browser/index.ts +2 -2
- package/src/browser/navigation-bridge.ts +3 -4
- package/src/browser/navigation-transaction.ts +22 -2
- package/src/browser/partial-update.ts +35 -25
- package/src/browser/react/ScrollRestoration.tsx +6 -6
- package/src/browser/rsc-router.tsx +6 -1
- package/src/browser/scroll-restoration.ts +53 -6
- package/src/cache/cache-exec-scope.ts +37 -4
- package/src/cache/cache-key-utils.ts +23 -8
- package/src/cache/cache-policy.ts +22 -0
- package/src/cache/cache-runtime.ts +264 -68
- package/src/cache/cache-scope.ts +419 -43
- package/src/cache/cache-tag.ts +375 -11
- package/src/cache/cf/cf-base64.ts +36 -4
- package/src/cache/cf/cf-cache-constants.ts +12 -0
- package/src/cache/cf/cf-cache-store.ts +990 -348
- package/src/cache/cf/cf-cache-types.ts +32 -4
- package/src/cache/cf/cf-shell-frame.ts +258 -0
- package/src/cache/cf/cf-tag-marker-memo.ts +143 -39
- package/src/cache/document-cache.ts +15 -0
- package/src/cache/handle-capture.ts +90 -10
- package/src/cache/handle-snapshot.ts +133 -28
- package/src/cache/index.ts +2 -0
- package/src/cache/isolate-tag-memo.ts +308 -0
- package/src/cache/segment-codec.ts +26 -7
- package/src/cache/shell-memo.ts +341 -0
- package/src/cache/shell-snapshot.ts +217 -27
- package/src/cache/tag-invalidation.ts +108 -22
- package/src/cache/taint.ts +1 -1
- package/src/cache/types.ts +225 -44
- package/src/cache/vercel/vercel-cache-store.ts +545 -61
- package/src/client.rsc.tsx +10 -9
- package/src/client.tsx +5 -4
- package/src/components/DefaultDocument.tsx +7 -2
- package/src/context-var.ts +6 -5
- package/src/escape-script.ts +1 -1
- package/src/handles/MetaTags.tsx +13 -11
- package/src/handles/Scripts.tsx +11 -10
- package/src/handles/meta.ts +2 -2
- package/src/handles/script.ts +17 -16
- package/src/href-client.ts +1 -1
- package/src/html.ts +12 -0
- package/src/index.rsc.ts +5 -0
- package/src/index.ts +1 -0
- package/src/loader-store.ts +7 -4
- package/src/prerender/build-shell-capture.ts +73 -22
- package/src/reverse.ts +44 -4
- package/src/route-definition/dsl-helpers.ts +121 -33
- package/src/route-definition/helpers-types.ts +33 -9
- package/src/route-definition/resolve-handler-use.ts +121 -6
- package/src/route-types.ts +0 -3
- package/src/router/debug-manifest.ts +10 -2
- package/src/router/error-handling.ts +51 -15
- package/src/router/handler-context.ts +71 -28
- package/src/router/instrument.ts +54 -2
- package/src/router/intercept-resolution.ts +141 -43
- package/src/router/loader-resolution.ts +115 -39
- package/src/router/match-api.ts +40 -26
- package/src/router/match-handlers.ts +5 -0
- package/src/router/match-middleware/background-revalidation.ts +161 -96
- package/src/router/match-middleware/cache-lookup.ts +110 -10
- package/src/router/match-middleware/cache-store.ts +48 -101
- package/src/router/middleware-types.ts +9 -6
- package/src/router/middleware.ts +75 -13
- package/src/router/prerender-match.ts +59 -19
- package/src/router/route-snapshot.ts +11 -1
- package/src/router/router-context.ts +2 -0
- package/src/router/router-interfaces.ts +25 -2
- package/src/router/router-options.ts +8 -5
- package/src/router/segment-resolution/fresh.ts +62 -21
- package/src/router/segment-resolution/helpers.ts +4 -2
- package/src/router/segment-resolution/loader-cache.ts +407 -76
- package/src/router/segment-resolution/loader-mask.ts +12 -22
- package/src/router/segment-resolution/loader-snapshot.ts +208 -56
- package/src/router/segment-resolution/mask-nested.ts +138 -44
- package/src/router/segment-resolution/revalidation.ts +61 -16
- package/src/router/segment-wrappers.ts +4 -0
- package/src/rsc/full-payload.ts +25 -1
- package/src/rsc/handler.ts +14 -2
- package/src/rsc/progressive-enhancement.ts +3 -2
- package/src/rsc/render-pipeline.ts +3 -0
- package/src/rsc/response-cache-serve.ts +9 -6
- package/src/rsc/response-route-handler.ts +11 -3
- package/src/rsc/rsc-rendering.ts +608 -225
- package/src/rsc/shell-build-manifest.ts +27 -9
- package/src/rsc/shell-capture-constants.ts +73 -6
- package/src/rsc/shell-capture.ts +1068 -296
- package/src/rsc/shell-serve.ts +316 -34
- package/src/rsc/ssr-setup.ts +14 -8
- package/src/rsc/types.ts +18 -0
- package/src/server/context.ts +300 -32
- package/src/server/cookie-store.ts +87 -61
- package/src/server/handle-store.ts +232 -7
- package/src/server/request-context.ts +297 -67
- package/src/ssr/index.tsx +136 -44
- package/src/ssr/ssr-root.tsx +9 -8
- package/src/static-handler.ts +4 -1
- package/src/testing/flight-runtime.d.ts +21 -0
- package/src/testing/flight.entry.ts +14 -0
- package/src/testing/generated-routes.ts +2 -2
- package/src/testing/internal/context.ts +1 -1
- package/src/testing/internal/flight-client-globals.ts +7 -5
- package/src/testing/render-route.tsx +85 -24
- package/src/testing/run-loader.ts +68 -6
- package/src/testing/serve-shell-request.ts +378 -0
- package/src/testing/shell-status.ts +34 -12
- package/src/testing/vitest-stubs/plugin-rsc.ts +123 -20
- package/src/testing/vitest.ts +62 -1
- package/src/theme/ThemeProvider.tsx +7 -6
- package/src/theme/ThemeScript.tsx +3 -3
- package/src/types/cache-types.ts +14 -10
- package/src/types/handler-context.ts +28 -1
- package/src/types/loader-types.ts +8 -6
- package/src/urls/pattern-types.ts +22 -18
- package/src/urls/response-types.ts +3 -23
- package/src/use-loader.tsx +12 -3
- package/src/vite/discovery/shell-prerender-phase.ts +9 -0
- package/src/vite/plugins/use-cache-transform.ts +118 -74
- package/src/vite/rango.ts +7 -3
- package/src/vite/router-discovery.ts +14 -4
package/skills/catalog.json
CHANGED
|
@@ -17,19 +17,19 @@
|
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
19
|
"name": "bundle-analysis",
|
|
20
|
-
"description": "Audit a Rango app's production bundle for server-side code leaking into the client, dev/prod React duplication, oversized chunks, and
|
|
20
|
+
"description": "Audit a Rango app's production bundle for server-side code leaking into the client, dev/prod React duplication, oversized chunks, and poor client-chunk grouping. Use when investigating bundle size growth, before a production deploy, or when the client/SSR/RSC output suddenly balloons.",
|
|
21
21
|
"argumentHint": "<app-dir>",
|
|
22
22
|
"path": "skills/bundle-analysis/SKILL.md"
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
"name": "cache-guide",
|
|
26
|
-
"description": "
|
|
26
|
+
"description": "Decision guide for Rango's cache layers — \"use cache\", loader cache(), segment cache(), Prerender/Static, the ppr HTML shell, and document/CDN caching — with the cache() vs \"use cache\" comparison (keys, guards, SWR, nesting). Use when unsure which caching mechanism fits a problem, comparing layers, or asking \"which cache API should I use\".",
|
|
27
27
|
"argumentHint": "",
|
|
28
28
|
"path": "skills/cache-guide/SKILL.md"
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
"name": "caching",
|
|
32
|
-
"description": "Configure
|
|
32
|
+
"description": "Configure segment caching with the cache() DSL in @rangojs/router — TTL/SWR, tags and updateTag/revalidateTag, loader-level caching, and the Memory, Cloudflare (Cache API + optional KV), and Vercel Runtime Cache stores. Use when responses should be cached or revalidated, data is stale or not updating after changes, or you are wiring up a cache store.",
|
|
33
33
|
"argumentHint": "[setup]",
|
|
34
34
|
"path": "skills/caching/SKILL.md"
|
|
35
35
|
},
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"name": "composability",
|
|
56
|
-
"description": "Reusable composition patterns with globally importable route helpers in @rangojs/router. Use when sharing loaders, middleware, or
|
|
56
|
+
"description": "Reusable composition patterns with globally importable route helpers and include() modules in @rangojs/router. Use when sharing loaders, middleware, or caching config across multiple route files, splitting routes into eager or code-split include() groups, or avoiding copy-pasting the same route setup everywhere.",
|
|
57
57
|
"argumentHint": "pattern-name",
|
|
58
58
|
"path": "skills/composability/SKILL.md"
|
|
59
59
|
},
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
},
|
|
66
66
|
{
|
|
67
67
|
"name": "debug-manifest",
|
|
68
|
-
"description": "
|
|
68
|
+
"description": "Inspect the router's route manifest (route/layout tree, shortCodes, parent links, loader/middleware flags) and diff it between versions. Use when routes aren't matching as expected, you need to see the generated route tree, or a path resolves to the wrong handler.",
|
|
69
69
|
"argumentHint": "",
|
|
70
70
|
"path": "skills/debug-manifest/SKILL.md"
|
|
71
71
|
},
|
|
@@ -137,13 +137,13 @@
|
|
|
137
137
|
},
|
|
138
138
|
{
|
|
139
139
|
"name": "loader",
|
|
140
|
-
"description": "Define data loaders
|
|
140
|
+
"description": "Define data loaders with createLoader and register them on routes with loader(). Use when a route needs per-request data that stays fresh and streams while the page renders, a client component reads server data with useLoader, a loader should re-run after specific actions (revalidate), be cached (cache), be callable from the client (fetchable loaders), throw notFound()/redirect(), write page meta/breadcrumbs handles, or must be settled in the SSR'd document (ssr:false).",
|
|
141
141
|
"argumentHint": "[loader]",
|
|
142
142
|
"path": "skills/loader/SKILL.md"
|
|
143
143
|
},
|
|
144
144
|
{
|
|
145
145
|
"name": "middleware",
|
|
146
|
-
"description": "Define middleware
|
|
146
|
+
"description": "Define global (router.use) and route (middleware()) middleware in @rangojs/router — auth gates, logging, response headers, context variables, redirects. Use when gating routes behind auth checks, logging requests, setting headers or ctx variables before a handler runs, or deciding whether middleware wraps server actions.",
|
|
147
147
|
"argumentHint": "[middleware-name]",
|
|
148
148
|
"path": "skills/middleware/SKILL.md"
|
|
149
149
|
},
|
|
@@ -173,7 +173,7 @@
|
|
|
173
173
|
},
|
|
174
174
|
{
|
|
175
175
|
"name": "parallel",
|
|
176
|
-
"description": "Define parallel routes for multi-column layouts, sidebars, and
|
|
176
|
+
"description": "Define parallel routes (named slots) for multi-column layouts, sidebars, and UI-less metadata slots in @rangojs/router. Use when a layout needs multiple independently-loading regions (e.g. a sidebar and main panel), or rendering more than one route segment at the same URL.",
|
|
177
177
|
"argumentHint": "[@slot-name]",
|
|
178
178
|
"path": "skills/parallel/SKILL.md"
|
|
179
179
|
},
|
|
@@ -185,7 +185,7 @@
|
|
|
185
185
|
},
|
|
186
186
|
{
|
|
187
187
|
"name": "prerender",
|
|
188
|
-
"description": "Pre-render route segments at build time with Prerender
|
|
188
|
+
"description": "Pre-render route segments at build time with Prerender (with getParams), Passthrough live fallback, Static segments, and Skip. Use when a page's content is mostly static and shouldn't render on every request, speeding up cold responses, reading build-only data (files, build env), or deciding which routes to prerender vs render live.",
|
|
189
189
|
"argumentHint": "[passthrough]",
|
|
190
190
|
"path": "skills/prerender/SKILL.md"
|
|
191
191
|
},
|
|
@@ -203,19 +203,19 @@
|
|
|
203
203
|
},
|
|
204
204
|
{
|
|
205
205
|
"name": "response-routes",
|
|
206
|
-
"description": "Response routes (path.json, path.text, etc.) for non-RSC endpoints with typed responses. Use when building a JSON/text API endpoint alongside your pages,
|
|
206
|
+
"description": "Response routes (path.json, path.text, etc.) for non-RSC endpoints with typed responses. Use when building a JSON/text API endpoint alongside your pages, asking how to return raw JSON instead of RSC from a route, or protecting a state-changing endpoint from CSRF.",
|
|
207
207
|
"argumentHint": "[json|text|html|xml|md|image|stream]",
|
|
208
208
|
"path": "skills/response-routes/SKILL.md"
|
|
209
209
|
},
|
|
210
210
|
{
|
|
211
211
|
"name": "route",
|
|
212
|
-
"description": "Define routes with path() in @rangojs/router. Use when creating a new page or route, or asking how to define a URL path and its handler.",
|
|
212
|
+
"description": "Define routes with path() in @rangojs/router — URL params, catch-alls, typed search params, the handler context, handler-to-child data, and redirects. Use when creating a new page or route, or asking how to define a URL path and its handler.",
|
|
213
213
|
"argumentHint": "[pattern]",
|
|
214
214
|
"path": "skills/route/SKILL.md"
|
|
215
215
|
},
|
|
216
216
|
{
|
|
217
217
|
"name": "router-setup",
|
|
218
|
-
"description": "Create and configure
|
|
218
|
+
"description": "Create and configure a Rango app with createRouter() and the rango() Vite plugin. Use when bootstrapping a new app, wiring vite.config, writing the Document or worker entry, or setting top-level router options (basename, cache store, prefetch, timeouts, origin check, telemetry, SSR streaming).",
|
|
219
219
|
"argumentHint": "[option]",
|
|
220
220
|
"path": "skills/router-setup/SKILL.md"
|
|
221
221
|
},
|
|
@@ -227,7 +227,7 @@
|
|
|
227
227
|
},
|
|
228
228
|
{
|
|
229
229
|
"name": "server-actions",
|
|
230
|
-
"description": "Define and call server actions (`\"use server\"`) — forms, useActionState, useOptimistic, validation, error handling, redirects, revalidation. Use when handling a form submission on the server, calling a server function from a client component,
|
|
230
|
+
"description": "Define and call server actions (`\"use server\"`) — forms, useActionState, useOptimistic, validation, error handling, redirects, post-action revalidation, client-cache control (keepClientCache), and the default CSRF origin check. Use when handling a form submission on the server, calling a server function from a client component, choosing what re-renders after a mutation, needing optimistic UI after a mutation, or asking how actions are protected from CSRF.",
|
|
231
231
|
"argumentHint": "[action]",
|
|
232
232
|
"path": "skills/server-actions/SKILL.md"
|
|
233
233
|
},
|
|
@@ -251,19 +251,19 @@
|
|
|
251
251
|
},
|
|
252
252
|
{
|
|
253
253
|
"name": "testing",
|
|
254
|
-
"description": "Test @rangojs/router apps — unit (loaders
|
|
254
|
+
"description": "Test @rangojs/router apps — unit (loaders, middleware, server actions, handles, transition/clientUrls predicates), client components (renderRoute), RSC/Flight (renderServerTree, renderHandler, serveShellRequest for PPR shells), integration (dispatch), and e2e (dev+prod parity, progressive enhancement). Use when writing a unit test for a loader, middleware, action, or handler, setting up vitest for a Rango app, or testing a route end-to-end in dev and production.",
|
|
255
255
|
"argumentHint": "[layer]",
|
|
256
256
|
"path": "skills/testing/SKILL.md"
|
|
257
257
|
},
|
|
258
258
|
{
|
|
259
259
|
"name": "theme",
|
|
260
|
-
"description": "Opt-in theme system with FOUC prevention
|
|
260
|
+
"description": "Opt-in light/dark theme system with FOUC prevention, server-side theme access, and a useTheme() hook. Use when adding a light/dark mode toggle, reading or setting the theme in handlers or middleware, or when the page flashes the wrong theme on load (FOUC).",
|
|
261
261
|
"argumentHint": "[setup]",
|
|
262
262
|
"path": "skills/theme/SKILL.md"
|
|
263
263
|
},
|
|
264
264
|
{
|
|
265
265
|
"name": "typesafety",
|
|
266
|
-
"description": "Set up type-safe
|
|
266
|
+
"description": "Set up type-safe route names, params, search params, response payloads, and environment types in @rangojs/router. Use when route or search params aren't typed, ctx.env or ctx.get() is untyped, TypeScript can't infer a loader's return type, or wiring RegisteredRoutes / the generated route map.",
|
|
267
267
|
"argumentHint": "[setup]",
|
|
268
268
|
"path": "skills/typesafety/SKILL.md"
|
|
269
269
|
},
|
|
@@ -119,20 +119,27 @@ The async form works without a server wrapper module too:
|
|
|
119
119
|
behavior, no startup win, uniform with code-split server groups.
|
|
120
120
|
|
|
121
121
|
Route names compose through the include (`shop.index`, `shop.product`) and
|
|
122
|
-
flow into the generated route map, so `href
|
|
123
|
-
typing work exactly as for server routes
|
|
122
|
+
flow into the generated route map, so `href()`, `ctx.reverse()` and
|
|
123
|
+
`RouteParams<"shop.product">` typing work exactly as for server routes
|
|
124
|
+
(`/typesafety`). `rango generate` also writes a per-module `.gen.ts` for a
|
|
125
|
+
`clientUrls()` module, so components inside the group can link with
|
|
126
|
+
`useReverse(routes)` (`/links`).
|
|
124
127
|
|
|
125
128
|
## Helpers: what exists inside clientUrls()
|
|
126
129
|
|
|
127
|
-
| Helper | Notes
|
|
128
|
-
| -------------- |
|
|
129
|
-
| `path()` | Options are `name`, `search`, `trailingSlash`, `ppr` (shell caching — see
|
|
130
|
-
| `layout()` |
|
|
131
|
-
| `loader()` | `loader(Def, use?)` or `loader(Def, { ssr: false }, use?)` — see below
|
|
132
|
-
| `loading()` | Route-level boundary around the optimistic render; inline `<Suspense>` at read sites keeps the destination's chrome visible while only the reads wait
|
|
133
|
-
| `revalidate()` | Valid **inside a loader() use callback only**; runs in the browser
|
|
134
|
-
| `transition()` | Data-only ViewTransition
|
|
135
|
-
| `intercept()` | Dot-local named target in the SAME definition; use may contain `loader()`/`loading()`
|
|
130
|
+
| Helper | Notes |
|
|
131
|
+
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
132
|
+
| `path()` | Options are `name`, `search`, `trailingSlash`, `ppr` (shell caching — see `/ppr` → The loader lane rule); no response variants. Use callback may contain `loader()`, `loading()`, `transition()` |
|
|
133
|
+
| `layout()` | `layout(Component, () => [...])` — children are required and must contain at least one `path()`; may also hold `loader()`, `loading()`, `intercept()`, nested `layout()` |
|
|
134
|
+
| `loader()` | `loader(Def, use?)` or `loader(Def, { ssr: false }, use?)` — see below |
|
|
135
|
+
| `loading()` | Route-level boundary around the optimistic render; inline `<Suspense>` at read sites keeps the destination's chrome visible while only the reads wait |
|
|
136
|
+
| `revalidate()` | Valid **inside a loader() use callback only**; runs in the browser |
|
|
137
|
+
| `transition()` | Inside a `path()` use callback only (at most one). Data-only ViewTransition config — no `when`; same-route navs in a group already hold previous content without it |
|
|
138
|
+
| `intercept()` | Dot-local named target in the SAME definition; use may contain `loader()`/`loading()` |
|
|
139
|
+
|
|
140
|
+
At the top level of the builder only `path()`, `layout()` and `intercept()`
|
|
141
|
+
are accepted, and the builder must define at least one `path()`. Any helper
|
|
142
|
+
name not in this table throws (`clientUrls() has no route() helper`).
|
|
136
143
|
|
|
137
144
|
`include`, `parallel`, `cache`, `middleware`, `errorBoundary`,
|
|
138
145
|
`notFoundBoundary` **throw** — and that is a design position, not a gap.
|
|
@@ -201,16 +208,23 @@ browser — which is why the matcher (resolving an imported reference's
|
|
|
201
208
|
import { addToCart, removeFromCart } from "./actions/cart";
|
|
202
209
|
import * as CartActions from "./actions/cart";
|
|
203
210
|
|
|
204
|
-
|
|
205
|
-
revalidate(({ isAction }) => isAction(
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
211
|
+
// After an action, re-run only for cart actions; on navigation, keep the default.
|
|
212
|
+
revalidate(({ isAction }) => (isAction() ? isAction(CartActions) : undefined));
|
|
213
|
+
|
|
214
|
+
// Matcher forms (each returns a boolean):
|
|
215
|
+
isAction(); // any action
|
|
216
|
+
isAction(addToCart); // one action
|
|
217
|
+
isAction(addToCart, removeFromCart); // several
|
|
218
|
+
isAction(CartActions); // import * as
|
|
219
|
+
isAction({ addToCart, removeFromCart }); // object
|
|
209
220
|
```
|
|
210
221
|
|
|
211
222
|
Bare `isAction()` is "is this an action at all?". `actionId` stays as the
|
|
212
|
-
string escape hatch.
|
|
213
|
-
|
|
223
|
+
string escape hatch. A group loader's locked default already re-runs after
|
|
224
|
+
every action, so `isAction(refs) || undefined` changes nothing there; narrow
|
|
225
|
+
with the ternary above instead (same rule as a server-tree loader). A bare
|
|
226
|
+
`isAction(refs)` is a hard `false` on navigation too, so the loader stops
|
|
227
|
+
refetching when params change.
|
|
214
228
|
|
|
215
229
|
Two scars worth copying:
|
|
216
230
|
|
|
@@ -226,10 +240,12 @@ Two scars worth copying:
|
|
|
226
240
|
Everything a DSL loader can do in the server tree works here — the loader body
|
|
227
241
|
is server code either way.
|
|
228
242
|
|
|
229
|
-
**Authority signals.** A loader may `
|
|
243
|
+
**Authority signals.** A loader may call `notFound()` (it throws) or
|
|
230
244
|
`throw redirect(url)`:
|
|
231
245
|
|
|
232
246
|
```ts
|
|
247
|
+
import { createLoader, notFound, redirect } from "@rangojs/router";
|
|
248
|
+
|
|
233
249
|
export const ProductLoader = createLoader(async (ctx) => {
|
|
234
250
|
const moved = LEGACY_SLUGS[ctx.params.slug];
|
|
235
251
|
if (moved) throw redirect(`/shop/product/${moved}`);
|
|
@@ -252,8 +268,9 @@ handler parity — `ctx.use(Meta)({ title })` pushes exactly like a handler
|
|
|
252
268
|
push. Reads moved to `ctx.get(handle)`, gated behind `await ctx.rendered()`.
|
|
253
269
|
Delivery follows the race model: pushes that settle before the handler barrier
|
|
254
270
|
ride the SSR handle snapshot; later ones stream and apply post-hydration
|
|
255
|
-
(document loads) or progressively (navigations).
|
|
256
|
-
|
|
271
|
+
(document loads) or progressively (navigations). On a `ppr` shell HIT a loader
|
|
272
|
+
without `ssr: false` never ran during the capture, so its pushes are never in
|
|
273
|
+
the shell and always apply client-side. See `/loader` for the full contract.
|
|
257
274
|
|
|
258
275
|
## `ssr: false` — the SSR-completeness opt-in
|
|
259
276
|
|
|
@@ -265,7 +282,11 @@ document — `<head>` meta via a handle, or a real 404 status — flag it:
|
|
|
265
282
|
|
|
266
283
|
```ts
|
|
267
284
|
path("/product/:slug", ProductPage, { name: "product" }, () => [
|
|
268
|
-
loader(ProductLoader, { ssr: false }, () => [
|
|
285
|
+
loader(ProductLoader, { ssr: false }, () => [
|
|
286
|
+
revalidate(({ currentParams, nextParams, defaultShouldRevalidate }) =>
|
|
287
|
+
currentParams.slug !== nextParams.slug ? defaultShouldRevalidate : false,
|
|
288
|
+
),
|
|
289
|
+
]),
|
|
269
290
|
loader(RelatedLoader), // untouched: still streams behind its boundary
|
|
270
291
|
]),
|
|
271
292
|
```
|
|
@@ -286,13 +307,17 @@ Constraints:
|
|
|
286
307
|
construction. It throws a deadlock error naming the fix.
|
|
287
308
|
- `intercept()` loaders reject the flag — intercepts render on client
|
|
288
309
|
navigations only, so a document-render await can never apply.
|
|
289
|
-
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
Every document
|
|
293
|
-
that is the point, but it is a real cost.
|
|
294
|
-
|
|
295
|
-
|
|
310
|
+
- Under a `ppr` group route the flag is the bake lane, exactly as on a server
|
|
311
|
+
route (`/ppr` → The loader lane rule).
|
|
312
|
+
|
|
313
|
+
Every document render that is not a `ppr` shell HIT pays the flagged
|
|
314
|
+
loader's latency before first byte — that is the point, but it is a real cost.
|
|
315
|
+
On a shell HIT the shell flushes first: a flagged loader whose value has no
|
|
316
|
+
promises is served from the shell and does not run (unless the capture marked
|
|
317
|
+
it to run: see `/ppr` → On a shell HIT), and one whose value
|
|
318
|
+
carries promises runs on every HIT to fill its holes. Keep flagged loaders
|
|
319
|
+
fast (existence checks before expensive fetches) and flag the loaders that
|
|
320
|
+
need it, not the route.
|
|
296
321
|
|
|
297
322
|
Pinned end to end by dev + production e2e in the router repository.
|
|
298
323
|
|
|
@@ -321,15 +346,17 @@ a hard load of the target URL renders the full route.
|
|
|
321
346
|
- **Duplicate patterns or names throw** at definition time, per definition.
|
|
322
347
|
- **`layout()` with no `path()` inside throws** — a client layout exists only
|
|
323
348
|
to wrap routes.
|
|
324
|
-
- **`loading()` vs inline Suspense:** same-route
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
`
|
|
331
|
-
|
|
332
|
-
|
|
349
|
+
- **`loading()` vs inline Suspense:** same-route navigations hold previous
|
|
350
|
+
content by default, for SEARCH changes (filters, tabs) and PARAM changes
|
|
351
|
+
alike — group route segments are keyed by the group (`cg:<group>`,
|
|
352
|
+
`segment-system.tsx`), not by route id + params, so the mounted instance
|
|
353
|
+
reconciles instead of remounting. The canonical commit runs in a
|
|
354
|
+
`startTransition` when no new segments mount, and the wrapping layout sees
|
|
355
|
+
`useOutlet().pending === true` for the held window; a route-level
|
|
356
|
+
`loading()` does not re-flash there. `transition()` is not needed for the
|
|
357
|
+
hold; it adds the view-transition animation. Inline `<Suspense>` above each
|
|
358
|
+
`useLoader` read is still the finer-grained tool when different reads on
|
|
359
|
+
one route should wait independently.
|
|
333
360
|
- **Two parallel loaders with equal latency look "SSR'd" together.** Loaders
|
|
334
361
|
kick off in parallel, so awaiting one (`ssr: false`) gives
|
|
335
362
|
same-or-faster siblings time to settle coincidentally. Do not read "it was
|
|
@@ -5,30 +5,36 @@ description: Deploy and operate @rangojs/router on Cloudflare Workers with the C
|
|
|
5
5
|
|
|
6
6
|
# Cloudflare Workers deployment
|
|
7
7
|
|
|
8
|
+
This skill covers running a Rango app on Cloudflare Workers: Vite and Wrangler
|
|
9
|
+
config, the Worker entry, typed bindings, caching, and deployment. The
|
|
10
|
+
references cover D1/KV setup, streaming and deploy diagnostics, and webhooks.
|
|
11
|
+
For router options in general see `/router-setup`.
|
|
12
|
+
|
|
8
13
|
Use the Cloudflare Vite plugin as the runtime bridge. It runs the real Worker
|
|
9
14
|
entry in workerd during `vite dev` and `vite preview`, supplies bindings, and
|
|
10
|
-
emits the deployable Worker configuration during `vite build`.
|
|
15
|
+
emits the deployable Worker configuration during `vite build`. Unlike the Node
|
|
16
|
+
and Vercel presets, you own the Worker entry.
|
|
11
17
|
|
|
12
18
|
## Install and configure
|
|
13
19
|
|
|
14
20
|
```bash
|
|
15
21
|
pnpm add @rangojs/router react react-dom
|
|
16
|
-
pnpm add -D vite @
|
|
17
|
-
|
|
22
|
+
pnpm add -D vite @cloudflare/vite-plugin @cloudflare/workers-types wrangler typescript
|
|
23
|
+
# optional: @vitejs/plugin-react (e.g. for the React Compiler, see /react-compiler)
|
|
18
24
|
```
|
|
19
25
|
|
|
20
|
-
|
|
26
|
+
Rango needs Node 24+ for the Vite toolchain. Keep plugin order stable:
|
|
27
|
+
`react()` first when you use it, then `rango()`, then `cloudflare()`.
|
|
21
28
|
|
|
22
29
|
```typescript
|
|
23
30
|
// vite.config.ts
|
|
24
31
|
import { cloudflare } from "@cloudflare/vite-plugin";
|
|
25
|
-
import react from "@vitejs/plugin-react";
|
|
26
32
|
import { rango } from "@rangojs/router/vite";
|
|
27
33
|
import { defineConfig } from "vite";
|
|
28
34
|
|
|
29
35
|
export default defineConfig({
|
|
30
36
|
plugins: [
|
|
31
|
-
react(),
|
|
37
|
+
// react(), // optional; first when used
|
|
32
38
|
rango({ preset: "cloudflare", buildEnv: "auto" }),
|
|
33
39
|
cloudflare({
|
|
34
40
|
configPath: "./wrangler.json",
|
|
@@ -38,8 +44,16 @@ export default defineConfig({
|
|
|
38
44
|
});
|
|
39
45
|
```
|
|
40
46
|
|
|
41
|
-
`
|
|
42
|
-
|
|
47
|
+
`viteEnvironment` must name the `rsc` environment with `ssr` as a child: the
|
|
48
|
+
Worker runs the RSC entry and loads SSR inside the same isolate.
|
|
49
|
+
|
|
50
|
+
`buildEnv: "auto"` gives `Prerender` and `Static` handlers a real `ctx.env` at
|
|
51
|
+
build time through Wrangler's `getPlatformProxy()` (local bindings). Omit it
|
|
52
|
+
(default `false`) when build-time rendering must not touch bindings; `ctx.env`
|
|
53
|
+
then throws during build rendering. See `/prerender`.
|
|
54
|
+
|
|
55
|
+
`wrangler.json` points `main` at the Worker entry and serves the client build
|
|
56
|
+
as static assets:
|
|
43
57
|
|
|
44
58
|
```json
|
|
45
59
|
{
|
|
@@ -81,7 +95,13 @@ does not need `@types/node` just to type-check Rango:
|
|
|
81
95
|
}
|
|
82
96
|
```
|
|
83
97
|
|
|
84
|
-
##
|
|
98
|
+
## Worker entry
|
|
99
|
+
|
|
100
|
+
Pass both `env` and `ctx` to `router.fetch`. Bindings reach handlers as
|
|
101
|
+
`ctx.env`; the `ExecutionContext` backs `waitUntil`, `CFCacheStore`, and
|
|
102
|
+
tracing. A bare `export default { fetch: router.fetch }` loses both, because
|
|
103
|
+
Workers call `fetch(request, env, ctx)` while `router.fetch` takes
|
|
104
|
+
`(request, { env, ctx })`.
|
|
85
105
|
|
|
86
106
|
```typescript
|
|
87
107
|
// src/worker.rsc.tsx
|
|
@@ -97,8 +117,10 @@ export default {
|
|
|
97
117
|
```
|
|
98
118
|
|
|
99
119
|
Do not call `response.text()` or `response.arrayBuffer()` on the Rango response
|
|
100
|
-
in
|
|
101
|
-
|
|
120
|
+
in the Worker entry: that buffers the whole body and removes RSC/SSR streaming.
|
|
121
|
+
When only headers must change, rewrap the body stream instead
|
|
122
|
+
(`new Response(response.body, response)`); see
|
|
123
|
+
[references/streaming-and-deploy.md](references/streaming-and-deploy.md).
|
|
102
124
|
|
|
103
125
|
## Choose the next reference
|
|
104
126
|
|
|
@@ -114,6 +136,7 @@ in a custom Worker entry. That drains RSC/SSR streaming. Rewrap
|
|
|
114
136
|
Use the Cache API as L1 and KV as optional cross-colo L2:
|
|
115
137
|
|
|
116
138
|
```typescript
|
|
139
|
+
import { createRouter } from "@rangojs/router";
|
|
117
140
|
import { CFCacheStore } from "@rangojs/router/cache";
|
|
118
141
|
|
|
119
142
|
export const router = createRouter<AppBindings>({
|
|
@@ -121,7 +144,7 @@ export const router = createRouter<AppBindings>({
|
|
|
121
144
|
urls: urlpatterns,
|
|
122
145
|
cache: (env, ctx) => ({
|
|
123
146
|
store: new CFCacheStore({
|
|
124
|
-
ctx
|
|
147
|
+
ctx: ctx!, // typed optional on the factory; always present on Workers
|
|
125
148
|
kv: env.CACHE_KV,
|
|
126
149
|
defaults: { ttl: 60, swr: 300 },
|
|
127
150
|
}),
|
|
@@ -129,12 +152,54 @@ export const router = createRouter<AppBindings>({
|
|
|
129
152
|
});
|
|
130
153
|
```
|
|
131
154
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
`
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
155
|
+
`ctx` is required: the store schedules non-blocking writes with
|
|
156
|
+
`ctx.waitUntil`, which is why the Worker entry must pass `{ env, ctx }` to
|
|
157
|
+
`router.fetch`.
|
|
158
|
+
|
|
159
|
+
Tag invalidation (`updateTag()` / `revalidateTag()`) stores its markers in the
|
|
160
|
+
same `kv` namespace. Without `kv`, configure purge mode instead:
|
|
161
|
+
`tagPurge: { zoneId, apiToken }` (an API token with `Zone.Cache Purge`, stored
|
|
162
|
+
as a Worker secret) evicts tagged Cache API entries through Cloudflare's
|
|
163
|
+
purge-by-tag API.
|
|
164
|
+
|
|
165
|
+
PPR shells use the Cache API as the per-colo L1 and KV as the durable
|
|
166
|
+
cross-colo L2; a KV hit promotes the shell back into L1. Without `kv` the shell
|
|
167
|
+
family runs L1-only (each colo captures and serves its own shell). A tagged
|
|
168
|
+
shell with neither `kv` nor `tagPurge` logs a warning once and expires only by
|
|
169
|
+
ttl+swr. See `/caching` and `/ppr`.
|
|
170
|
+
|
|
171
|
+
Shell reads are stale-while-revalidate through per-isolate memos: a warm
|
|
172
|
+
isolate serves a shell it read within `memo.shellMs` (default 2000) from
|
|
173
|
+
memory, and with `kv` it checks tag markers through a memo that is used as is
|
|
174
|
+
for `memo.markerFreshMs` (default 1000) and while it refreshes in the
|
|
175
|
+
background up to `memo.markerMaxStaleMs` (default 10000). After
|
|
176
|
+
`updateTag()`/`revalidateTag()` the response sets the fresh-reads cookie
|
|
177
|
+
(`rango-state-fresh` by default), so the mutating user's next requests skip
|
|
178
|
+
the memos. That makes them fresh in the colo that ran the mutation; other
|
|
179
|
+
colos converge once KV propagates the marker and their cached marker
|
|
180
|
+
(`tagCacheTtl`) expires. In purge mode without `kv`, another isolate's memo
|
|
181
|
+
keeps serving a purged shell until `memo.shellMs` passes. Set
|
|
182
|
+
`memo: { shellMs: 0, markerFreshMs: 0 }` to remove the memo delay for every
|
|
183
|
+
user's next request; cross-colo KV propagation (and `tagCacheTtl`) still
|
|
184
|
+
applies. Details: `/caching` → "The fresh-reads cookie".
|
|
185
|
+
|
|
186
|
+
## Tracing on Workers
|
|
187
|
+
|
|
188
|
+
`createCloudflareTracing()` from `@rangojs/router/cloudflare` emits the
|
|
189
|
+
router's phases as native Workers custom spans next to the automatic KV/D1/fetch
|
|
190
|
+
spans. It reads the tracer from the `ctx` passed to `router.fetch`, and does
|
|
191
|
+
nothing when Workers tracing is not enabled for the Worker. See
|
|
192
|
+
`/observability`.
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
import { createCloudflareTracing } from "@rangojs/router/cloudflare";
|
|
196
|
+
|
|
197
|
+
export const router = createRouter<AppBindings>({
|
|
198
|
+
document: Document,
|
|
199
|
+
urls: urlpatterns,
|
|
200
|
+
tracing: createCloudflareTracing(),
|
|
201
|
+
});
|
|
202
|
+
```
|
|
138
203
|
|
|
139
204
|
## Commands
|
|
140
205
|
|
|
@@ -149,5 +214,7 @@ ttl+swr only.
|
|
|
149
214
|
}
|
|
150
215
|
```
|
|
151
216
|
|
|
152
|
-
|
|
153
|
-
|
|
217
|
+
Always deploy the output of `vite build` (`dist/rsc/wrangler.json`; a plain
|
|
218
|
+
`wrangler deploy` right after a build follows the plugin's redirect to it),
|
|
219
|
+
never the source config. Use `vite dev` and `vite preview` for local RSC work. Reserve
|
|
220
|
+
Wrangler for resource provisioning, migrations, secrets, and deployment.
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# D1, KV, and local parity
|
|
2
2
|
|
|
3
|
+
Provisioning D1/KV bindings, applying migrations, loading local secrets, and
|
|
4
|
+
testing that `vite dev` and `vite preview` behave like the deployed Worker.
|
|
5
|
+
|
|
3
6
|
## Contents
|
|
4
7
|
|
|
5
8
|
- [Provision bindings](#provision-bindings)
|
|
@@ -50,9 +53,11 @@ therefore visible to both `vite dev` and `vite preview`; treat the internal
|
|
|
50
53
|
`.wrangler/state` layout as an implementation detail.
|
|
51
54
|
|
|
52
55
|
Add a real handler probe while setting up the binding, then remove it after the
|
|
53
|
-
first production-shaped test:
|
|
56
|
+
first production-shaped test. `path.json` is a response route (`/response-routes`):
|
|
57
|
+
return a value and it is serialized as JSON.
|
|
54
58
|
|
|
55
59
|
```typescript
|
|
60
|
+
// inside urls(({ path }) => [ ... ])
|
|
56
61
|
path.json("/__db-check", async (ctx) => {
|
|
57
62
|
const row = await ctx.env.DB.prepare(
|
|
58
63
|
"SELECT COUNT(*) AS n FROM users",
|
|
@@ -65,9 +70,17 @@ path.json("/__db-check", async (ctx) => {
|
|
|
65
70
|
|
|
66
71
|
## Use bindings
|
|
67
72
|
|
|
68
|
-
Handlers, loaders, and middleware all receive the same typed bindings
|
|
73
|
+
Handlers, loaders, and middleware all receive the same typed bindings on
|
|
74
|
+
`ctx.env`:
|
|
69
75
|
|
|
70
76
|
```typescript
|
|
77
|
+
import {
|
|
78
|
+
cookies,
|
|
79
|
+
createLoader,
|
|
80
|
+
redirect,
|
|
81
|
+
type Middleware,
|
|
82
|
+
} from "@rangojs/router";
|
|
83
|
+
|
|
71
84
|
export const UserLoader = createLoader(async (ctx) =>
|
|
72
85
|
ctx.env.DB.prepare("SELECT * FROM users WHERE id = ?")
|
|
73
86
|
.bind(ctx.params.id)
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Streaming, preview, and deployment
|
|
2
2
|
|
|
3
|
+
Keeping responses streamed through a custom Worker entry, choosing local
|
|
4
|
+
tooling, route-owned CORS, deploying the built Worker, and isolating
|
|
5
|
+
dev/preview differences.
|
|
6
|
+
|
|
3
7
|
## Contents
|
|
4
8
|
|
|
5
9
|
- [Keep streamed responses intact](#keep-streamed-responses-intact)
|
|
@@ -80,9 +84,12 @@ pnpm exec vite build
|
|
|
80
84
|
pnpm exec wrangler deploy -c dist/rsc/wrangler.json
|
|
81
85
|
```
|
|
82
86
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
87
|
+
`vite build` also writes a `.wrangler/deploy/config.json` redirect, so a plain
|
|
88
|
+
`wrangler deploy` run after the build picks up the same generated config. Never
|
|
89
|
+
deploy the source `main` (for example `wrangler deploy -c wrangler.json`, or a
|
|
90
|
+
deploy with no fresh build): Wrangler's bundler cannot reconstruct Rango's Vite
|
|
91
|
+
virtual modules. If the RSC environment has a custom name, use its matching
|
|
92
|
+
`dist/<name>/wrangler.json` path.
|
|
86
93
|
|
|
87
94
|
Before deployment:
|
|
88
95
|
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Webhooks and WebCrypto on Workers
|
|
2
2
|
|
|
3
|
+
Verifying signed webhooks against the raw request body, testing them offline,
|
|
4
|
+
porting Node crypto to WebCrypto, and keeping large SDKs out of the Worker's
|
|
5
|
+
startup path.
|
|
6
|
+
|
|
3
7
|
## Contents
|
|
4
8
|
|
|
5
9
|
- [Read the original request body](#read-the-original-request-body)
|
|
@@ -136,10 +140,13 @@ provider behavior when upgrading the SDK major.
|
|
|
136
140
|
|
|
137
141
|
## Keep SDKs off the cold path
|
|
138
142
|
|
|
139
|
-
Put a large, rarely used webhook/billing group behind an async include
|
|
143
|
+
Put a large, rarely used webhook/billing group behind an async include with
|
|
144
|
+
its own URL prefix. The chunk is imported on the first request that reaches
|
|
145
|
+
that prefix, not at Worker startup (`/composability`):
|
|
140
146
|
|
|
141
147
|
```typescript
|
|
142
|
-
|
|
148
|
+
// urls/billing.ts: `export default urls(({ path }) => [ ... ])`
|
|
149
|
+
include("/api/billing", () => import("./urls/billing.js"), { name: "billing" });
|
|
143
150
|
```
|
|
144
151
|
|
|
145
152
|
Measure a before/after production build before claiming an SDK's incremental
|
|
@@ -5,6 +5,11 @@ description: Compare Rango with Next.js App Router, TanStack Start, and Waku. Us
|
|
|
5
5
|
|
|
6
6
|
# Compare Rango with other React frameworks
|
|
7
7
|
|
|
8
|
+
This skill positions Rango against Next.js App Router, TanStack Start, and Waku
|
|
9
|
+
on capabilities and architecture. Use it for "why Rango" questions, adoption
|
|
10
|
+
memos, and fact-checking a comparative claim. For the mechanics of actually
|
|
11
|
+
porting an app, use `/migrate-nextjs` or `/migrate-react-router`.
|
|
12
|
+
|
|
8
13
|
Use the canonical [framework comparison](references/framework-comparison.md) as
|
|
9
14
|
the factual baseline. Read the sections relevant to the question; read the full
|
|
10
15
|
reference when producing an overall evaluation or editing the comparison itself.
|