@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,24 +1,127 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
/// <reference path="../flight-runtime.d.ts" />
|
|
2
|
+
/**
|
|
3
|
+
* Stub for `@vitejs/plugin-rsc/rsc` and the split `/rsc/server`, `/rsc/client`
|
|
4
|
+
* entries, shipped so consumers do not have to write a per-file `vi.mock(...)`.
|
|
5
|
+
* The real entries top-level import Vite virtuals that do not resolve in plain
|
|
6
|
+
* node.
|
|
7
|
+
*
|
|
8
|
+
* Under the `react-server` condition (the Flight project) the "use cache"
|
|
9
|
+
* codec runs on real Flight: the vendored react-server-dom `server.edge` /
|
|
10
|
+
* `client.edge` builds that plugin-rsc's `react/rsc/server` and
|
|
11
|
+
* `react/rsc/client` wrap, with the same manifests and the same server-side
|
|
12
|
+
* reference loader (`@vitejs/plugin-rsc/core/rsc` `setRequireModule`), so
|
|
13
|
+
* keys, writes, hits, value round trips and error rows match a build. The
|
|
14
|
+
* wrappers are not reused: their manifests read `import.meta.env.DEV`, which
|
|
15
|
+
* is undefined in a module node loads directly (vitest externalizes
|
|
16
|
+
* node_modules).
|
|
17
|
+
*
|
|
18
|
+
* Without the condition React's server build refuses to load, so the codec
|
|
19
|
+
* functions throw and a "use cache" call runs uncached. Any other load failure
|
|
20
|
+
* (a moved vendored path, a missing peer) throws. The action entries stay
|
|
21
|
+
* inert either way: no primitive decodes an action request.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/** React's server build throws this on load without the react-server condition. */
|
|
25
|
+
const MISSING_REACT_SERVER_CONDITION =
|
|
26
|
+
/"react-server" condition must be enabled/;
|
|
27
|
+
|
|
28
|
+
async function loadFlightRuntime() {
|
|
29
|
+
// The server build first, alone. `@vitejs/plugin-rsc/core/rsc` statically
|
|
30
|
+
// imports it, and importing that ESM module after the CJS build failed to
|
|
31
|
+
// load leaks an unhandled rejection from Node's module loader even when every
|
|
32
|
+
// import() is caught (Node 22 and 24). So core/rsc loads only once the server
|
|
33
|
+
// build has.
|
|
34
|
+
const server =
|
|
35
|
+
await import("@vitejs/plugin-rsc/vendor/react-server-dom/server.edge").catch(
|
|
36
|
+
(error: unknown) => {
|
|
37
|
+
if (
|
|
38
|
+
error instanceof Error &&
|
|
39
|
+
MISSING_REACT_SERVER_CONDITION.test(error.message)
|
|
40
|
+
) {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
throw error;
|
|
44
|
+
},
|
|
45
|
+
);
|
|
46
|
+
if (!server) return undefined;
|
|
47
|
+
const [client, core] = await Promise.all([
|
|
48
|
+
import("@vitejs/plugin-rsc/vendor/react-server-dom/client.edge"),
|
|
49
|
+
import("@vitejs/plugin-rsc/core/rsc"),
|
|
50
|
+
]);
|
|
51
|
+
await import("../internal/flight-client-globals.js");
|
|
52
|
+
// Resolves the `$$decode-client:` / `$$preserve:` ids a cached value's client
|
|
53
|
+
// and server references decode to; any other id would load a server module.
|
|
54
|
+
core.setRequireModule({
|
|
55
|
+
load: (id) => {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`plugin-rsc stub: server reference module "${id}" is not loadable in a test`,
|
|
58
|
+
);
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
return { server, client, core };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const runtime = await loadFlightRuntime();
|
|
65
|
+
|
|
66
|
+
/** `<module id>#<export name>` -> manifest entry, as plugin-rsc builds it. */
|
|
67
|
+
function referenceManifest(prefix: string): Record<string, unknown> {
|
|
68
|
+
return new Proxy(
|
|
69
|
+
{},
|
|
70
|
+
{
|
|
71
|
+
get(_target, $$id) {
|
|
72
|
+
if (typeof $$id !== "string") return undefined;
|
|
73
|
+
const [id, name] = $$id.split("#");
|
|
74
|
+
return { id: prefix + id, name, chunks: [], async: true };
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const CLIENT_MANIFEST = referenceManifest("");
|
|
81
|
+
|
|
82
|
+
function unavailable(name: string): never {
|
|
83
|
+
throw new Error(
|
|
84
|
+
`plugin-rsc stub: ${name} needs the react-server condition (the Flight test project)`,
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export const renderToReadableStream = (
|
|
89
|
+
value: unknown,
|
|
90
|
+
options?: object,
|
|
91
|
+
): ReadableStream<Uint8Array> =>
|
|
92
|
+
runtime
|
|
93
|
+
? runtime.server.renderToReadableStream(value, CLIENT_MANIFEST, options)
|
|
94
|
+
: unavailable("renderToReadableStream");
|
|
95
|
+
export const createTemporaryReferenceSet = (): unknown =>
|
|
96
|
+
runtime ? runtime.server.createTemporaryReferenceSet() : {};
|
|
97
|
+
export const createFromReadableStream = (
|
|
98
|
+
stream: ReadableStream<Uint8Array>,
|
|
99
|
+
options?: object,
|
|
100
|
+
extraOptions?: { preserveServerReferences?: boolean },
|
|
101
|
+
): Promise<unknown> =>
|
|
102
|
+
runtime
|
|
103
|
+
? runtime.client.createFromReadableStream(stream, {
|
|
104
|
+
serverConsumerManifest: {
|
|
105
|
+
serverModuleMap: referenceManifest(
|
|
106
|
+
extraOptions?.preserveServerReferences
|
|
107
|
+
? "$$server:$$preserve:"
|
|
108
|
+
: "$$server:",
|
|
109
|
+
),
|
|
110
|
+
moduleMap: runtime.core.createServerDecodeClientManifest(),
|
|
111
|
+
},
|
|
112
|
+
...options,
|
|
113
|
+
})
|
|
114
|
+
: unavailable("createFromReadableStream");
|
|
115
|
+
export const encodeReply = (
|
|
116
|
+
value: unknown,
|
|
117
|
+
options?: object,
|
|
118
|
+
): Promise<string | FormData> =>
|
|
119
|
+
runtime
|
|
120
|
+
? runtime.client.encodeReply(value, options)
|
|
121
|
+
: unavailable("encodeReply");
|
|
122
|
+
export const createClientTemporaryReferenceSet = (): unknown =>
|
|
123
|
+
runtime ? runtime.client.createTemporaryReferenceSet() : {};
|
|
13
124
|
export const loadServerAction = (): undefined => undefined;
|
|
14
125
|
export const decodeReply = (): undefined => undefined;
|
|
15
126
|
export const decodeAction = (): undefined => undefined;
|
|
16
127
|
export const decodeFormState = (): undefined => undefined;
|
|
17
|
-
export const createTemporaryReferenceSet = (): Record<string, never> => ({});
|
|
18
|
-
export const encodeReply = (): never => {
|
|
19
|
-
throw new Error("plugin-rsc stub: encodeReply not available");
|
|
20
|
-
};
|
|
21
|
-
export const createClientTemporaryReferenceSet = (): Record<
|
|
22
|
-
string,
|
|
23
|
-
never
|
|
24
|
-
> => ({});
|
package/src/testing/vitest.ts
CHANGED
|
@@ -78,6 +78,10 @@
|
|
|
78
78
|
|
|
79
79
|
import { createRequire } from "node:module";
|
|
80
80
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
81
|
+
import {
|
|
82
|
+
isUseCacheCandidate,
|
|
83
|
+
transformUseCache,
|
|
84
|
+
} from "../vite/plugins/use-cache-transform.js";
|
|
81
85
|
|
|
82
86
|
/** A single Vite/Vitest resolve alias entry. Structurally a Vite `Alias`. */
|
|
83
87
|
export interface TestAlias {
|
|
@@ -262,6 +266,7 @@ interface FlightTransformPlugin {
|
|
|
262
266
|
* import { defineConfig } from "vitest/config";
|
|
263
267
|
* import {
|
|
264
268
|
* rangoUseClientTransform,
|
|
269
|
+
* rangoUseCacheTransform,
|
|
265
270
|
* rangoTestAliases,
|
|
266
271
|
* rangoInlineDeps,
|
|
267
272
|
* } from "@rangojs/router/testing/vitest";
|
|
@@ -271,7 +276,7 @@ interface FlightTransformPlugin {
|
|
|
271
276
|
* process.env.NODE_ENV = "production";
|
|
272
277
|
*
|
|
273
278
|
* export default defineConfig({
|
|
274
|
-
* plugins: [rangoUseClientTransform()],
|
|
279
|
+
* plugins: [rangoUseClientTransform(), rangoUseCacheTransform()],
|
|
275
280
|
* resolve: {
|
|
276
281
|
* conditions: ["react-server"],
|
|
277
282
|
* // Bare `@rangojs/router` -> its react-server build, so a handler/component
|
|
@@ -340,3 +345,59 @@ export function rangoUseClientTransform(): FlightTransformPlugin {
|
|
|
340
345
|
},
|
|
341
346
|
};
|
|
342
347
|
}
|
|
348
|
+
|
|
349
|
+
/** The Vite plugin shape {@link rangoUseCacheTransform} returns. */
|
|
350
|
+
interface UseCacheTransformPlugin {
|
|
351
|
+
name: string;
|
|
352
|
+
enforce: "post";
|
|
353
|
+
configResolved(config: { root: string }): void;
|
|
354
|
+
transform(
|
|
355
|
+
this: { warn(message: string): void },
|
|
356
|
+
code: string,
|
|
357
|
+
id: string,
|
|
358
|
+
): Promise<{ code: string; map: unknown } | undefined>;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* A Vite plugin that applies the rango plugin's `"use cache"` transform in a
|
|
363
|
+
* Vitest project, so a function written with the directive is wrapped with
|
|
364
|
+
* `registerCachedFunction` as in dev and a build. `rango()` runs that transform
|
|
365
|
+
* only in its `rsc` environment and Vitest transforms in `ssr`, so without this
|
|
366
|
+
* plugin the directive is an inert string and the function runs on every call.
|
|
367
|
+
*
|
|
368
|
+
* Add it to the react-server project next to {@link rangoUseClientTransform}
|
|
369
|
+
* (see that function's config). There, with a seeded `cacheStore`,
|
|
370
|
+
* `renderHandler` / `runLoader` observe real hits. In the node project the
|
|
371
|
+
* wrap applies too, but the stubbed Flight serializer cannot write an entry.
|
|
372
|
+
*
|
|
373
|
+
* Ids are the ones `vite dev` emits: `<path relative to the Vitest root>#<name>`
|
|
374
|
+
* (a function-level directive gives `src/data.ts#$$hoist_0_getData`), not the
|
|
375
|
+
* build's hashed path, so store keys stay readable. `configResolved` sets that
|
|
376
|
+
* root. If `@vitejs/plugin-rsc/transforms` fails to load, the transform throws
|
|
377
|
+
* instead of leaving the module unwrapped (which the rango plugin does).
|
|
378
|
+
*/
|
|
379
|
+
export function rangoUseCacheTransform(): UseCacheTransformPlugin {
|
|
380
|
+
let root = process.cwd();
|
|
381
|
+
return {
|
|
382
|
+
name: "rango:testing-use-cache",
|
|
383
|
+
enforce: "post",
|
|
384
|
+
configResolved(config) {
|
|
385
|
+
root = config.root;
|
|
386
|
+
},
|
|
387
|
+
async transform(code, id) {
|
|
388
|
+
if (!isUseCacheCandidate(code, id)) return undefined;
|
|
389
|
+
return transformUseCache(code, id, {
|
|
390
|
+
root,
|
|
391
|
+
isBuild: false,
|
|
392
|
+
warn: (message) => this.warn(message),
|
|
393
|
+
onTransformsError: (error) => {
|
|
394
|
+
throw new Error(
|
|
395
|
+
`rangoUseCacheTransform: @vitejs/plugin-rsc/transforms failed to ` +
|
|
396
|
+
`load, so "use cache" functions in ${id} would run unwrapped.`,
|
|
397
|
+
{ cause: error },
|
|
398
|
+
);
|
|
399
|
+
},
|
|
400
|
+
});
|
|
401
|
+
},
|
|
402
|
+
};
|
|
403
|
+
}
|
|
@@ -133,12 +133,13 @@ export function ThemeProvider({
|
|
|
133
133
|
setSystemTheme(getSystemTheme());
|
|
134
134
|
// Re-sync state from an EXPLICITLY stored theme after mount. initialTheme
|
|
135
135
|
// comes from the payload and can legitimately differ from the visitor's
|
|
136
|
-
// stored theme — on a PPR shell HIT it is deliberately the CAPTURE's
|
|
137
|
-
// (the resume tree must match the
|
|
138
|
-
// ShellCacheEntry.initialTheme). The FOUC script
|
|
139
|
-
// theme to the document pre-paint; this brings
|
|
140
|
-
// useTheme readers) in line with it, and is
|
|
141
|
-
// reads storage (the initializer must not —
|
|
136
|
+
// stored theme — on a PPR shell HIT it is deliberately the CAPTURE's
|
|
137
|
+
// initialTheme, the no-cookie default (the resume tree must match the
|
|
138
|
+
// frozen prelude; see ShellCacheEntry.initialTheme). The FOUC script
|
|
139
|
+
// already applied the stored theme to the document pre-paint; this brings
|
|
140
|
+
// the provider state (toggles, useTheme readers) in line with it, and is
|
|
141
|
+
// the ONLY place the provider reads storage (the initializer must not —
|
|
142
|
+
// see the parity note above).
|
|
142
143
|
// Only an explicit cookie/localStorage value re-syncs — a defaultTheme
|
|
143
144
|
// fallback must not override a server-provided initialTheme when the
|
|
144
145
|
// visitor never chose a theme.
|
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
*
|
|
9
9
|
* Must be placed in the <head> element of your document, before any stylesheets.
|
|
10
10
|
*
|
|
11
|
-
* Note: when theme is enabled in the router config, `<
|
|
11
|
+
* Note: when theme is enabled in the router config, `<Html.Meta />` ALREADY
|
|
12
12
|
* renders this FOUC script. Use `<ThemeScript />` only if you do NOT render
|
|
13
|
-
* `<
|
|
13
|
+
* `<Html.Meta />`. Rendering both is safe — the inline script guards the
|
|
14
14
|
* matchMedia listener registration against double-running — but it is redundant.
|
|
15
15
|
*
|
|
16
16
|
* @example
|
|
17
17
|
* ```tsx
|
|
18
|
-
* // In your document component. Use ThemeScript only when you do not render
|
|
18
|
+
* // In your document component. Use ThemeScript only when you do not render Html.Meta.
|
|
19
19
|
* import { ThemeScript } from "@rangojs/router/theme";
|
|
20
20
|
*
|
|
21
21
|
* export function Document({ children }) {
|
package/src/types/cache-types.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Context passed to cache condition/key/tags functions
|
|
2
|
+
* Context passed to cache condition/key/tags functions (the full
|
|
3
|
+
* RequestContext).
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* Ordering: global middleware wraps the whole request, and on RSC routes route
|
|
6
|
+
* middleware wraps the match/render pipeline (rsc/handler.ts executeRender), so
|
|
7
|
+
* variables they set before `next()` are readable via `ctx.get()`. On response
|
|
8
|
+
* routes the cache lookup runs BEFORE route middleware, which wraps only the
|
|
9
|
+
* handler run on a miss (rsc/response-route-handler.ts); only global-middleware
|
|
10
|
+
* variables are populated there.
|
|
10
11
|
*/
|
|
11
12
|
export type { RequestContext as CacheContext } from "../server/request-context.js";
|
|
12
13
|
|
|
@@ -109,7 +110,8 @@ export interface CacheOptions<TEnv = unknown> {
|
|
|
109
110
|
* Return false to skip cache for this request (always fetch fresh).
|
|
110
111
|
*
|
|
111
112
|
* Has access to full RequestContext including env, request, params, cookies, etc.
|
|
112
|
-
*
|
|
113
|
+
* Runs after global and route middleware on RSC routes; on response routes,
|
|
114
|
+
* before route middleware (see CacheContext).
|
|
113
115
|
*
|
|
114
116
|
* @example
|
|
115
117
|
* ```typescript
|
|
@@ -131,7 +133,8 @@ export interface CacheOptions<TEnv = unknown> {
|
|
|
131
133
|
* Bypasses default key generation AND store's keyGenerator.
|
|
132
134
|
*
|
|
133
135
|
* Has access to full RequestContext including env, request, params, cookies, etc.
|
|
134
|
-
*
|
|
136
|
+
* Runs after global and route middleware on RSC routes; on response routes,
|
|
137
|
+
* before route middleware (see CacheContext).
|
|
135
138
|
*
|
|
136
139
|
* @example
|
|
137
140
|
* ```typescript
|
|
@@ -153,7 +156,8 @@ export interface CacheOptions<TEnv = unknown> {
|
|
|
153
156
|
* Tags for cache invalidation.
|
|
154
157
|
* Can be a static array or a function that returns tags.
|
|
155
158
|
*
|
|
156
|
-
* The built-in `MemorySegmentCacheStore
|
|
159
|
+
* The built-in `MemorySegmentCacheStore`, `CFCacheStore`, and
|
|
160
|
+
* `VercelCacheStore` index by tag.
|
|
157
161
|
* Invalidate on demand with `updateTag(...tags)` (awaitable, read-your-own-writes;
|
|
158
162
|
* for server actions) or `revalidateTag(...tags)` (background hard-purge, not
|
|
159
163
|
* awaited; for route handlers / webhooks). For `CFCacheStore`, distributed
|
|
@@ -342,6 +342,12 @@ export type HandlerContext<
|
|
|
342
342
|
* Current theme (from cookie or default).
|
|
343
343
|
* Only available when theme is enabled in router config.
|
|
344
344
|
*
|
|
345
|
+
* The visitor's cookie, so it is guarded like `cookies()`: reading it on a
|
|
346
|
+
* `ppr` route refuses the shell capture, and inside a `cache()` boundary or
|
|
347
|
+
* a `"use cache"` function it throws (#971). Read it with `useTheme()` in a
|
|
348
|
+
* client component, or in a live loader, on those routes. A read-only,
|
|
349
|
+
* non-enumerable getter: `{ ...ctx }` does not carry it.
|
|
350
|
+
*
|
|
345
351
|
* @example
|
|
346
352
|
* ```typescript
|
|
347
353
|
* route("settings", (ctx) => {
|
|
@@ -350,7 +356,7 @@ export type HandlerContext<
|
|
|
350
356
|
* });
|
|
351
357
|
* ```
|
|
352
358
|
*/
|
|
353
|
-
theme?: Theme;
|
|
359
|
+
readonly theme?: Theme;
|
|
354
360
|
/**
|
|
355
361
|
* Set the theme (only available when theme is enabled in router config).
|
|
356
362
|
* Sets a cookie with the new theme value.
|
|
@@ -455,6 +461,27 @@ export type InternalHandlerContext<
|
|
|
455
461
|
* table (so a loader cannot await its own in-flight memoized promise).
|
|
456
462
|
*/
|
|
457
463
|
_loaderCacheOriginalUse?: (item: any) => any;
|
|
464
|
+
/**
|
|
465
|
+
* @internal A loader-cache HIT asks before replaying a loader's recorded
|
|
466
|
+
* pushes: true when that loader has not run in this request and no other
|
|
467
|
+
* replay delivered it; its later run then replaces the replayed values
|
|
468
|
+
* (HandleStore.pushReplayed). One copy per loader per request. See
|
|
469
|
+
* setupLoaderAccess.
|
|
470
|
+
*/
|
|
471
|
+
_claimLoaderPushes?: (loaderId: string) => boolean;
|
|
472
|
+
/**
|
|
473
|
+
* @internal Run a loader on a fresh executor (own memo map): a loader-cache
|
|
474
|
+
* stale refresh, whose diverted pushes must not take a dependency's run
|
|
475
|
+
* from the page. See setupLoaderAccess.
|
|
476
|
+
*/
|
|
477
|
+
_runLoaderIsolated?: (loader: any) => Promise<any>;
|
|
478
|
+
/**
|
|
479
|
+
* @internal A loader's cache() binding started with these cache() tags: an
|
|
480
|
+
* execution of that loader outside the binding (a reader started it first,
|
|
481
|
+
* or a stale refresh runs it) answers for them too (#964). See
|
|
482
|
+
* setupLoaderAccess.
|
|
483
|
+
*/
|
|
484
|
+
_bindLoaderCacheTags?: (loaderId: string, tags: Set<string>) => void;
|
|
458
485
|
};
|
|
459
486
|
|
|
460
487
|
/**
|
|
@@ -28,9 +28,10 @@ import type { RequestScope } from "./request-scope.js";
|
|
|
28
28
|
* return await db.cart.get(user.id);
|
|
29
29
|
* });
|
|
30
30
|
*
|
|
31
|
-
* //
|
|
32
|
-
*
|
|
33
|
-
*
|
|
31
|
+
* // createLoader's one type parameter is the data type; params are
|
|
32
|
+
* // Record<string, string | undefined>:
|
|
33
|
+
* const ProductLoader = createLoader<Product>(async (ctx) => {
|
|
34
|
+
* const { slug } = ctx.params; // string | undefined
|
|
34
35
|
* return await db.products.findBySlug(slug);
|
|
35
36
|
* });
|
|
36
37
|
* ```
|
|
@@ -243,9 +244,10 @@ export type LoadOptions =
|
|
|
243
244
|
* return await db.cart.get(ctx.get("user").id);
|
|
244
245
|
* });
|
|
245
246
|
*
|
|
246
|
-
* //
|
|
247
|
-
*
|
|
248
|
-
*
|
|
247
|
+
* // createLoader's one type parameter is the data type; params are
|
|
248
|
+
* // Record<string, string | undefined>:
|
|
249
|
+
* export const ProductLoader = createLoader<Product>(async (ctx) => {
|
|
250
|
+
* const { slug } = ctx.params; // string | undefined
|
|
249
251
|
* return await db.products.findBySlug(slug);
|
|
250
252
|
* });
|
|
251
253
|
*
|
|
@@ -59,30 +59,34 @@ export interface PartialPrerenderProps {
|
|
|
59
59
|
/**
|
|
60
60
|
* Operational tags attached to the captured shell entry for
|
|
61
61
|
* `updateTag()`/`revalidateTag()`-driven eviction. UNIONED with the tags the
|
|
62
|
-
* capture
|
|
62
|
+
* capture collects: its doc record's tags (what the handler layer and the
|
|
63
|
+
* server components it rendered recorded) and its bake-lane loaders'.
|
|
63
64
|
*/
|
|
64
65
|
tags?: string[];
|
|
65
66
|
/**
|
|
66
|
-
* Upper bound (serialized UTF-8 bytes) on the
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
67
|
+
* Upper bound (serialized UTF-8 bytes) on the loader pins in the capture
|
|
68
|
+
* data snapshot: the loader records and the cache values loaders read,
|
|
69
|
+
* duplicated into the shell entry. The doc record (the handler layer every
|
|
70
|
+
* HIT replays) is exempt. Over the cap the pins are dropped: the shell is
|
|
71
|
+
* still stored and every HIT still replays the handler layer, but the
|
|
72
|
+
* pinned loaders read the live store, so drifted cached content can
|
|
73
|
+
* hydration-mismatch and be repaired client-side. Reported once per key.
|
|
74
|
+
* Defaults to 8 MiB. The whole entry is bounded separately by the store's
|
|
75
|
+
* value limit (Cloudflare KV: 25 MiB); an entry over it is refused.
|
|
74
76
|
*/
|
|
75
77
|
maxSnapshotBytes?: number;
|
|
76
78
|
/**
|
|
77
|
-
* Capture settle budget in MILLISECONDS (default 15000).
|
|
78
|
-
* background capture: the
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
79
|
+
* Capture settle budget in MILLISECONDS (default 15000). One deadline for
|
|
80
|
+
* the whole background capture: the match (the handlers, and the loaders
|
|
81
|
+
* they await), the wait for handler output (handle pushes and the promises
|
|
82
|
+
* nested in them, bake-lane loaders, and the doc record's encode, which
|
|
83
|
+
* awaits handler promises and async server components), AND the fizz
|
|
84
|
+
* prerender. Everything a handler produces is
|
|
85
|
+
* awaited and baked into the stored shell. Declare it to tighten the
|
|
86
|
+
* budget below the default or when a route's shell material takes longer
|
|
87
|
+
* than 15s to settle. A budget that expires before the doc record is
|
|
88
|
+
* written REFUSES the capture (the route stays MISS with the once-per-key
|
|
89
|
+
* warning): a shell with missing handler output is never stored. Capture is background work
|
|
86
90
|
* (waitUntil), so a longer budget costs latency-to-HIT only, never a served
|
|
87
91
|
* response; the platform waitUntil lifetime (workerd: ~30s past response
|
|
88
92
|
* completion) is the physical ceiling — the default's derivation lives in
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ContextVar } from "../context-var.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { GlobalReverseFunction } from "../reverse.js";
|
|
3
3
|
import type {
|
|
4
4
|
DefaultReverseRouteMap,
|
|
5
5
|
DefaultVars,
|
|
@@ -7,27 +7,6 @@ import type {
|
|
|
7
7
|
import type { UseItems, ResponseRouteUseItem } from "../route-types.js";
|
|
8
8
|
import type { RequestScope } from "../types/request-scope.js";
|
|
9
9
|
|
|
10
|
-
/**
|
|
11
|
-
* Reverse function for response handler contexts.
|
|
12
|
-
* Global names get autocomplete and param validation from the generated route map.
|
|
13
|
-
* Local `.name` calls are accepted but not validated (scope unknown at type level).
|
|
14
|
-
*/
|
|
15
|
-
type ResponseReverseFunction = [DefaultReverseRouteMap] extends [
|
|
16
|
-
Record<string, string>,
|
|
17
|
-
]
|
|
18
|
-
? (
|
|
19
|
-
name: string,
|
|
20
|
-
params?: Record<string, string>,
|
|
21
|
-
search?: Record<string, unknown>,
|
|
22
|
-
) => string
|
|
23
|
-
: ReverseFunction<DefaultReverseRouteMap> & {
|
|
24
|
-
(
|
|
25
|
-
name: `.${string}`,
|
|
26
|
-
params?: Record<string, string>,
|
|
27
|
-
search?: Record<string, unknown>,
|
|
28
|
-
): string;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
10
|
/**
|
|
32
11
|
* Symbol marking a route as a response route (non-RSC).
|
|
33
12
|
* Stored on PathOptions and UrlPatterns to signal the trie to short-circuit.
|
|
@@ -99,7 +78,8 @@ export interface ResponseHandlerContext<
|
|
|
99
78
|
params: TParams;
|
|
100
79
|
/** @internal Phantom property for params type invariance. Prevents mounting handlers on wrong routes. */
|
|
101
80
|
readonly _paramCheck?: (params: TParams) => TParams;
|
|
102
|
-
|
|
81
|
+
/** Global route names only; see {@link GlobalReverseFunction}. */
|
|
82
|
+
reverse: GlobalReverseFunction<DefaultReverseRouteMap>;
|
|
103
83
|
/** Read a variable set by middleware via ctx.set(key, value) or ctx.set(ContextVar, value). */
|
|
104
84
|
get: {
|
|
105
85
|
<T>(contextVar: ContextVar<T>): T | undefined;
|
package/src/use-loader.tsx
CHANGED
|
@@ -117,6 +117,14 @@ export type LoadFunction<T> = (options?: LoadOptions) => Promise<T>;
|
|
|
117
117
|
|
|
118
118
|
export interface UseLoaderResult<T> {
|
|
119
119
|
data: T;
|
|
120
|
+
/**
|
|
121
|
+
* True while this loader family (`loader.$$id`) is in flight: a `load()` /
|
|
122
|
+
* group refresh, or a held navigation still streaming a re-run of this
|
|
123
|
+
* loader. Family-keyed, not segment-keyed: a layout `useLoader` of the same
|
|
124
|
+
* `createLoader` the child route is re-running also reports true, even if
|
|
125
|
+
* the layout copy is not replaced. Not used for the initial streamed read
|
|
126
|
+
* (that suspends).
|
|
127
|
+
*/
|
|
120
128
|
isLoading: boolean;
|
|
121
129
|
error: Error | null;
|
|
122
130
|
load: LoadFunction<T>;
|
|
@@ -125,6 +133,7 @@ export interface UseLoaderResult<T> {
|
|
|
125
133
|
|
|
126
134
|
export interface UseFetchLoaderResult<T> {
|
|
127
135
|
data: T | undefined;
|
|
136
|
+
/** Same family-keyed contract as {@link UseLoaderResult.isLoading}. */
|
|
128
137
|
isLoading: boolean;
|
|
129
138
|
error: Error | null;
|
|
130
139
|
load: LoadFunction<T>;
|
|
@@ -560,7 +569,7 @@ function useLoaderInternal<T>(
|
|
|
560
569
|
* @example Basic usage - accessing route loader data
|
|
561
570
|
* ```tsx
|
|
562
571
|
* "use client";
|
|
563
|
-
* import { useLoader } from "
|
|
572
|
+
* import { useLoader } from "@rangojs/router/client";
|
|
564
573
|
* import { CartLoader } from "../loaders/cart";
|
|
565
574
|
*
|
|
566
575
|
* // In route definition: loader(CartLoader)
|
|
@@ -608,7 +617,7 @@ export function useLoader<T>(
|
|
|
608
617
|
* @example On-demand fetching
|
|
609
618
|
* ```tsx
|
|
610
619
|
* "use client";
|
|
611
|
-
* import { useFetchLoader } from "
|
|
620
|
+
* import { useFetchLoader } from "@rangojs/router/client";
|
|
612
621
|
* import { SearchLoader } from "../loaders/search";
|
|
613
622
|
*
|
|
614
623
|
* export function SearchResults() {
|
|
@@ -670,7 +679,7 @@ export function useFetchLoader<T>(
|
|
|
670
679
|
* @example
|
|
671
680
|
* ```tsx
|
|
672
681
|
* "use client";
|
|
673
|
-
* import { useLoader, useRefreshLoaders } from "
|
|
682
|
+
* import { useLoader, useRefreshLoaders } from "@rangojs/router/client";
|
|
674
683
|
*
|
|
675
684
|
* function Profile() {
|
|
676
685
|
* const { data } = useLoader(ProfileLoader, { key: userId, refreshGroup: "account" });
|
|
@@ -64,6 +64,14 @@ export async function runShellPrerenderPhase(
|
|
|
64
64
|
const startTotal = performance.now();
|
|
65
65
|
console.log(`[rango] Shell-prerendering ${candidates.length} URL(s)...`);
|
|
66
66
|
|
|
67
|
+
// Hold the process open for the phase. The capture's waits are unref'd
|
|
68
|
+
// timers (retry delay, Flight quiesce hops) so a runtime capture never keeps
|
|
69
|
+
// Node alive; every bundle is already written and the build temp server has
|
|
70
|
+
// no file watcher (#947). Its only remaining handle is the HMR WebSocket on
|
|
71
|
+
// 24678, which fails to bind silently when another Vite server holds the
|
|
72
|
+
// port; `vite build` then exited 0 mid-phase without writing
|
|
73
|
+
// __shell-manifest.js.
|
|
74
|
+
const keepAlive = setInterval(() => {}, 60_000);
|
|
67
75
|
let restoreClientRequire: (() => void) | undefined;
|
|
68
76
|
try {
|
|
69
77
|
// Runner access needs the RunnableDevEnvironment surface; the environments
|
|
@@ -343,6 +351,7 @@ export async function runShellPrerenderPhase(
|
|
|
343
351
|
// buildApp post hook's finally on success, buildEnd on an aborted build.
|
|
344
352
|
delete (globalThis as any).__loadPrerenderManifestModule;
|
|
345
353
|
restoreClientRequire?.();
|
|
354
|
+
clearInterval(keepAlive);
|
|
346
355
|
}
|
|
347
356
|
}
|
|
348
357
|
|