@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
|
@@ -1,26 +1,35 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: prerender
|
|
3
|
-
description: Pre-render route segments at build time with Prerender
|
|
3
|
+
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.
|
|
4
4
|
argument-hint: [passthrough]
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Pre-rendering with Prerender
|
|
8
8
|
|
|
9
|
-
Pre-rendering is **caching at build time**.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
Pre-rendering is **caching at build time**. `Prerender()` renders a route's
|
|
10
|
+
segments once per known param set during `vite build`, and `Static()` renders a
|
|
11
|
+
single segment once. Same serialization format, same deserialization path, same
|
|
12
|
+
segment system as the runtime `cache()`. The worker handles every request --
|
|
13
|
+
there are NO static .html or .rsc files served from assets. At runtime the
|
|
14
|
+
worker reads the pre-computed Flight payloads instead of executing handler code,
|
|
15
|
+
exactly like a cache hit; middleware and loaders still run on every request.
|
|
16
|
+
|
|
17
|
+
Use it when the page content is known at build time (markdown files, a CMS
|
|
18
|
+
snapshot, a fixed list of products) or needs build-only APIs such as `node:fs`.
|
|
19
|
+
The handler code and its imports are removed from the production bundle.
|
|
13
20
|
|
|
14
21
|
## Not this skill if…
|
|
15
22
|
|
|
16
|
-
- You want a cached HTML shell captured at runtime, with holes
|
|
17
|
-
|
|
23
|
+
- You want a cached HTML shell captured at runtime, with holes staying live
|
|
24
|
+
per request (loaders without `ssr: false` run per request; `ssr: false`
|
|
25
|
+
loaders bake) — see `/ppr`.
|
|
18
26
|
- You want runtime segment caching with TTL/SWR — that is the `cache()` DSL:
|
|
19
27
|
see `/caching`. Prerender is the same cache filled at build time.
|
|
28
|
+
- You are unsure which cache layer you need — start at `/cache-guide`.
|
|
20
29
|
|
|
21
30
|
## API: Prerender
|
|
22
31
|
|
|
23
|
-
###
|
|
32
|
+
### Route without params
|
|
24
33
|
|
|
25
34
|
```typescript
|
|
26
35
|
import { Prerender } from "@rangojs/router";
|
|
@@ -96,7 +105,7 @@ functions — no `ctx.build` branching needed.
|
|
|
96
105
|
| Unknown params | Handler evicted, no live fallback | Live handler runs at request time |
|
|
97
106
|
| `ctx.passthrough()` | Throws (not on Passthrough route) | Skips artifact, defers to live handler |
|
|
98
107
|
| Bundle size | Build handler code + imports removed | Build handler evicted, live handler kept |
|
|
99
|
-
| `revalidate()` |
|
|
108
|
+
| `revalidate()` | No effect on prerendered segments | Allowed (live handler can re-render) |
|
|
100
109
|
| `loading()` | Ignored (segments fully resolved) | Works for live fallback renders |
|
|
101
110
|
|
|
102
111
|
### When to use Passthrough
|
|
@@ -138,12 +147,19 @@ interface BuildContext<TParams> {
|
|
|
138
147
|
search?: Record<string, unknown>,
|
|
139
148
|
): string; // URL generation
|
|
140
149
|
passthrough(): PrerenderPassthroughResult; // Skip local artifact (Passthrough routes only)
|
|
141
|
-
dynamic(): void; // No-op in Prerender/Static handlers; use middleware for PPR shell opt-out
|
|
142
150
|
env: DefaultEnv; // Available when buildEnv is configured in rango() (throws otherwise)
|
|
143
|
-
//
|
|
151
|
+
// ctx.request, ctx.res, ctx.headers throw: there is no request at build time.
|
|
152
|
+
// ctx.waitUntil() is a no-op. ctx.dynamic() exists at runtime but is a no-op
|
|
153
|
+
// here -- opt a URL out of a build shell from middleware instead.
|
|
144
154
|
}
|
|
145
155
|
```
|
|
146
156
|
|
|
157
|
+
`getParams` receives a smaller `GetParamsContext` (`build`, `dev`, `env`, `set`,
|
|
158
|
+
`reverse`). Values it stores with `ctx.set()` are copied into every param set's
|
|
159
|
+
handler context and read there with `ctx.get()`. `env` is the `buildEnv` from
|
|
160
|
+
`rango()` — build-time bindings shared by the whole build, not a live request
|
|
161
|
+
env.
|
|
162
|
+
|
|
147
163
|
Use `createVar<T>()` to share typed data from a Prerender handler to child layouts:
|
|
148
164
|
|
|
149
165
|
```typescript
|
|
@@ -199,6 +215,13 @@ export const BlogPost = cph(getParams, handler);
|
|
|
199
215
|
All patterns support whole-file stubbing, expression stubbing, and build-time
|
|
200
216
|
module tracking. The same applies to `Static`.
|
|
201
217
|
|
|
218
|
+
Anything else gets no build-injected id, and the call throws
|
|
219
|
+
`Prerender: missing $$id` when the module loads. Unsupported shapes include
|
|
220
|
+
`export let`/`export var`, and calling `Prerender(...)` inline — for example
|
|
221
|
+
directly inside `path()`. Declare it as an exported `const` and pass the
|
|
222
|
+
binding. (`Passthrough(def, liveHandler)` needs no id and can be written inline
|
|
223
|
+
in `path()`.)
|
|
224
|
+
|
|
202
225
|
## Handler Eviction
|
|
203
226
|
|
|
204
227
|
In production builds, `Prerender` exports are replaced with stubs:
|
|
@@ -221,46 +244,81 @@ In client and SSR environments, ALL prerender handlers are always stubbed.
|
|
|
221
244
|
|
|
222
245
|
## Sub-use Semantics
|
|
223
246
|
|
|
224
|
-
Everything inside the path's use() callback is part of the
|
|
225
|
-
pre-rendered:
|
|
247
|
+
Everything inside the path's use() callback is part of the pre-rendered route
|
|
248
|
+
subtree and gets pre-rendered. Loaders are the exception — they stay live:
|
|
226
249
|
|
|
227
250
|
```typescript
|
|
228
251
|
path("/blog/:slug", BlogPost, { name: "blog.post" }, () => [
|
|
229
|
-
layout(<PostLayout />, () => [ // inside
|
|
252
|
+
layout(<PostLayout />, () => [ // inside the route -> pre-rendered
|
|
230
253
|
loader(PostMetaLoader), // live at runtime, bundled normally
|
|
231
254
|
]),
|
|
232
|
-
parallel({ "@sidebar": BlogSidebar }), // inside
|
|
255
|
+
parallel({ "@sidebar": BlogSidebar }), // inside the route -> pre-rendered
|
|
233
256
|
])
|
|
234
257
|
```
|
|
235
258
|
|
|
236
|
-
|
|
237
|
-
|
|
259
|
+
Only the route's own `Prerender` handler is evicted from the bundle. If a
|
|
260
|
+
parallel or child layout uses build-only APIs such as `node:fs`, wrap it in
|
|
261
|
+
`Static()` (see "Static segments" below) so the Vite plugin can stub it too.
|
|
262
|
+
`layout()` and `parallel()` accept `Static()` definitions; they do not accept
|
|
263
|
+
`Prerender()` definitions.
|
|
238
264
|
|
|
239
265
|
```typescript
|
|
240
|
-
// sidebar.tsx -- uses node:fs, must be
|
|
241
|
-
|
|
266
|
+
// sidebar.tsx -- uses node:fs, so it must be stubbed out of the bundle
|
|
267
|
+
import { Static } from "@rangojs/router";
|
|
268
|
+
|
|
269
|
+
export const BlogSidebar = Static(async () => {
|
|
242
270
|
const files = await fs.readdir("content/blog/");
|
|
243
|
-
return <Sidebar posts={files.map(f => basename(f, ".md"))} />;
|
|
271
|
+
return <Sidebar posts={files.map((f) => basename(f, ".md"))} />;
|
|
244
272
|
});
|
|
245
273
|
|
|
246
274
|
// urls.tsx
|
|
247
275
|
path("/blog/:slug", BlogPost, { name: "blog.post" }, () => [
|
|
248
|
-
parallel({ "@sidebar": BlogSidebar }),
|
|
276
|
+
parallel({ "@sidebar": BlogSidebar }), // stubbable, node:fs excluded
|
|
249
277
|
])
|
|
250
278
|
```
|
|
251
279
|
|
|
280
|
+
## Static segments
|
|
281
|
+
|
|
282
|
+
`Static(handler, options?)` renders ONE segment once at build time. It has no
|
|
283
|
+
params and produces no URLs; it works on `layout()`, `parallel()`, and `path()`.
|
|
284
|
+
Use it for build-time chrome such as a docs navigation built from files, or for
|
|
285
|
+
a static route with no params.
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
import { Static } from "@rangojs/router";
|
|
289
|
+
|
|
290
|
+
export const DocsNav = Static(async (ctx) => {
|
|
291
|
+
const docs = await readDocsIndex(); // build-only I/O
|
|
292
|
+
return <Nav docs={docs} />;
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
// urls.tsx
|
|
296
|
+
layout(DocsNav, () => [
|
|
297
|
+
path("/docs/:slug", DocPage, { name: "doc" }),
|
|
298
|
+
]);
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
- The handler receives `StaticBuildContext`: `build`, `dev`, `env` (with
|
|
302
|
+
`buildEnv`), `get`/`set`, `use(handle)`, and `reverse`. `params`, `url`,
|
|
303
|
+
`pathname`, and `request` throw.
|
|
304
|
+
- `Static(handler, { passthrough: true })` skips the build render and keeps the
|
|
305
|
+
handler in the bundle, rendering live at request time.
|
|
306
|
+
- `Static()` always renders sequentially (no `concurrency` option) and supports
|
|
307
|
+
`throw new Skip()` (see "Skipping Entries with Skip").
|
|
308
|
+
- The same export rules as `Prerender` apply (`export const X = Static(...)`).
|
|
309
|
+
|
|
252
310
|
## Interaction with DSL Items
|
|
253
311
|
|
|
254
|
-
| DSL item | Behavior with Prerender
|
|
255
|
-
| -------------- |
|
|
256
|
-
| `loader()` | Live at runtime, bundled normally. Use `cache()` for caching.
|
|
257
|
-
| `revalidate()` |
|
|
258
|
-
| `cache()` | Orthogonal --
|
|
259
|
-
| `layout()` | Child layouts inside path are pre-rendered. Parent layouts are live.
|
|
260
|
-
| `parallel()` | Parallel slots inside path are pre-rendered.
|
|
261
|
-
| `middleware()` | Skipped while collecting build-time Flight payloads (no request). For `Prerender` + `ppr`,
|
|
262
|
-
| `loading()` | Ignored without Passthrough. Works for live fallback with Passthrough.
|
|
263
|
-
| `intercept()` | Pre-rendered at build time. Intercept variant stored under `/i` key alongside main segments. At runtime, the correct variant is served based on `ctx.isIntercept`. `when` config conditions are skipped at build time (all intercepts are pre-rendered unconditionally).
|
|
312
|
+
| DSL item | Behavior with Prerender |
|
|
313
|
+
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
314
|
+
| `loader()` | Live at runtime, bundled normally. Use `cache()` for caching. |
|
|
315
|
+
| `revalidate()` | Without Passthrough: no effect on the prerendered segments (re-served from the build artifact); loader revalidation still works. With Passthrough: re-renders through the live handler. |
|
|
316
|
+
| `cache()` | Orthogonal -- prerendered segments bypass the runtime cache. Use `cache()` on parent layouts and loaders. |
|
|
317
|
+
| `layout()` | Child layouts inside path are pre-rendered. Parent layouts are live. |
|
|
318
|
+
| `parallel()` | Parallel slots inside path are pre-rendered. |
|
|
319
|
+
| `middleware()` | Skipped while collecting build-time Flight payloads (no request). For `Prerender` + `ppr`, the build-shell step replays global and route middleware with `ctx.build === true`; `ctx.dynamic()` skips that shell. At request time middleware runs normally on every request. |
|
|
320
|
+
| `loading()` | Ignored without Passthrough. Works for live fallback with Passthrough. |
|
|
321
|
+
| `intercept()` | Pre-rendered at build time. Intercept variant stored under `/i` key alongside main segments. At runtime, the correct variant is served based on `ctx.isIntercept`. `when` config conditions are skipped at build time (all intercepts are pre-rendered unconditionally). |
|
|
264
322
|
|
|
265
323
|
When Passthrough revalidation is enabled, remember that revalidation is
|
|
266
324
|
still partial: opting a child segment into revalidation does not
|
|
@@ -269,9 +327,16 @@ implicitly re-run outer prerender-derived handlers/layouts.
|
|
|
269
327
|
## Prerender + PPR Build Shells
|
|
270
328
|
|
|
271
329
|
A `Prerender` page may also declare `ppr` on the path option. The build still
|
|
272
|
-
stores the Flight payload first. After that,
|
|
273
|
-
shell for each generated URL so the first document
|
|
274
|
-
`x-rango-shell: HIT`.
|
|
330
|
+
stores the Flight payload first. After that, the build-time shell capture
|
|
331
|
+
tries to bake the HTML shell for each generated URL so the first document
|
|
332
|
+
request can be an `x-rango-shell: HIT`. A route partitioned by
|
|
333
|
+
`cache({ key })` or a store `keyGenerator` never serves that build shell (the
|
|
334
|
+
build captured one partition); each partition captures at runtime, a
|
|
335
|
+
once-per-route warning says so, and a `keyGenerator` that returns the default
|
|
336
|
+
key unchanged keeps it. When the route's `cache()` scope (its own, or one
|
|
337
|
+
inherited from a layout) refuses a request — `cache(false)`, or a
|
|
338
|
+
`condition()` that returns false — that request gets no shell at all, the
|
|
339
|
+
build shell included: it renders like a cache miss.
|
|
275
340
|
|
|
276
341
|
That shell capture is request-shaped enough to run middleware safely:
|
|
277
342
|
|
|
@@ -284,6 +349,11 @@ Use `ctx.build` inside middleware to avoid runtime-only side effects during
|
|
|
284
349
|
build shell capture, or call `ctx.dynamic()` to leave that route to runtime
|
|
285
350
|
PPR. Runtime requests still run the normal middleware chain.
|
|
286
351
|
|
|
352
|
+
Build shells are keyed by pathname and served only for requests without a query
|
|
353
|
+
string (after `cache.searchParams` filtering). A URL with search params has its
|
|
354
|
+
own shell identity and is captured at runtime. The runtime shell store is read
|
|
355
|
+
first, so a runtime capture supersedes the baked entry once it exists.
|
|
356
|
+
|
|
287
357
|
### Freshness of a build shell
|
|
288
358
|
|
|
289
359
|
A build-baked shell is not on a wall clock the way a pure runtime `ppr` shell is.
|
|
@@ -299,30 +369,32 @@ entry STILL serves and a runtime recapture is scheduled that upgrades it in plac
|
|
|
299
369
|
(SWR is the upgrade path from build entry → fresher runtime entry). Because the
|
|
300
370
|
`Prerender` handler is evicted from the production bundle, that recapture never
|
|
301
371
|
re-runs the handler — it replays the same build-time segments and only refreshes
|
|
302
|
-
`cache()`-scoped data baked into the shell
|
|
303
|
-
`
|
|
372
|
+
what the capture reads again: `cache()`-scoped data baked into the shell, and
|
|
373
|
+
the data of `ssr: false` loaders, which run at every capture. **If the shell
|
|
374
|
+
bakes neither, `ttl` has nothing to refresh** — reach for `updateTag` (or a
|
|
304
375
|
redeploy) instead of a shorter `ttl`.
|
|
305
376
|
|
|
306
|
-
`ctx.dynamic()` opts a request off the shell
|
|
377
|
+
`ctx.dynamic()` opts a request off the shell ONLY. A `Prerender` route has
|
|
307
378
|
no live handler to fall back to (it was evicted), so a `dynamic()` request still
|
|
308
|
-
serves the build-baked
|
|
309
|
-
|
|
379
|
+
serves the build-baked segments — fresh loaders, not a fresh handler render.
|
|
380
|
+
There is no "fully dynamic" render for a prerendered route.
|
|
310
381
|
|
|
311
382
|
## Dev Mode
|
|
312
383
|
|
|
313
|
-
In dev
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
384
|
+
In dev there is no build pass and no handler stubbing. Instead, a request to a
|
|
385
|
+
prerendered route is rendered **on demand** through the dev server's
|
|
386
|
+
`/__rsc_prerender` endpoint, which runs the same build-time resolution in
|
|
387
|
+
Node.js (so `node:fs` and `buildEnv` work even when the app itself runs in
|
|
388
|
+
workerd). This applies to both the Node and the Cloudflare presets.
|
|
389
|
+
|
|
390
|
+
- The handler receives `BuildContext` (`ctx.build === true`, `ctx.dev === true`),
|
|
391
|
+
and segments resolve exactly as in the production prerender.
|
|
392
|
+
- Results are memoized until you edit a file in the router's module graph, so
|
|
393
|
+
`getParams()` and handler side effects run once per edit, not once per request.
|
|
394
|
+
The endpoint reports `x-rango-prerender-cache: HIT | MISS`.
|
|
395
|
+
- If the on-demand render has no entry for the URL (unknown param, `Skip`,
|
|
396
|
+
`ctx.passthrough()`, or a render error, which is logged), the request falls
|
|
397
|
+
through to a live render — the Passthrough live handler when there is one.
|
|
326
398
|
|
|
327
399
|
## Storage Layout
|
|
328
400
|
|
|
@@ -378,13 +450,28 @@ export const BlogPost = Prerender(
|
|
|
378
450
|
},
|
|
379
451
|
);
|
|
380
452
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
To serve skipped params live at runtime, give the definition its own name and
|
|
456
|
+
wrap it with `Passthrough()`; the live handler renders them:
|
|
457
|
+
|
|
458
|
+
```typescript
|
|
459
|
+
import { Prerender, Passthrough, Skip } from "@rangojs/router";
|
|
460
|
+
|
|
461
|
+
export const BlogPostDef = Prerender(
|
|
462
|
+
async () => [{ slug: "published" }, { slug: "draft" }],
|
|
463
|
+
async (ctx) => {
|
|
464
|
+
if (ctx.params.slug === "draft") {
|
|
465
|
+
throw new Skip("Draft articles are not pre-rendered");
|
|
466
|
+
}
|
|
467
|
+
return <PostPage slug={ctx.params.slug} />;
|
|
468
|
+
},
|
|
469
|
+
);
|
|
470
|
+
|
|
471
|
+
// Live handler: runs at request time for "draft" and any unknown slug
|
|
472
|
+
export const BlogPost = Passthrough(BlogPostDef, async (ctx) => (
|
|
473
|
+
<PostPage slug={ctx.params.slug} />
|
|
474
|
+
));
|
|
388
475
|
```
|
|
389
476
|
|
|
390
477
|
Skipped entries are excluded from the build output. With `Passthrough()`,
|
|
@@ -416,6 +503,12 @@ rango({ prerender: { onError: "warn" } }); // default is "fail"
|
|
|
416
503
|
| `return ctx.passthrough()` | Skip entry, log PASS (Passthrough routes) | Skip entry, log PASS |
|
|
417
504
|
| `throw new Skip("reason")` | Skip entry, log SKIP, continue | Skip entry, log SKIP, continue |
|
|
418
505
|
| `throw new Error("reason")` | Log FAIL, stop ALL pre-rendering, fail build | Log WARN, skip the URL, continue |
|
|
506
|
+
| A child component throws | Log FAIL, stop ALL pre-rendering, fail build | Log WARN, skip the URL, continue |
|
|
507
|
+
|
|
508
|
+
The last row covers a handler that returns fine but whose tree holds an async
|
|
509
|
+
server component that throws while the page is rendered at build, for example
|
|
510
|
+
because its fetch fails. That error goes through the same policy instead of being
|
|
511
|
+
baked as an error row, and a `Skip` thrown there skips the URL.
|
|
419
512
|
|
|
420
513
|
With `"warn"` the errored entry is logged and left un-baked (never served as a baked
|
|
421
514
|
200 error page). `"warn"` is a build-unblock, not a runtime contract: the route falls
|
|
@@ -427,7 +520,8 @@ fallback) or `throw new Skip()` (an intentional skip — works in the render fn,
|
|
|
427
520
|
only `getParams()`); otherwise prefer the default `"fail"`.
|
|
428
521
|
|
|
429
522
|
Both `Skip` and hard errors propagate to the router's `onError` callback with phase
|
|
430
|
-
`"prerender"` or `"static"
|
|
523
|
+
`"prerender"` or `"static"`; skipped entries (a `Skip`, or an error under
|
|
524
|
+
`"warn"`) carry `metadata.skipped: true`.
|
|
431
525
|
|
|
432
526
|
### Build logs
|
|
433
527
|
|
|
@@ -454,13 +548,9 @@ the build continues.
|
|
|
454
548
|
|
|
455
549
|
### Dev mode behavior
|
|
456
550
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
**Non-Node runtimes using `/__rsc_prerender`** — `Skip` participates in the
|
|
461
|
-
on-demand prerender path, so build-style skip logic does run for that request.
|
|
462
|
-
The dev prerender endpoint treats it like a prerender miss and the request
|
|
463
|
-
falls back according to normal dev/runtime behavior.
|
|
551
|
+
In dev, `Skip` runs inside the on-demand `/__rsc_prerender` render, so
|
|
552
|
+
build-style skip logic runs for that request. The endpoint treats it as a
|
|
553
|
+
prerender miss and the request falls through to a live render (see "Dev Mode").
|
|
464
554
|
|
|
465
555
|
## Per-Param Passthrough with ctx.passthrough()
|
|
466
556
|
|
|
@@ -553,6 +643,11 @@ Passthrough entries are logged distinctly:
|
|
|
553
643
|
Loaders on pre-rendered routes run at request time. They are bundled normally
|
|
554
644
|
and need `cache()` for caching. Do not use build-only APIs in loaders.
|
|
555
645
|
|
|
646
|
+
The exception is an `ssr: false` loader on a `Prerender` + `ppr` route: the
|
|
647
|
+
build-time shell capture runs it and bakes its settled data into the shell,
|
|
648
|
+
and a shell HIT runs it only when its return carries promises (`/ppr` → "The
|
|
649
|
+
bake lane"). The Flight payload collection itself still skips loaders.
|
|
650
|
+
|
|
556
651
|
### Build-time handle data is frozen
|
|
557
652
|
|
|
558
653
|
Handle values pushed via `ctx.use()` DURING pre-rendering (handler pushes at
|
|
@@ -564,23 +659,48 @@ say) is request-time data — delivery follows the loader race model, see
|
|
|
564
659
|
|
|
565
660
|
### Server actions work normally
|
|
566
661
|
|
|
567
|
-
Actions
|
|
568
|
-
|
|
569
|
-
|
|
662
|
+
Actions run normally; what changes is the re-render after them. Loaders are live
|
|
663
|
+
and are revalidated by actions as usual.
|
|
664
|
+
|
|
665
|
+
- **Plain `Prerender`**: the handler was evicted, so the action re-render serves
|
|
666
|
+
the stored prerender entry again. The prerendered output stays frozen; the
|
|
667
|
+
action's return value reaches the client as usual.
|
|
668
|
+
- **`Passthrough()`**: the action re-render runs the live handler, replacing the
|
|
669
|
+
prerendered output. To keep the frozen tree mounted after actions (for example
|
|
670
|
+
so a client component's form state survives), suppress action
|
|
671
|
+
revalidation on the route while keeping navigation defaults:
|
|
672
|
+
`revalidate((ctx) => (ctx.isAction() ? false : undefined))`.
|
|
673
|
+
|
|
674
|
+
A handler may also embed an inline `"use server"` action that closes over
|
|
675
|
+
build-time values; the captured values are frozen at build and the action body
|
|
676
|
+
runs live when invoked.
|
|
570
677
|
|
|
571
678
|
### Empty getParams
|
|
572
679
|
|
|
573
680
|
If `getParams` returns an empty array, no Flight payloads are written. No error.
|
|
681
|
+
Every request to the route then behaves like an unknown param.
|
|
574
682
|
|
|
575
683
|
### Route name is required
|
|
576
684
|
|
|
577
685
|
Routes using `Prerender` must have a `name` in path options.
|
|
578
686
|
The name is used as the storage key for Flight payloads.
|
|
579
687
|
|
|
580
|
-
###
|
|
688
|
+
### revalidate() needs Passthrough
|
|
689
|
+
|
|
690
|
+
Without `Passthrough()` the handler is evicted, so there is nothing to
|
|
691
|
+
re-render: a revalidation re-serves the prerendered segments from the build
|
|
692
|
+
artifact. `revalidate()` on the route's loaders still works. No warning is
|
|
693
|
+
emitted — wrap the route in `Passthrough()` when its segments must re-render.
|
|
694
|
+
|
|
695
|
+
### Tag invalidation does not reach prerendered segments
|
|
581
696
|
|
|
582
|
-
|
|
583
|
-
|
|
697
|
+
`updateTag()`/`revalidateTag()` evict runtime cache entries. They do not refresh
|
|
698
|
+
a prerendered route's build-time Flight payload, which is served before the tag
|
|
699
|
+
system is consulted, and a `cacheTag()` inside a `"use cache"` function that runs
|
|
700
|
+
during the build has no runtime effect. A redeploy replaces the payload. To make
|
|
701
|
+
a route tag-invalidatable, serve it from the runtime cache instead (`cache()`,
|
|
702
|
+
or a `Passthrough()` live handler). A build-baked **ppr shell** is different: a
|
|
703
|
+
tag it carries does drop it (see "Freshness of a build shell").
|
|
584
704
|
|
|
585
705
|
### loading() is ignored without Passthrough
|
|
586
706
|
|
|
@@ -589,11 +709,13 @@ With `Passthrough()`, `loading()` works for live fallback renders.
|
|
|
589
709
|
|
|
590
710
|
## Complete Example
|
|
591
711
|
|
|
712
|
+
Known guides are pre-rendered; any other slug is rendered live by the
|
|
713
|
+
Passthrough handler.
|
|
714
|
+
|
|
592
715
|
```typescript
|
|
593
716
|
// pages/guides-handler.tsx
|
|
594
717
|
import { Prerender, Passthrough } from "@rangojs/router";
|
|
595
718
|
import { Link } from "@rangojs/router/client";
|
|
596
|
-
import { href } from "../router.js";
|
|
597
719
|
|
|
598
720
|
const knownGuides: Record<string, string> = {
|
|
599
721
|
routing: "Routing Guide",
|
|
@@ -609,9 +731,9 @@ export const GuidesDetailDef = Prerender<{ slug: string }>(
|
|
|
609
731
|
<h1>{title}</h1>
|
|
610
732
|
<p>Slug: {ctx.params.slug}</p>
|
|
611
733
|
<nav>
|
|
612
|
-
<Link to={
|
|
734
|
+
<Link to={ctx.reverse("guides.detail", { slug: "routing" })}>Routing</Link>
|
|
613
735
|
{" | "}
|
|
614
|
-
<Link to={
|
|
736
|
+
<Link to={ctx.reverse("guides.detail", { slug: "dynamic-test" })}>Dynamic</Link>
|
|
615
737
|
</nav>
|
|
616
738
|
</div>
|
|
617
739
|
);
|
|
@@ -625,9 +747,9 @@ export const GuidesDetail = Passthrough(GuidesDetailDef, async (ctx) => {
|
|
|
625
747
|
<h1>{title}</h1>
|
|
626
748
|
<p>Slug: {ctx.params.slug}</p>
|
|
627
749
|
<nav>
|
|
628
|
-
<Link to={
|
|
750
|
+
<Link to={ctx.reverse("guides.detail", { slug: "routing" })}>Routing</Link>
|
|
629
751
|
{" | "}
|
|
630
|
-
<Link to={
|
|
752
|
+
<Link to={ctx.reverse("guides.detail", { slug: "dynamic-test" })}>Dynamic</Link>
|
|
631
753
|
</nav>
|
|
632
754
|
</div>
|
|
633
755
|
);
|
|
@@ -711,41 +833,21 @@ Loaders run fresh at request time for both variants.
|
|
|
711
833
|
|
|
712
834
|
Pre-rendered routes set flags on the route trie leaf at build time:
|
|
713
835
|
|
|
714
|
-
- `pr: true` -- route has pre-rendered
|
|
836
|
+
- `pr: true` -- route has pre-rendered segment data
|
|
715
837
|
- `pt: true` -- route wrapped with `Passthrough()` (live handler available)
|
|
716
838
|
|
|
717
839
|
At runtime, the cache-lookup middleware uses these flags:
|
|
718
840
|
|
|
719
841
|
- `pr + hit` -- serve pre-rendered Flight payload
|
|
720
842
|
- `pr + pt + miss` -- fall through to Passthrough live handler
|
|
721
|
-
- `pr + miss` (no pt) -- fall through
|
|
722
|
-
|
|
723
|
-
## Contributor Checklist
|
|
724
|
-
|
|
725
|
-
Before changing prerender behavior, run these tests.
|
|
726
|
-
|
|
727
|
-
### Tests to run
|
|
728
|
-
|
|
729
|
-
```bash
|
|
730
|
-
# Core prerender e2e (Passthrough, eviction, loaders, sub-use, intercept)
|
|
731
|
-
pnpm --filter @rangojs/router exec playwright test prerender
|
|
732
|
-
|
|
733
|
-
# Prerender-specific unit test
|
|
734
|
-
pnpm --filter @rangojs/router run test:unit -- prerender-passthrough
|
|
735
|
-
|
|
736
|
-
# Semantic matrix (prerender rows cover intercept + ctx propagation)
|
|
737
|
-
pnpm --filter @rangojs/router exec playwright test semantic-matrix
|
|
738
|
-
|
|
739
|
-
# Handler-first (ctx.set/get visibility with prerender handlers)
|
|
740
|
-
pnpm --filter @rangojs/router exec playwright test handler-first
|
|
741
|
-
```
|
|
843
|
+
- `pr + miss` (no pt) -- fall through to the stubbed handler, which throws a
|
|
844
|
+
not-found error ("No prerender data found for this route"); there is no live render
|
|
742
845
|
|
|
743
|
-
|
|
846
|
+
## Related
|
|
744
847
|
|
|
745
|
-
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
-
|
|
749
|
-
|
|
750
|
-
-
|
|
751
|
-
fallback, intercept variant selection) must work in the production build.
|
|
848
|
+
- `/cache-guide` — how prerendering compares with the runtime cache layers
|
|
849
|
+
- `/caching` — runtime `cache()` segments and loader caching
|
|
850
|
+
- `/ppr` — the `ppr` path option; combine with `Prerender` for build-time shells
|
|
851
|
+
- `/shell-manifest` — prerendered shell feeding ids to a live loader
|
|
852
|
+
- `/deployment-caching` — why prerender output is not a CDN static file
|
|
853
|
+
- `/loader` — loaders stay live on prerendered routes
|