@rangojs/router 0.27.0 → 0.28.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/dist/bin/rango.js +1 -1
- package/dist/types/__internal.d.ts +7 -1
- package/dist/types/browser/event-controller.d.ts +2 -1
- package/dist/types/browser/history-state.d.ts +3 -9
- package/dist/types/browser/navigation-store.d.ts +8 -6
- package/dist/types/browser/react/filter-segment-order.d.ts +2 -2
- package/dist/types/browser/segment-reconciler.d.ts +6 -4
- package/dist/types/browser/types.d.ts +2 -1
- package/dist/types/browser/wire-protocol.d.ts +25 -0
- package/dist/types/cache/cache-key-utils.d.ts +11 -5
- package/dist/types/cache/cache-scope.d.ts +34 -22
- package/dist/types/cache/cf/cf-cache-constants.d.ts +2 -2
- package/dist/types/cache/cf/cf-cache-store.d.ts +47 -65
- package/dist/types/cache/cf/cf-kv-utils.d.ts +1 -1
- package/dist/types/cache/handle-snapshot.d.ts +9 -4
- package/dist/types/cache/segment-codec.d.ts +14 -0
- package/dist/types/cache/shell-snapshot.d.ts +1 -1
- package/dist/types/cache/tag-invalidation.d.ts +10 -0
- package/dist/types/cache/taint.d.ts +5 -3
- package/dist/types/cache/types.d.ts +7 -3
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +8 -6
- package/dist/types/prefetch-markers.d.ts +5 -14
- package/dist/types/prerender/store.d.ts +31 -0
- package/dist/types/prerender/warm-request.d.ts +3 -3
- package/dist/types/prerender.d.ts +2 -2
- package/dist/types/route-name.d.ts +5 -0
- package/dist/types/router/error-handling.d.ts +4 -4
- package/dist/types/router/instrument.d.ts +4 -3
- package/dist/types/router/intercept-resolution.d.ts +25 -9
- package/dist/types/router/match-context.d.ts +4 -11
- package/dist/types/router/match-handlers.d.ts +2 -6
- package/dist/types/router/match-middleware/background-revalidation.d.ts +10 -20
- package/dist/types/router/match-middleware/cache-lookup.d.ts +34 -86
- package/dist/types/router/match-middleware/segment-resolution.d.ts +8 -6
- package/dist/types/router/prerender-match.d.ts +21 -6
- package/dist/types/router/preview-match.d.ts +2 -7
- package/dist/types/router/request-classification.d.ts +5 -0
- package/dist/types/router/router-context.d.ts +7 -46
- package/dist/types/router/router-interfaces.d.ts +8 -14
- package/dist/types/router/segment-resolution/loader-cache.d.ts +3 -3
- package/dist/types/router/segment-resolution/loader-mask.d.ts +4 -4
- package/dist/types/router/segment-resolution/prefetch-deferral.d.ts +20 -18
- package/dist/types/router/segment-resolution/resolution-pass.d.ts +93 -0
- package/dist/types/router/segment-resolution/revalidation.d.ts +82 -31
- package/dist/types/router/segment-resolution.d.ts +1 -2
- package/dist/types/router/segment-wrappers.d.ts +11 -48
- package/dist/types/router/telemetry.d.ts +2 -0
- package/dist/types/router/types.d.ts +10 -0
- package/dist/types/rsc/full-payload.d.ts +2 -2
- package/dist/types/rsc/handler-context.d.ts +6 -6
- package/dist/types/rsc/json-route-result.d.ts +5 -9
- package/dist/types/rsc/request-stages.d.ts +203 -0
- package/dist/types/rsc/response-cache-serve.d.ts +7 -12
- package/dist/types/rsc/response-route-handler.d.ts +2 -2
- package/dist/types/rsc/routine-plan.d.ts +1 -1
- package/dist/types/rsc/server-action.d.ts +2 -2
- package/dist/types/rsc/shell-capture-constants.d.ts +1 -1
- package/dist/types/rsc/shell-capture.d.ts +132 -15
- package/dist/types/rsc/shell-serve.d.ts +37 -12
- package/dist/types/server/context.d.ts +9 -8
- package/dist/types/server/handle-store.d.ts +16 -0
- package/dist/types/server/render-pass.d.ts +72 -0
- package/dist/types/server/request-context.d.ts +24 -104
- package/dist/types/server/rewrite-trail.d.ts +2 -2
- package/dist/types/testing/dispatch.d.ts +35 -18
- package/dist/types/types/cache-types.d.ts +6 -3
- package/dist/types/types/error-types.d.ts +9 -1
- package/dist/types/types/handler-context.d.ts +9 -1
- package/dist/types/types/segments.d.ts +1 -1
- package/dist/types/vite/discovery/build-discovery-phase.d.ts +40 -0
- package/dist/types/vite/discovery/build-env.d.ts +22 -0
- package/dist/types/vite/discovery/bundle-scan-phase.d.ts +12 -0
- package/dist/types/vite/discovery/dev-prerender-cache.d.ts +3 -2
- package/dist/types/vite/discovery/dev-server-phase.d.ts +26 -0
- package/dist/types/vite/discovery/discovery-errors.d.ts +1 -1
- package/dist/types/vite/discovery/state.d.ts +12 -0
- package/dist/types/vite/plugins/version-plugin.d.ts +1 -1
- package/dist/types/vite/plugins/virtual-entries.d.ts +1 -1
- package/dist/types/vite/router-discovery.d.ts +8 -47
- package/dist/types/vite/temp-rsc-server.d.ts +39 -0
- package/dist/types/vite/utils/prerender-utils.d.ts +9 -0
- package/dist/types/wire-params.d.ts +34 -0
- package/dist/vite/index.js +3809 -3710
- package/package.json +1 -1
- package/skills/cache-guide/SKILL.md +8 -5
- package/skills/caching/SKILL.md +37 -18
- package/skills/document-cache/SKILL.md +13 -1
- package/skills/handler-use/SKILL.md +1 -1
- package/skills/intercept/SKILL.md +17 -7
- package/skills/middleware/SKILL.md +18 -0
- package/skills/ppr/SKILL.md +18 -3
- package/skills/prerender/SKILL.md +39 -15
- package/skills/rango/SKILL.md +5 -1
- package/skills/server-actions/SKILL.md +8 -1
- package/skills/testing/response-routes.md +6 -4
- package/skills/use-cache/SKILL.md +46 -8
- package/src/__internal.ts +7 -1
- package/src/browser/connection-warmup.ts +3 -1
- package/src/browser/event-controller.ts +5 -3
- package/src/browser/history-state.ts +6 -12
- package/src/browser/navigation-bridge.ts +14 -13
- package/src/browser/navigation-client.ts +18 -25
- package/src/browser/navigation-store.ts +25 -27
- package/src/browser/navigation-transaction.ts +4 -1
- package/src/browser/prefetch/cache.ts +2 -1
- package/src/browser/prefetch/fetch.ts +8 -16
- package/src/browser/prefetch/queue.ts +4 -4
- package/src/browser/react/NavigationProvider.tsx +2 -1
- package/src/browser/react/filter-segment-order.ts +2 -2
- package/src/browser/rsc-router.tsx +1 -0
- package/src/browser/segment-reconciler.ts +66 -53
- package/src/browser/server-action-bridge.ts +50 -57
- package/src/browser/types.ts +2 -1
- package/src/browser/wire-protocol.ts +41 -0
- package/src/cache/cache-key-utils.ts +11 -5
- package/src/cache/cache-runtime.ts +110 -50
- package/src/cache/cache-scope.ts +110 -64
- package/src/cache/cf/cf-cache-constants.ts +2 -2
- package/src/cache/cf/cf-cache-store.ts +486 -874
- package/src/cache/cf/cf-kv-utils.ts +1 -1
- package/src/cache/document-cache.ts +34 -13
- package/src/cache/handle-snapshot.ts +19 -7
- package/src/cache/segment-codec.ts +55 -0
- package/src/cache/shell-snapshot.ts +2 -2
- package/src/cache/tag-invalidation.ts +21 -2
- package/src/cache/taint.ts +5 -3
- package/src/cache/types.ts +7 -3
- package/src/cache/vercel/vercel-cache-store.ts +243 -310
- package/src/handles/pushed-by.ts +1 -1
- package/src/prefetch-markers.ts +5 -16
- package/src/prerender/store.ts +76 -0
- package/src/prerender/warm-request.ts +8 -4
- package/src/prerender.ts +2 -2
- package/src/route-name.ts +8 -0
- package/src/router/error-handling.ts +4 -4
- package/src/router/instrument.ts +4 -3
- package/src/router/intercept-resolution.ts +77 -75
- package/src/router/loader-resolution.ts +5 -4
- package/src/router/match-api.ts +4 -5
- package/src/router/match-context.ts +20 -12
- package/src/router/match-handlers.ts +8 -20
- package/src/router/match-middleware/background-revalidation.ts +41 -53
- package/src/router/match-middleware/cache-lookup.ts +675 -726
- package/src/router/match-middleware/cache-store.ts +4 -8
- package/src/router/match-middleware/intercept-resolution.ts +3 -23
- package/src/router/match-middleware/segment-resolution.ts +34 -61
- package/src/router/middleware.ts +69 -11
- package/src/router/navigation-snapshot.ts +4 -4
- package/src/router/prerender-match.ts +100 -44
- package/src/router/preview-match.ts +6 -41
- package/src/router/request-classification.ts +13 -7
- package/src/router/route-snapshot.ts +2 -5
- package/src/router/router-context.ts +10 -95
- package/src/router/router-interfaces.ts +8 -14
- package/src/router/segment-resolution/loader-cache.ts +14 -9
- package/src/router/segment-resolution/loader-mask.ts +5 -5
- package/src/router/segment-resolution/prefetch-deferral.ts +30 -27
- package/src/router/segment-resolution/resolution-pass.ts +137 -0
- package/src/router/segment-resolution/revalidation.ts +897 -776
- package/src/router/segment-resolution.ts +4 -13
- package/src/router/segment-wrappers.ts +51 -269
- package/src/router/telemetry.ts +5 -0
- package/src/router/types.ts +10 -0
- package/src/router.ts +12 -13
- package/src/rsc/full-payload.ts +6 -5
- package/src/rsc/handler-context.ts +8 -14
- package/src/rsc/handler.ts +126 -507
- package/src/rsc/json-route-result.ts +5 -9
- package/src/rsc/loader-fetch.ts +6 -5
- package/src/rsc/progressive-enhancement.ts +5 -0
- package/src/rsc/request-stages.ts +757 -0
- package/src/rsc/response-cache-serve.ts +10 -14
- package/src/rsc/response-route-handler.ts +13 -5
- package/src/rsc/rewrite-passes.ts +2 -1
- package/src/rsc/routine-plan.ts +1 -1
- package/src/rsc/rsc-rendering.ts +164 -349
- package/src/rsc/server-action.ts +87 -113
- package/src/rsc/shell-capture-constants.ts +1 -1
- package/src/rsc/shell-capture.ts +212 -169
- package/src/rsc/shell-serve.ts +121 -18
- package/src/rsc/ssr-setup.ts +5 -4
- package/src/segment-system.tsx +3 -3
- package/src/server/context.ts +22 -25
- package/src/server/handle-store.ts +55 -0
- package/src/server/render-pass.ts +291 -0
- package/src/server/request-context.ts +26 -115
- package/src/server/rewrite-trail.ts +6 -4
- package/src/ssr/index.tsx +1 -1
- package/src/testing/dispatch.ts +223 -710
- package/src/testing/e2e/page-helpers.ts +2 -2
- package/src/testing/serve-shell-request.ts +23 -36
- package/src/types/cache-types.ts +6 -3
- package/src/types/error-types.ts +9 -1
- package/src/types/handler-context.ts +12 -1
- package/src/types/segments.ts +1 -1
- package/src/vite/discovery/build-discovery-phase.ts +204 -0
- package/src/vite/discovery/build-env.ts +148 -0
- package/src/vite/discovery/bundle-scan-phase.ts +128 -0
- package/src/vite/discovery/dev-prerender-cache.ts +8 -3
- package/src/vite/discovery/dev-server-phase.ts +1776 -0
- package/src/vite/discovery/discover-routers.ts +1 -1
- package/src/vite/discovery/discovery-errors.ts +1 -1
- package/src/vite/discovery/prerender-collection.ts +24 -39
- package/src/vite/discovery/state.ts +15 -0
- package/src/vite/plugins/version-plugin.ts +1 -1
- package/src/vite/plugins/virtual-entries.ts +1 -1
- package/src/vite/router-discovery.ts +29 -2428
- package/src/vite/temp-rsc-server.ts +223 -0
- package/src/vite/utils/prerender-utils.ts +47 -0
- package/src/wire-params.ts +35 -0
- package/dist/types/router/segment-resolution/fresh.d.ts +0 -72
- package/src/router/segment-resolution/fresh.ts +0 -945
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The discovery temp RSC server: a minimal Vite server whose module runner
|
|
3
|
+
* imports the user's router files. Shared by dev discovery
|
|
4
|
+
* (discovery/dev-server-phase.ts) and build discovery
|
|
5
|
+
* (discovery/build-discovery-phase.ts).
|
|
6
|
+
*
|
|
7
|
+
* Sits in src/vite/, not src/vite/discovery/: the loader hook URL below
|
|
8
|
+
* resolves against this module's import.meta.url, and the published bundle
|
|
9
|
+
* (dist/vite/index.js) ships the hook at the same relative path.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { ViteDevServer } from "vite";
|
|
13
|
+
import { createServer as createViteServer } from "vite";
|
|
14
|
+
import { register } from "node:module";
|
|
15
|
+
import { createVersionPlugin } from "./plugins/version-plugin.js";
|
|
16
|
+
import { getVirtualEntrySSR } from "./plugins/virtual-entries.js";
|
|
17
|
+
import { createVirtualStubPlugin } from "./plugins/virtual-stub-plugin.js";
|
|
18
|
+
import { createCloudflareProtocolStubPlugin } from "./plugins/cloudflare-protocol-stub.js";
|
|
19
|
+
import {
|
|
20
|
+
exposeInternalIds,
|
|
21
|
+
exposeRouterId,
|
|
22
|
+
} from "./plugins/expose-internal-ids.js";
|
|
23
|
+
import { hashClientRefs } from "./plugins/client-ref-hashing.js";
|
|
24
|
+
import { hashServerRefs } from "./plugins/server-ref-hashing.js";
|
|
25
|
+
import { defineEncryptionKeyExpr } from "./encryption-key.js";
|
|
26
|
+
import type { DiscoveryState } from "./discovery/state.js";
|
|
27
|
+
import { recordClientUrlsModule } from "./discovery/client-urls-projection.js";
|
|
28
|
+
import { transitionWhenHoistPlugin } from "./plugins/transition-when-hoist.js";
|
|
29
|
+
import { clientUrlsRevalidateHoistPlugin } from "./plugins/client-urls-revalidate-hoist.js";
|
|
30
|
+
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// Node ESM Loader Hook Registration
|
|
33
|
+
// ============================================================================
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Registers a Node ESM loader hook that resolves `cloudflare:*` specifiers
|
|
37
|
+
* to a data: URL stub. Defense-in-depth alongside the Vite transform in
|
|
38
|
+
* `cloudflare-protocol-stub.ts`:
|
|
39
|
+
*
|
|
40
|
+
* - The Vite transform catches `cloudflare:*` imports in modules that flow
|
|
41
|
+
* through Vite's plugin pipeline. That's the vast majority of cases.
|
|
42
|
+
* - The Node loader catches imports in modules that Vite/Rollup externalize
|
|
43
|
+
* (e.g. the `partyserver` package, which has a top-level
|
|
44
|
+
* `import { DurableObject, env } from "cloudflare:workers"` and ships
|
|
45
|
+
* shapes plugin-rsc marks as external). Externalized modules are loaded
|
|
46
|
+
* via Node's native ESM loader, which rejects URL schemes.
|
|
47
|
+
*
|
|
48
|
+
* Registration is process-global and one-shot. The hook only intercepts
|
|
49
|
+
* `cloudflare:*` specifiers; everything else passes through via
|
|
50
|
+
* `nextResolve()`. It runs in a separate worker thread (Node ESM loader
|
|
51
|
+
* architecture), so it can't read the `globalThis[BUILD_ENV_GLOBAL_KEY]`
|
|
52
|
+
* bridge that the Vite transform uses — the stubs served here always
|
|
53
|
+
* return `env = {}`. That's fine because externalized libraries don't
|
|
54
|
+
* typically access `env` at module top level; user source (where real
|
|
55
|
+
* `env` matters at build time) flows through the Vite transform.
|
|
56
|
+
*/
|
|
57
|
+
let loaderHookRegistered = false;
|
|
58
|
+
function ensureCloudflareProtocolLoaderRegistered(): void {
|
|
59
|
+
if (loaderHookRegistered) return;
|
|
60
|
+
loaderHookRegistered = true;
|
|
61
|
+
try {
|
|
62
|
+
register(
|
|
63
|
+
new URL("./plugins/cloudflare-protocol-loader-hook.mjs", import.meta.url),
|
|
64
|
+
);
|
|
65
|
+
} catch (err: any) {
|
|
66
|
+
// register() requires Node 18.19+ / 20.6+. Older Node still has the
|
|
67
|
+
// Vite transform as primary defense.
|
|
68
|
+
console.warn(
|
|
69
|
+
`[rango] Could not register Node ESM loader hook for cloudflare:* imports (${err?.message ?? err}). Falling back to Vite transform only.`,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ============================================================================
|
|
75
|
+
// Temp Server Factory
|
|
76
|
+
// ============================================================================
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Create a minimal Vite server for router discovery.
|
|
80
|
+
*
|
|
81
|
+
* Both dev-mode prerender and build-mode discovery need a temp RSC server
|
|
82
|
+
* to import user router files via module runner. This factory centralizes
|
|
83
|
+
* the shared config and the mode-specific differences:
|
|
84
|
+
* - Dev: path-based IDs (no forceBuild), separate cacheDir
|
|
85
|
+
* - Build: hashed IDs (forceBuild), hashClientRefs for production bundles
|
|
86
|
+
*
|
|
87
|
+
* Returns the ViteDevServer instance. Callers access .environments.rsc as needed.
|
|
88
|
+
* @internal Exported for tests.
|
|
89
|
+
*/
|
|
90
|
+
export async function createTempRscServer(
|
|
91
|
+
state: DiscoveryState,
|
|
92
|
+
options: {
|
|
93
|
+
forceBuild?: boolean;
|
|
94
|
+
cacheDir?: string;
|
|
95
|
+
/**
|
|
96
|
+
* Serve the REAL rango SSR entry (getVirtualEntrySSR) for
|
|
97
|
+
* "virtual:entry-ssr" instead of the discovery stub, so the dev
|
|
98
|
+
* /__rsc_shell endpoint can drive captureShellHTML in this server's SSR
|
|
99
|
+
* realm. Dev-correct by construction: the entry's bootstrap resolves to
|
|
100
|
+
* plugin-rsc's stable virtual browser-entry URL, which the MAIN dev
|
|
101
|
+
* server serves to the browser. Loaded lazily — discovery never imports
|
|
102
|
+
* the SSR entry, so the temp server stays as light as before until a
|
|
103
|
+
* shell capture actually runs.
|
|
104
|
+
*/
|
|
105
|
+
realSsrEntry?: boolean;
|
|
106
|
+
} = {},
|
|
107
|
+
): Promise<ViteDevServer> {
|
|
108
|
+
// Install the Node ESM loader hook before any module evaluation so
|
|
109
|
+
// `cloudflare:*` specifiers in externalized/loader-delegated modules
|
|
110
|
+
// (e.g. packages plugin-rsc marks as external) resolve to stubs
|
|
111
|
+
// instead of crashing Node's native loader.
|
|
112
|
+
ensureCloudflareProtocolLoaderRegistered();
|
|
113
|
+
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
114
|
+
// Mirror the user's resolution config + plugins so discovery (and the
|
|
115
|
+
// prerender/static rendering that shares this runner) resolves modules the
|
|
116
|
+
// same way the real environment does. Falls back to the legacy alias-only
|
|
117
|
+
// behavior if configResolved hasn't populated the parity slice yet.
|
|
118
|
+
const runnerConfig = state.userRunnerConfig;
|
|
119
|
+
const resolveConfig = runnerConfig?.resolve ?? {
|
|
120
|
+
alias: state.userResolveAlias,
|
|
121
|
+
};
|
|
122
|
+
const oxcConfig = runnerConfig?.oxc ?? {
|
|
123
|
+
jsx: { runtime: "automatic", importSource: "react" },
|
|
124
|
+
};
|
|
125
|
+
return createViteServer({
|
|
126
|
+
root: state.projectRoot,
|
|
127
|
+
configFile: false,
|
|
128
|
+
server: {
|
|
129
|
+
middlewareMode: true,
|
|
130
|
+
// Build mode: no file watching. buildStart installs the per-router tries
|
|
131
|
+
// into this realm and runShellPrerenderPhase reuses it after the bundles
|
|
132
|
+
// are written. A watched write in between (writeRouteTypesFiles' own
|
|
133
|
+
// <router>.named-routes.gen.ts, which every router file imports) can
|
|
134
|
+
// make Vite full-reload the RSC runner; the shell phase then matches in
|
|
135
|
+
// a fresh realm with no tries and a root path("/*") wins (#947).
|
|
136
|
+
...(options.forceBuild ? { watch: null } : {}),
|
|
137
|
+
},
|
|
138
|
+
appType: "custom",
|
|
139
|
+
logLevel: "silent",
|
|
140
|
+
resolve: resolveConfig,
|
|
141
|
+
...(runnerConfig?.define ? { define: runnerConfig.define } : {}),
|
|
142
|
+
oxc: oxcConfig as any,
|
|
143
|
+
...(options.cacheDir && { cacheDir: options.cacheDir }),
|
|
144
|
+
plugins: [
|
|
145
|
+
rsc({
|
|
146
|
+
entries: {
|
|
147
|
+
client: "virtual:entry-client",
|
|
148
|
+
ssr: "virtual:entry-ssr",
|
|
149
|
+
rsc: state.resolvedEntryPath!,
|
|
150
|
+
},
|
|
151
|
+
// The temp server renders Static/Prerender output and encrypts inline-
|
|
152
|
+
// action bound args. Give it the SAME key as the main build/dev runtime
|
|
153
|
+
// (defineEncryptionKeyExpr is process-cached) so those args decrypt at
|
|
154
|
+
// invocation. Unconditional, NOT build-only: under Cloudflare/workerd dev
|
|
155
|
+
// the RSC env has no module runner, so prerender is rendered by THIS temp
|
|
156
|
+
// server (via /__rsc_prerender), and the action decrypts in the main
|
|
157
|
+
// runtime with the rango.ts key -- gating on forceBuild left dev encrypting
|
|
158
|
+
// with the temp server's own random key, failing decryptActionBoundArgs.
|
|
159
|
+
// (hashServerRefs stays build-only: dev keeps dev-style ids the dev runtime
|
|
160
|
+
// resolves directly.)
|
|
161
|
+
defineEncryptionKey: defineEncryptionKeyExpr(),
|
|
162
|
+
}),
|
|
163
|
+
// hashClientRefs/hashServerRefs only in build mode — production bundles
|
|
164
|
+
// need hashed refs. hashServerRefs is the server-side analog: it rewrites
|
|
165
|
+
// registerServerReference dev-style ids to production hashes so a
|
|
166
|
+
// server-created action embedded in prerendered/static Flight resolves
|
|
167
|
+
// against the production manifest on a build-time-cache hit.
|
|
168
|
+
...(options.forceBuild
|
|
169
|
+
? [hashClientRefs(state.projectRoot), hashServerRefs(state.projectRoot)]
|
|
170
|
+
: []),
|
|
171
|
+
createVersionPlugin(),
|
|
172
|
+
// Before the stub plugin, so "virtual:entry-ssr" resolves to the real
|
|
173
|
+
// SSR entry when the shell endpoint needs it (see the option doc).
|
|
174
|
+
...(options.realSsrEntry
|
|
175
|
+
? [
|
|
176
|
+
{
|
|
177
|
+
name: "@rangojs/router:temp-real-ssr-entry",
|
|
178
|
+
enforce: "pre" as const,
|
|
179
|
+
resolveId(id: string) {
|
|
180
|
+
return id === "virtual:entry-ssr"
|
|
181
|
+
? "\0rango-temp-real-ssr-entry"
|
|
182
|
+
: null;
|
|
183
|
+
},
|
|
184
|
+
load(id: string) {
|
|
185
|
+
return id === "\0rango-temp-real-ssr-entry"
|
|
186
|
+
? getVirtualEntrySSR(
|
|
187
|
+
state.opts?.headScripts,
|
|
188
|
+
state.opts?.progressiveChunkSize,
|
|
189
|
+
)
|
|
190
|
+
: null;
|
|
191
|
+
},
|
|
192
|
+
} satisfies import("vite").Plugin,
|
|
193
|
+
]
|
|
194
|
+
: []),
|
|
195
|
+
createVirtualStubPlugin(),
|
|
196
|
+
createCloudflareProtocolStubPlugin(),
|
|
197
|
+
// Inline transition({ when }) literals become client references here
|
|
198
|
+
// too, or discovery would see (and reject) the plain function.
|
|
199
|
+
transitionWhenHoistPlugin(),
|
|
200
|
+
// clientUrls() revalidate() predicates move to the server here too:
|
|
201
|
+
// discovery serializes the SSR copy's markers and the RSC realm
|
|
202
|
+
// registers the predicates the materialized stubs call. The index is
|
|
203
|
+
// the main plugin's, so its group modules import the files assigned here.
|
|
204
|
+
...clientUrlsRevalidateHoistPlugin(state.clientUrlRevalidate),
|
|
205
|
+
// Dev prerender must use dev-mode IDs (path-based) to match the workerd
|
|
206
|
+
// runtime. forceBuild produces hashed IDs for production bundle consistency.
|
|
207
|
+
exposeInternalIds(options.forceBuild ? { forceBuild: true } : undefined),
|
|
208
|
+
exposeRouterId(),
|
|
209
|
+
{
|
|
210
|
+
name: "@rangojs/router:client-urls-source-tracking",
|
|
211
|
+
enforce: "pre",
|
|
212
|
+
transform(code, id) {
|
|
213
|
+
recordClientUrlsModule(state, code, id);
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
// Forwarded user resolution plugins (e.g. vite-tsconfig-paths). Stripped
|
|
217
|
+
// to resolveId/load (plus transform for import rewriters, see
|
|
218
|
+
// IMPORT_REWRITE_PLUGINS) and placed last so framework resolution runs first;
|
|
219
|
+
// Vite re-sorts by `enforce`, so `enforce: "pre"` resolvers still lead.
|
|
220
|
+
...state.userResolvePlugins,
|
|
221
|
+
],
|
|
222
|
+
});
|
|
223
|
+
}
|
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
import { resolve } from "node:path";
|
|
11
11
|
|
|
12
12
|
import { escapeRegExp } from "../../regex-escape.js";
|
|
13
|
+
import { localRouteName, publicRouteName } from "../../route-name.js";
|
|
14
|
+
import type { LiveIntercept } from "../../router/prerender-match.js";
|
|
13
15
|
import { substitutePatternParams } from "../../router/substitute-pattern-params.js";
|
|
14
16
|
import { encodePathRemainder } from "../../router/url-params.js";
|
|
15
17
|
|
|
@@ -216,6 +218,51 @@ export function resolvePrerenderError(
|
|
|
216
218
|
throw error;
|
|
217
219
|
}
|
|
218
220
|
|
|
221
|
+
/**
|
|
222
|
+
* Warn once per router, route and slot (`warned` holds the keys already
|
|
223
|
+
* warned) that an intercept over a Prerender() route renders live: the build
|
|
224
|
+
* did not bake it (matchForPrerender `liveIntercepts`), so its handler runs
|
|
225
|
+
* per request and one that needs BuildContext fails there. A route in an
|
|
226
|
+
* unnamed include() has an internal key; the warning names its URL instead.
|
|
227
|
+
*/
|
|
228
|
+
export function warnLiveIntercepts(
|
|
229
|
+
warned: Set<string>,
|
|
230
|
+
routerId: string,
|
|
231
|
+
routeName: string,
|
|
232
|
+
urlPath: string,
|
|
233
|
+
liveIntercepts: readonly LiveIntercept[] | undefined,
|
|
234
|
+
): void {
|
|
235
|
+
for (const { slot, reason } of liveIntercepts ?? []) {
|
|
236
|
+
const key = `${routerId} ${routeName} ${slot}`;
|
|
237
|
+
if (warned.has(key)) continue;
|
|
238
|
+
warned.add(key);
|
|
239
|
+
const local = localRouteName(routeName);
|
|
240
|
+
const [why, fix] = {
|
|
241
|
+
"same-slot": [
|
|
242
|
+
`two intercepts on one layout fill ${slot}`,
|
|
243
|
+
"give each intercept its own slot",
|
|
244
|
+
],
|
|
245
|
+
"handler-response": [
|
|
246
|
+
`its handler returned a Response for ${urlPath}`,
|
|
247
|
+
"return a node from its handler at build time",
|
|
248
|
+
],
|
|
249
|
+
"layout-response": [
|
|
250
|
+
`its layout returned a Response for ${urlPath}`,
|
|
251
|
+
"return a node from its layout at build time",
|
|
252
|
+
],
|
|
253
|
+
"local-name": [
|
|
254
|
+
`it targets "${local}", the route's name inside its include()`,
|
|
255
|
+
`declare it inside the include() as ".${local}"`,
|
|
256
|
+
],
|
|
257
|
+
}[reason];
|
|
258
|
+
console.warn(
|
|
259
|
+
`[rango] Prerender route "${publicRouteName(routeName) ?? urlPath}": intercept ${slot} is not pre-rendered: ${why}. ` +
|
|
260
|
+
`A navigation that selects it renders it live, and its handler runs per request without BuildContext. ` +
|
|
261
|
+
`To pre-render it, ${fix}.`,
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
219
266
|
/** Build scratch space, relative to the project root. Never shipped. */
|
|
220
267
|
export const RANGO_BUILD_DIR = "node_modules/.rangojs-router-build";
|
|
221
268
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The router's `_rsc_*` query parameter names, shared by the browser and the
|
|
3
|
+
* server graph (dependency free): the one module that spells them
|
|
4
|
+
* (tools/check-internals.mjs rule rsc-param-literal). The browser writes the
|
|
5
|
+
* partial-request set through browser/wire-protocol.ts writePartialParams.
|
|
6
|
+
*/
|
|
7
|
+
export const WIRE = {
|
|
8
|
+
/** A navigation or prefetch: `true`. */
|
|
9
|
+
partial: "_rsc_partial",
|
|
10
|
+
/** The mounted segment ids, comma-joined. */
|
|
11
|
+
segments: "_rsc_segments",
|
|
12
|
+
/** A JS server action's id, in place of `partial`. */
|
|
13
|
+
action: "_rsc_action",
|
|
14
|
+
/** The client's build version (version-mismatch reload). */
|
|
15
|
+
version: "_rsc_v",
|
|
16
|
+
/** The client's router id (app-switch reload). */
|
|
17
|
+
routerId: "_rsc_rid",
|
|
18
|
+
/** The rewrite target of the page on screen (#1144). */
|
|
19
|
+
rewriteTarget: "_rsc_rt",
|
|
20
|
+
/** A stale request: `true` (router/navigation-snapshot.ts). */
|
|
21
|
+
stale: "_rsc_stale",
|
|
22
|
+
/** A fill request (docs/design/prefetch-false.md): `1`. */
|
|
23
|
+
fill: "_rsc_fill",
|
|
24
|
+
/** A loader fetch's loader id (rsc/loader-fetch.ts). */
|
|
25
|
+
loader: "_rsc_loader",
|
|
26
|
+
/** A loader fetch's params, JSON: a query param, or a form field on a POST. */
|
|
27
|
+
loaderParams: "_rsc_loader_params",
|
|
28
|
+
/** The forced-MISS marker of a degraded PPR shell reload (rsc/shell-serve.ts). */
|
|
29
|
+
shellMiss: "_rsc_shell",
|
|
30
|
+
/** A connection warmup HEAD request (browser/connection-warmup.ts). */
|
|
31
|
+
warmup: "_rsc_warmup",
|
|
32
|
+
} as const;
|
|
33
|
+
|
|
34
|
+
/** The prefix every name in WIRE starts with. */
|
|
35
|
+
export const WIRE_PREFIX = "_rsc_";
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Fresh Path Segment Resolution
|
|
3
|
-
*
|
|
4
|
-
* Functions for resolving segments during a full (non-revalidation) request.
|
|
5
|
-
* Handles loaders, layouts, routes, parallels, orphan layouts, and error boundaries.
|
|
6
|
-
*/
|
|
7
|
-
import { type EntryData } from "../../server/context";
|
|
8
|
-
import type { HandlerContext, ResolvedSegment } from "../../types";
|
|
9
|
-
import type { SegmentResolutionDeps } from "../types.js";
|
|
10
|
-
/**
|
|
11
|
-
* Resolve loaders for an entry and emit segments.
|
|
12
|
-
* Loaders are run lazily via ctx.use() and memoized for parallel execution.
|
|
13
|
-
*/
|
|
14
|
-
export declare function resolveLoaders<TEnv>(entry: EntryData, ctx: HandlerContext<any, TEnv>, belongsToRoute: boolean, deps: SegmentResolutionDeps<TEnv>, shortCodeOverride?: string): Promise<ResolvedSegment[]>;
|
|
15
|
-
/**
|
|
16
|
-
* Options for segment resolution.
|
|
17
|
-
*/
|
|
18
|
-
export interface ResolveSegmentOptions {
|
|
19
|
-
/** When true, skip resolveLoaders() calls (used for pre-rendering) */
|
|
20
|
-
skipLoaders?: boolean;
|
|
21
|
-
/**
|
|
22
|
-
* When true, a thrown render error is re-thrown instead of being converted
|
|
23
|
-
* into an error-boundary segment. Set only by the pre-render path so a
|
|
24
|
-
* build-time render failure (and a `throw new Skip()` inside a render fn)
|
|
25
|
-
* surfaces to the build instead of being silently baked into a frozen error
|
|
26
|
-
* page served as a 200 (issue #587). The live request path leaves this unset,
|
|
27
|
-
* so error boundaries keep catching at request time.
|
|
28
|
-
*/
|
|
29
|
-
throwOnError?: boolean;
|
|
30
|
-
/**
|
|
31
|
-
* The matched route's full entry chain. resolveAllSegments defaults it to
|
|
32
|
-
* its `entries`; withCacheLookup passes it when it resolves only the entries
|
|
33
|
-
* above a cache() boundary. An orphan list can hold an entry of the chain: a
|
|
34
|
-
* bare cache() marker sits in its layout's layout[] (it wraps that layout's
|
|
35
|
-
* routes) and is the parent of the routes after it. For those routes it
|
|
36
|
-
* resolves once, as a chain entry, below the cache() header latch (issue
|
|
37
|
-
* #918: resolved twice on a MISS, once and discarded on a HIT).
|
|
38
|
-
*/
|
|
39
|
-
chain?: readonly EntryData[];
|
|
40
|
-
/**
|
|
41
|
-
* The matched chain entry being resolved: where the sync path catches a
|
|
42
|
-
* handler error, so a streamed handler (or slot owned by a routeless layout)
|
|
43
|
-
* recovers into the same boundary. resolveSegment sets it for the entry it
|
|
44
|
-
* resolves; nested resolutions keep the outer value.
|
|
45
|
-
*/
|
|
46
|
-
boundaryEntry?: EntryData;
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Resolve segments from EntryData.
|
|
50
|
-
* Executes middlewares, loaders, parallels, and handlers in correct order.
|
|
51
|
-
* Returns array: [main segment, ...orphan layout segments]
|
|
52
|
-
*/
|
|
53
|
-
export declare function resolveSegment<TEnv>(entry: EntryData, routeKey: string, params: Record<string, string>, context: HandlerContext<any, TEnv>, loaderPromises: Map<string, Promise<any>>, deps: SegmentResolutionDeps<TEnv>, isRouteEntry?: boolean, options?: ResolveSegmentOptions): Promise<ResolvedSegment[]>;
|
|
54
|
-
/**
|
|
55
|
-
* Resolve orphan layout with its middlewares, loaders, and parallels.
|
|
56
|
-
*/
|
|
57
|
-
export declare function resolveOrphanLayout<TEnv>(orphan: EntryData, params: Record<string, string>, context: HandlerContext<any, TEnv>, loaderPromises: Map<string, Promise<any>>, belongsToRoute: boolean, deps: SegmentResolutionDeps<TEnv>, options?: ResolveSegmentOptions, routeKey?: string,
|
|
58
|
-
/** Parent route entry — its loaders are inherited by the layout so
|
|
59
|
-
* parallel slots inside this layout can access them via useLoader(). */
|
|
60
|
-
parentRouteEntry?: EntryData): Promise<ResolvedSegment[]>;
|
|
61
|
-
/**
|
|
62
|
-
* Resolve parallel EntryData with its loaders and slot handlers.
|
|
63
|
-
*/
|
|
64
|
-
export declare function resolveParallelEntry<TEnv>(parallelEntry: EntryData, params: Record<string, string>, context: HandlerContext<any, TEnv>, belongsToRoute: boolean, parentShortCode: string, deps: SegmentResolutionDeps<TEnv>, options?: ResolveSegmentOptions, routeKey?: string, slotNames?: `@${string}`[], includeLoaders?: boolean): Promise<ResolvedSegment[]>;
|
|
65
|
-
/**
|
|
66
|
-
* Resolve all segments for a route (used for single-cache-per-request pattern).
|
|
67
|
-
*/
|
|
68
|
-
export declare function resolveAllSegments<TEnv>(entries: EntryData[], routeKey: string, params: Record<string, string>, context: HandlerContext<any, TEnv>, loaderPromises: Map<string, Promise<any>>, deps: SegmentResolutionDeps<TEnv>, options?: ResolveSegmentOptions): Promise<ResolvedSegment[]>;
|
|
69
|
-
/**
|
|
70
|
-
* Resolve only loader segments for all entries (used when serving cached non-loader segments).
|
|
71
|
-
*/
|
|
72
|
-
export declare function resolveLoadersOnly<TEnv>(entries: EntryData[], context: HandlerContext<any, TEnv>, deps: SegmentResolutionDeps<TEnv>): Promise<ResolvedSegment[]>;
|