@rangojs/router 0.19.1 → 0.21.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 +26 -14
- package/dist/types/browser/event-controller.d.ts +32 -0
- package/dist/types/browser/history-state.d.ts +16 -4
- package/dist/types/browser/navigation-transaction.d.ts +7 -0
- package/dist/types/browser/rango-state.d.ts +3 -1
- package/dist/types/browser/react/context.d.ts +11 -0
- package/dist/types/browser/react/location-state-shared.d.ts +84 -10
- package/dist/types/browser/react/location-state.d.ts +7 -2
- package/dist/types/browser/react/subscribe-to-nothing.d.ts +7 -0
- package/dist/types/cache/cache-scope.d.ts +4 -5
- package/dist/types/cache/cf/cf-cache-store.d.ts +27 -6
- package/dist/types/cache/cf/cf-cache-types.d.ts +12 -4
- package/dist/types/cache/handle-snapshot.d.ts +36 -50
- package/dist/types/cache/index.d.ts +2 -0
- package/dist/types/cache/shell-snapshot.d.ts +19 -3
- package/dist/types/cache/types.d.ts +21 -10
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +28 -16
- package/dist/types/client-urls/navigation.d.ts +7 -1
- package/dist/types/client-urls/optimistic-location.d.ts +10 -4
- package/dist/types/handles/deferred-resolution.d.ts +11 -1
- package/dist/types/prerender/build-shell-capture.d.ts +8 -6
- package/dist/types/router/match-middleware/cache-lookup.d.ts +1 -1
- package/dist/types/router/navigation-snapshot.d.ts +8 -1
- package/dist/types/router/router-interfaces.d.ts +2 -1
- package/dist/types/router/router-options.d.ts +17 -7
- package/dist/types/router/segment-resolution/loader-cache.d.ts +21 -9
- package/dist/types/router-versions.d.ts +39 -0
- package/dist/types/rsc/handler-context.d.ts +5 -0
- package/dist/types/rsc/shell-build-manifest.d.ts +3 -2
- package/dist/types/rsc/types.d.ts +4 -6
- package/dist/types/server/build-version-table.d.ts +44 -0
- package/dist/types/server/handle-store.d.ts +87 -46
- package/dist/types/server/request-context.d.ts +22 -8
- package/dist/types/ssr/entry-preload-priority.d.ts +69 -0
- package/dist/types/ssr/index.d.ts +1 -0
- package/dist/types/ssr/preinit-client-references.d.ts +17 -5
- package/dist/types/testing/build-versions.d.ts +32 -0
- package/dist/types/testing/dom.entry.d.ts +1 -1
- package/dist/types/testing/flight.entry.d.ts +1 -1
- package/dist/types/testing/index.d.ts +2 -0
- package/dist/types/testing/internal/seed-vars.d.ts +7 -2
- package/dist/types/testing/location-state-key.d.ts +5 -1
- package/dist/types/testing/render-route.d.ts +77 -6
- package/dist/types/testing/serve-shell-request.d.ts +21 -0
- package/dist/types/testing/vitest-stubs/version.d.ts +1 -0
- package/dist/types/types/handler-context.d.ts +8 -5
- package/dist/types/vite/discovery/build-versions.d.ts +393 -0
- package/dist/types/vite/discovery/installed-packages.d.ts +26 -0
- package/dist/types/vite/discovery/router-versions-phase.d.ts +52 -0
- package/dist/types/vite/discovery/shell-prerender-phase.d.ts +7 -17
- package/dist/types/vite/discovery/state.d.ts +14 -0
- package/dist/types/vite/encryption-key.d.ts +18 -0
- package/dist/types/vite/plugin-types.d.ts +47 -6
- package/dist/types/vite/plugins/{version-injector.d.ts → entry-bootstrap-injector.d.ts} +4 -6
- package/dist/types/vite/plugins/expose-ids/export-analysis.d.ts +1 -0
- package/dist/types/vite/plugins/expose-ids/router-transform.d.ts +14 -0
- package/dist/types/vite/plugins/stable-rsc-output.d.ts +51 -0
- package/dist/types/vite/plugins/version-plugin.d.ts +9 -11
- package/dist/types/vite/plugins/virtual-entries.d.ts +21 -2
- package/dist/types/vite/router-discovery.d.ts +6 -0
- package/dist/types/vite/utils/client-chunks.d.ts +24 -2
- package/dist/types/vite/utils/compare-strings.d.ts +7 -0
- package/dist/types/vite/utils/package-resolution.d.ts +8 -0
- package/dist/types/vite/utils/prerender-utils.d.ts +2 -0
- package/dist/vite/index.js +1544 -420
- package/package.json +1 -2
- package/skills/bundle-analysis/SKILL.md +1 -1
- package/skills/cache-guide/SKILL.md +84 -20
- package/skills/caching/SKILL.md +16 -5
- package/skills/client-urls/SKILL.md +16 -0
- package/skills/cloudflare/SKILL.md +2 -1
- package/skills/comparison/references/framework-comparison.md +16 -12
- package/skills/hooks/SKILL.md +3 -0
- package/skills/hooks/handle-and-actions.md +6 -0
- package/skills/hooks/navigation.md +28 -0
- package/skills/hooks/state.md +209 -8
- package/skills/hooks/urls.md +40 -1
- package/skills/host-router/SKILL.md +13 -0
- package/skills/intercept/SKILL.md +6 -0
- package/skills/loader/SKILL.md +19 -1
- package/skills/middleware/SKILL.md +2 -0
- package/skills/ppr/SKILL.md +119 -40
- package/skills/prerender/SKILL.md +7 -3
- package/skills/rango/SKILL.md +8 -7
- package/skills/router-setup/SKILL.md +23 -3
- package/skills/testing/SKILL.md +30 -26
- package/skills/testing/client-components.md +193 -8
- package/skills/testing/handles.md +2 -0
- package/skills/testing/loader.md +1 -1
- package/skills/testing/middleware.md +1 -1
- package/skills/testing/render-handler.md +18 -18
- package/skills/testing/serve-shell-request.md +63 -14
- package/skills/testing/server-actions.md +17 -17
- package/skills/testing/server-tree.md +1 -1
- package/skills/typesafety/generated-files-and-cli.md +1 -1
- package/skills/use-cache/SKILL.md +16 -5
- package/skills/vercel/SKILL.md +3 -3
- package/src/bin/rango.ts +1 -1
- package/src/browser/event-controller.ts +75 -2
- package/src/browser/history-state.ts +39 -17
- package/src/browser/navigation-bridge.ts +41 -18
- package/src/browser/navigation-transaction.ts +15 -10
- package/src/browser/partial-update.ts +10 -2
- package/src/browser/rango-state.ts +3 -1
- package/src/browser/react/Link.tsx +2 -3
- package/src/browser/react/NavigationProvider.tsx +25 -1
- package/src/browser/react/context.ts +13 -0
- package/src/browser/react/location-state-shared.ts +200 -34
- package/src/browser/react/location-state.ts +40 -75
- package/src/browser/react/subscribe-to-nothing.ts +7 -0
- package/src/browser/react/use-handle.ts +20 -1
- package/src/browser/rsc-router.tsx +33 -11
- package/src/browser/server-action-bridge.ts +17 -1
- package/src/cache/cache-scope.ts +18 -8
- package/src/cache/cf/cf-cache-store.ts +75 -55
- package/src/cache/cf/cf-cache-types.ts +12 -4
- package/src/cache/handle-snapshot.ts +69 -87
- package/src/cache/index.ts +4 -0
- package/src/cache/shell-snapshot.ts +35 -5
- package/src/cache/types.ts +21 -10
- package/src/cache/vercel/vercel-cache-store.ts +48 -20
- package/src/client-urls/client-root.tsx +1 -0
- package/src/client-urls/navigation.ts +10 -0
- package/src/client-urls/optimistic-location.ts +10 -4
- package/src/handles/deferred-resolution.ts +31 -0
- package/src/prerender/build-shell-capture.ts +11 -9
- package/src/router/manifest.ts +2 -0
- package/src/router/match-middleware/cache-lookup.ts +11 -18
- package/src/router/navigation-snapshot.ts +25 -6
- package/src/router/request-classification.ts +15 -12
- package/src/router/router-interfaces.ts +2 -1
- package/src/router/router-options.ts +17 -7
- package/src/router/segment-resolution/loader-cache.ts +95 -60
- package/src/router-versions.ts +60 -0
- package/src/rsc/full-payload.ts +6 -2
- package/src/rsc/handler-context.ts +5 -0
- package/src/rsc/handler.ts +14 -4
- package/src/rsc/rsc-rendering.ts +12 -1
- package/src/rsc/shell-build-manifest.ts +10 -7
- package/src/rsc/shell-capture.ts +36 -26
- package/src/rsc/types.ts +4 -6
- package/src/server/build-version-table.ts +115 -0
- package/src/server/handle-store.ts +344 -127
- package/src/server/request-context.ts +62 -11
- package/src/ssr/entry-preload-priority.ts +308 -0
- package/src/ssr/index.tsx +46 -9
- package/src/ssr/preinit-client-references.ts +17 -5
- package/src/ssr/ssr-root.tsx +16 -4
- package/src/testing/build-versions.ts +64 -0
- package/src/testing/dispatch.ts +6 -0
- package/src/testing/dom.entry.ts +1 -0
- package/src/testing/flight.entry.ts +1 -0
- package/src/testing/index.ts +3 -0
- package/src/testing/internal/context.ts +2 -1
- package/src/testing/internal/seed-vars.ts +14 -2
- package/src/testing/location-state-key.ts +18 -8
- package/src/testing/render-handler.ts +2 -1
- package/src/testing/render-route.tsx +277 -43
- package/src/testing/serve-shell-request.ts +80 -11
- package/src/testing/vitest-stubs/version.ts +4 -1
- package/src/types/handler-context.ts +8 -5
- package/src/vite/discovery/build-versions.ts +1281 -0
- package/src/vite/discovery/installed-packages.ts +159 -0
- package/src/vite/discovery/prerender-collection.ts +38 -1
- package/src/vite/discovery/router-versions-phase.ts +336 -0
- package/src/vite/discovery/shell-prerender-phase.ts +28 -38
- package/src/vite/discovery/state.ts +19 -0
- package/src/vite/discovery/virtual-module-codegen.ts +7 -2
- package/src/vite/encryption-key.ts +101 -9
- package/src/vite/plugin-types.ts +48 -6
- package/src/vite/plugins/{version-injector.ts → entry-bootstrap-injector.ts} +7 -22
- package/src/vite/plugins/expose-ids/export-analysis.ts +1 -1
- package/src/vite/plugins/expose-ids/router-transform.ts +36 -15
- package/src/vite/plugins/expose-internal-ids.ts +12 -3
- package/src/vite/plugins/stable-rsc-output.ts +147 -0
- package/src/vite/plugins/version-plugin.ts +19 -24
- package/src/vite/plugins/version.d.ts +17 -2
- package/src/vite/plugins/virtual-entries.ts +40 -7
- package/src/vite/rango.ts +30 -3
- package/src/vite/router-discovery.ts +82 -13
- package/src/vite/utils/client-chunks.ts +84 -14
- package/src/vite/utils/compare-strings.ts +9 -0
- package/src/vite/utils/package-resolution.ts +9 -0
- package/src/vite/utils/prerender-utils.ts +4 -1
- package/src/vite/utils/shared-utils.ts +1 -1
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { parseAst, type Plugin } from "vite";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
VIRTUAL_IDS,
|
|
4
|
+
getVirtualBuildVersionContent,
|
|
5
|
+
getVirtualVersionContent,
|
|
6
|
+
} from "./virtual-entries.js";
|
|
3
7
|
import { hasUseClientDirective } from "../utils/directive-prologue.js";
|
|
4
8
|
|
|
5
9
|
interface ClientModuleSignature {
|
|
@@ -100,25 +104,22 @@ function getClientModuleSignature(
|
|
|
100
104
|
}
|
|
101
105
|
|
|
102
106
|
/**
|
|
103
|
-
* Plugin providing
|
|
104
|
-
* Exports VERSION that changes when RSC modules change (dev) or at build time (production).
|
|
107
|
+
* Plugin providing the `@rangojs/router:version` virtual module.
|
|
105
108
|
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
+
* Dev: exports a VERSION stamp used for both versions of every router. It
|
|
110
|
+
* updates when the server starts and when an RSC module changes via HMR (the
|
|
111
|
+
* version module is invalidated). Client-only HMR changes do not update it:
|
|
112
|
+
* they do not affect server-rendered content or cached RSC payloads.
|
|
109
113
|
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
* Client-only HMR changes don't update the version since they don't affect
|
|
115
|
-
* server-rendered content or cached RSC payloads.
|
|
114
|
+
* Build: exports a placeholder for the per-router versions table. The module
|
|
115
|
+
* holds nothing that varies between builds; the table is written into the
|
|
116
|
+
* built chunk after the server output is hashed (the buildApp post hook in
|
|
117
|
+
* router-discovery.ts). See docs/design/per-app-cache-version.md.
|
|
116
118
|
* @internal
|
|
117
119
|
*/
|
|
118
120
|
export function createVersionPlugin(): Plugin {
|
|
119
|
-
//
|
|
120
|
-
|
|
121
|
-
let currentVersion = buildVersion;
|
|
121
|
+
// Dev stamp, generated at plugin creation (server start).
|
|
122
|
+
let currentVersion = Date.now().toString(16);
|
|
122
123
|
let isDev = false;
|
|
123
124
|
let server: any = null;
|
|
124
125
|
let resolvedCacheDir: string | undefined;
|
|
@@ -142,14 +143,6 @@ export function createVersionPlugin(): Plugin {
|
|
|
142
143
|
name: "@rangojs/router:version",
|
|
143
144
|
enforce: "pre",
|
|
144
145
|
|
|
145
|
-
// The build-time shell capture phase (producer B, #699) stamps entries
|
|
146
|
-
// with THIS instance's version — the value folded into the shipped worker
|
|
147
|
-
// — never the discovery temp server's own version-plugin value (a
|
|
148
|
-
// different Date.now() stamp that would fail the serve-side gate).
|
|
149
|
-
api: {
|
|
150
|
-
getBuildVersion: (): string => currentVersion,
|
|
151
|
-
},
|
|
152
|
-
|
|
153
146
|
configResolved(config) {
|
|
154
147
|
isDev = config.command === "serve";
|
|
155
148
|
resolvedCacheDir = config.cacheDir
|
|
@@ -177,7 +170,9 @@ export function createVersionPlugin(): Plugin {
|
|
|
177
170
|
|
|
178
171
|
load(id) {
|
|
179
172
|
if (id === "\0" + VIRTUAL_IDS.version) {
|
|
180
|
-
return
|
|
173
|
+
return isDev
|
|
174
|
+
? getVirtualVersionContent(currentVersion)
|
|
175
|
+
: getVirtualBuildVersionContent();
|
|
181
176
|
}
|
|
182
177
|
return null;
|
|
183
178
|
},
|
|
@@ -5,8 +5,23 @@
|
|
|
5
5
|
|
|
6
6
|
declare module "@rangojs/router:version" {
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* The build's version string.
|
|
9
|
+
*
|
|
10
|
+
* - Dev: a stamp that changes on server start and on every RSC module edit.
|
|
11
|
+
* - Production: the whole-build document version, a hash of the server
|
|
12
|
+
* output and the client asset names. The same source builds to the same
|
|
13
|
+
* value; any change to any router changes it.
|
|
14
|
+
*
|
|
15
|
+
* A router serves with its own versions (`ROUTER_VERSIONS`), not this one.
|
|
10
16
|
*/
|
|
11
17
|
export const VERSION: string;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Per-router cache versions computed at build time: router id to
|
|
21
|
+
* `[data, document]`, with `"*"` holding the whole-build pair.
|
|
22
|
+
* `undefined` in dev, where `VERSION` is used for both.
|
|
23
|
+
*/
|
|
24
|
+
export const ROUTER_VERSIONS:
|
|
25
|
+
| Readonly<Record<string, readonly [data: string, document: string]>>
|
|
26
|
+
| undefined;
|
|
12
27
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { HeadScriptsOption } from "../plugin-types.js";
|
|
2
|
+
import { DEFAULT_ROUTER_VERSIONS_KEY } from "../../router-versions.js";
|
|
2
3
|
|
|
3
4
|
export const VIRTUAL_ENTRY_BROWSER: string = `
|
|
4
5
|
import {
|
|
@@ -65,13 +66,20 @@ function emitProgressiveChunkSize(value: number): string {
|
|
|
65
66
|
* option: "preinit" (default) installs the client-reference preinit hook and
|
|
66
67
|
* threads `getClientEntryUrl` so Fizz emits `bootstrapModules`;
|
|
67
68
|
* "preload" omits the hook and uses the deprecated inline
|
|
68
|
-
* `loadBootstrapScriptContent` bootstrap.
|
|
69
|
+
* `loadBootstrapScriptContent` bootstrap. Any other value throws: an unknown
|
|
70
|
+
* string such as "prenit" used to run as "preinit" silently
|
|
71
|
+
* (`headScripts !== "preload"` since #694).
|
|
69
72
|
*/
|
|
70
73
|
export function getVirtualEntrySSR(
|
|
71
74
|
headScripts: HeadScriptsOption = "preinit",
|
|
72
75
|
progressiveChunkSize?: number,
|
|
73
76
|
): string {
|
|
74
|
-
|
|
77
|
+
if (headScripts !== "preinit" && headScripts !== "preload") {
|
|
78
|
+
throw new Error(
|
|
79
|
+
`rango({ headScripts }) must be "preinit" or "preload", received ${JSON.stringify(headScripts)}`,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
const preinit = headScripts === "preinit";
|
|
75
83
|
// The preload variant drops the preinit-only imports/install and swaps the
|
|
76
84
|
// bootstrap dep, all built here so the template below stays a single
|
|
77
85
|
// unconditional shape.
|
|
@@ -157,7 +165,7 @@ export const resumeShellHTML = createShellResumeHandler({
|
|
|
157
165
|
* registered for the _rsc_loader endpoint and fail in production.
|
|
158
166
|
*
|
|
159
167
|
* Single source of truth: both the generated virtual RSC entry below and the
|
|
160
|
-
* custom-entry injector (
|
|
168
|
+
* custom-entry injector (entry-bootstrap-injector) consume this list, so a new
|
|
161
169
|
* bootstrap manifest cannot be added to one path and forgotten on the other.
|
|
162
170
|
* That exact drift (loader-manifest present here but missing from the injector)
|
|
163
171
|
* is what left fetchable loaders unresolved on custom worker entries.
|
|
@@ -190,12 +198,11 @@ import {
|
|
|
190
198
|
// consults them at router-module evaluation. Router-first would silently push
|
|
191
199
|
// every clientUrls() app onto the deferred-subscription path and change mount
|
|
192
200
|
// registration order with no error. The custom-entry injector keeps the same
|
|
193
|
-
// guarantee by PREPENDING this list at file top (
|
|
201
|
+
// guarantee by PREPENDING this list at file top (entry-bootstrap-injector.ts).
|
|
194
202
|
${bootstrapImports}
|
|
195
203
|
|
|
196
204
|
import { router } from "${routerPath}";
|
|
197
205
|
import { createRSCHandler } from "@rangojs/router/internal/rsc-handler";
|
|
198
|
-
import { VERSION } from "@rangojs/router:version";
|
|
199
206
|
|
|
200
207
|
// Lazily create the handler on first request so that ESM live bindings
|
|
201
208
|
// have resolved by the time we read \`router\`. During HMR the module may
|
|
@@ -205,7 +212,6 @@ export default function handler(request, env) {
|
|
|
205
212
|
if (!_handler) {
|
|
206
213
|
_handler = createRSCHandler({
|
|
207
214
|
router,
|
|
208
|
-
version: VERSION,
|
|
209
215
|
// Forward the router's CSP nonce provider. createRSCHandler reads the
|
|
210
216
|
// provider only from options.nonce; without this, createRouter({ nonce })
|
|
211
217
|
// is silently dropped on the Node preset (the Cloudflare path wires it via
|
|
@@ -307,6 +313,33 @@ export const VIRTUAL_IDS = {
|
|
|
307
313
|
version: "@rangojs/router:version",
|
|
308
314
|
} as const;
|
|
309
315
|
|
|
316
|
+
/** Dev: one stamp for both versions of every router, bumped on RSC edits. */
|
|
310
317
|
export function getVirtualVersionContent(version: string): string {
|
|
311
|
-
return
|
|
318
|
+
return [
|
|
319
|
+
`export const VERSION = ${JSON.stringify(version)};`,
|
|
320
|
+
`export const ROUTER_VERSIONS = undefined;`,
|
|
321
|
+
].join("\n");
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Free identifier the production version module ships in place of the table.
|
|
326
|
+
* The versions are hashes of the built server code, so they cannot be part of
|
|
327
|
+
* it: the buildApp post hook (router-discovery.ts) replaces this token in the
|
|
328
|
+
* written chunk once the hashes are final (runRouterVersionsPhase,
|
|
329
|
+
* discovery/router-versions-phase.ts). An unreplaced token throws a ReferenceError
|
|
330
|
+
* when the module evaluates, so a build that skipped the step cannot serve
|
|
331
|
+
* with a constant version.
|
|
332
|
+
*/
|
|
333
|
+
export const ROUTER_VERSIONS_PLACEHOLDER = "__RANGO_ROUTER_VERSIONS__";
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Production: byte-identical in every build, so it never moves the hashes it
|
|
337
|
+
* is later filled with. VERSION is the whole-build document version (the
|
|
338
|
+
* table's "*" entry).
|
|
339
|
+
*/
|
|
340
|
+
export function getVirtualBuildVersionContent(): string {
|
|
341
|
+
return [
|
|
342
|
+
`export const ROUTER_VERSIONS = ${ROUTER_VERSIONS_PLACEHOLDER};`,
|
|
343
|
+
`export const VERSION = ROUTER_VERSIONS[${JSON.stringify(DEFAULT_ROUTER_VERSIONS_KEY)}][1];`,
|
|
344
|
+
].join("\n");
|
|
312
345
|
}
|
package/src/vite/rango.ts
CHANGED
|
@@ -2,7 +2,10 @@ import { type PluginOption } from "vite";
|
|
|
2
2
|
import { readFileSync, existsSync } from "node:fs";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
import { exposeActionId } from "./plugins/expose-action-id.js";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
configureEncryptionKey,
|
|
7
|
+
defineEncryptionKeyExpr,
|
|
8
|
+
} from "./encryption-key.js";
|
|
6
9
|
import {
|
|
7
10
|
createLoaderDirectiveGuardPlugin,
|
|
8
11
|
createLoaderScanStubPlugin,
|
|
@@ -12,6 +15,7 @@ import {
|
|
|
12
15
|
import { useCacheTransform } from "./plugins/use-cache-transform.js";
|
|
13
16
|
import { transitionWhenHoistPlugin } from "./plugins/transition-when-hoist.js";
|
|
14
17
|
import { clientRefDedup } from "./plugins/client-ref-dedup.js";
|
|
18
|
+
import { stableRscOutput } from "./plugins/stable-rsc-output.js";
|
|
15
19
|
import { VIRTUAL_IDS } from "./plugins/virtual-entries.js";
|
|
16
20
|
import {
|
|
17
21
|
getExcludeDeps,
|
|
@@ -32,6 +36,7 @@ import {
|
|
|
32
36
|
getManualChunks,
|
|
33
37
|
} from "./utils/shared-utils.js";
|
|
34
38
|
import {
|
|
39
|
+
clientChunksReport,
|
|
35
40
|
resolveClientChunks,
|
|
36
41
|
type ClientChunkContext,
|
|
37
42
|
} from "./utils/client-chunks.js";
|
|
@@ -42,7 +47,7 @@ import type {
|
|
|
42
47
|
} from "./plugin-types.js";
|
|
43
48
|
import { createVercelOutputPlugin } from "./plugins/vercel-output.js";
|
|
44
49
|
import { printBanner, rangoVersion } from "./utils/banner.js";
|
|
45
|
-
import {
|
|
50
|
+
import { createEntryBootstrapInjectorPlugin } from "./plugins/entry-bootstrap-injector.js";
|
|
46
51
|
import { createCjsToEsmPlugin } from "./plugins/cjs-to-esm.js";
|
|
47
52
|
import { createRouterDiscoveryPlugin } from "./router-discovery.js";
|
|
48
53
|
import { performanceTracksPlugin } from "./plugins/performance-tracks.js";
|
|
@@ -75,6 +80,20 @@ const debugConfig = createRangoDebugger(NS.config);
|
|
|
75
80
|
*/
|
|
76
81
|
const SERVER_BUILD_TARGET = "esnext";
|
|
77
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Entry-signature mode for the node/vercel RSC build, the one
|
|
85
|
+
* `@cloudflare/vite-plugin` forces on its worker entry.
|
|
86
|
+
*
|
|
87
|
+
* Vite's default for a server build, "allow-extension", lets the bundler park
|
|
88
|
+
* modules shared with lazy chunks in the entry chunk. Under a host router that
|
|
89
|
+
* put the router runtime (80 modules, measured on e2e/test-app/.host-fixture
|
|
90
|
+
* and examples/vercel-multi-router) and every sub-app's route names into
|
|
91
|
+
* `index.js`, which every sub-app chunk imported back and which names each
|
|
92
|
+
* sub-app chunk by its content hash: no router's cache version was independent
|
|
93
|
+
* of the others (discovery/build-versions.ts hashes a router's chunks).
|
|
94
|
+
*/
|
|
95
|
+
const RSC_ENTRY_SIGNATURES = "strict";
|
|
96
|
+
|
|
78
97
|
// The leading-directive 'use client' sniff is shared with version-plugin's
|
|
79
98
|
// getClientModuleSignature so the two cannot drift. Imported for local use by the
|
|
80
99
|
// HMR transform below and re-exported because the E8 sniff test imports it from
|
|
@@ -110,6 +129,9 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
110
129
|
const rangoStart = performance.now();
|
|
111
130
|
const resolvedOptions: RangoOptions = options ?? { preset: "node" };
|
|
112
131
|
const preset = resolvedOptions.preset ?? "node";
|
|
132
|
+
// Before any plugin-rsc instance (this build's, the discovery temp server's)
|
|
133
|
+
// reads the key, and so an invalid key fails the config load.
|
|
134
|
+
configureEncryptionKey(resolvedOptions.encryptionKey);
|
|
113
135
|
const showBanner = resolvedOptions.banner ?? true;
|
|
114
136
|
const clientChunksOption = resolvedOptions.clientChunks ?? true;
|
|
115
137
|
const useBuiltInClientChunks = clientChunksOption === true;
|
|
@@ -466,6 +488,9 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
466
488
|
...(vercelServerEnv ?? {}),
|
|
467
489
|
build: {
|
|
468
490
|
target: SERVER_BUILD_TARGET,
|
|
491
|
+
rollupOptions: {
|
|
492
|
+
preserveEntrySignatures: RSC_ENTRY_SIGNATURES,
|
|
493
|
+
},
|
|
469
494
|
},
|
|
470
495
|
optimizeDeps: {
|
|
471
496
|
entries: [VIRTUAL_IDS.rsc],
|
|
@@ -537,6 +562,8 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
537
562
|
);
|
|
538
563
|
plugins.push(clientRefDedup());
|
|
539
564
|
}
|
|
565
|
+
plugins.push(clientChunksReport());
|
|
566
|
+
plugins.push(stableRscOutput());
|
|
540
567
|
|
|
541
568
|
plugins.push({
|
|
542
569
|
name: "@rangojs/router:client-component-hmr",
|
|
@@ -581,7 +608,7 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
581
608
|
const discoveryRouterRef = preset !== "cloudflare" ? routerRef : undefined;
|
|
582
609
|
|
|
583
610
|
if (preset === "cloudflare") {
|
|
584
|
-
plugins.push(
|
|
611
|
+
plugins.push(createEntryBootstrapInjectorPlugin(undefined));
|
|
585
612
|
}
|
|
586
613
|
|
|
587
614
|
plugins.push(createCjsToEsmPlugin());
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
import type { Plugin, ViteDevServer } from "vite";
|
|
10
10
|
import { createServer as createViteServer } from "vite";
|
|
11
|
-
import { resolve } from "node:path";
|
|
12
|
-
import { readFileSync } from "node:fs";
|
|
11
|
+
import { dirname, join, resolve } from "node:path";
|
|
12
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
13
13
|
import { createRequire, register } from "node:module";
|
|
14
14
|
import { pathToFileURL } from "node:url";
|
|
15
15
|
import {
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
internalDebugNoCacheMiddleware,
|
|
35
35
|
} from "./inject-client-debug.js";
|
|
36
36
|
import { createVersionPlugin } from "./plugins/version-plugin.js";
|
|
37
|
+
import { uniformVersions } from "../router-versions.js";
|
|
37
38
|
import { getVirtualEntrySSR, VIRTUAL_IDS } from "./plugins/virtual-entries.js";
|
|
38
39
|
import { createVirtualStubPlugin } from "./plugins/virtual-stub-plugin.js";
|
|
39
40
|
import {
|
|
@@ -64,6 +65,13 @@ import {
|
|
|
64
65
|
refreshRecordedClientUrlProjections,
|
|
65
66
|
} from "./discovery/client-urls-projection.js";
|
|
66
67
|
import { runShellPrerenderPhase } from "./discovery/shell-prerender-phase.js";
|
|
68
|
+
import { runRouterVersionsPhase } from "./discovery/router-versions-phase.js";
|
|
69
|
+
import {
|
|
70
|
+
recordBundleFiles,
|
|
71
|
+
recordClientGraph,
|
|
72
|
+
recordServerGraph,
|
|
73
|
+
recordVersionModuleFiles,
|
|
74
|
+
} from "./discovery/build-versions.js";
|
|
67
75
|
import { describeDiscoveryFailure } from "./discovery/discovery-errors.js";
|
|
68
76
|
import { findTransitionWhenError } from "../transition-when-ref.js";
|
|
69
77
|
import { transitionWhenHoistPlugin } from "./plugins/transition-when-hoist.js";
|
|
@@ -320,11 +328,44 @@ import type {
|
|
|
320
328
|
BuildEnvResult,
|
|
321
329
|
} from "./plugin-types.js";
|
|
322
330
|
|
|
331
|
+
const WRANGLER_CONFIG_NAMES: readonly string[] = [
|
|
332
|
+
"wrangler.json",
|
|
333
|
+
"wrangler.jsonc",
|
|
334
|
+
"wrangler.toml",
|
|
335
|
+
];
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* getPlatformProxy() looks for the wrangler config from process.cwd() and
|
|
339
|
+
* resolves its default persist path against cwd, so building from another
|
|
340
|
+
* directory dropped the app's bindings (#1037). Search upward from the Vite
|
|
341
|
+
* root with wrangler's own file names and order. Persisted state goes under
|
|
342
|
+
* the Vite root, where @cloudflare/vite-plugin reads it in dev and preview
|
|
343
|
+
* (its getPersistenceRoot), also when the config sits above the root. No
|
|
344
|
+
* config found: no options, wrangler's own lookup.
|
|
345
|
+
*/
|
|
346
|
+
function wranglerProxyOptions(
|
|
347
|
+
root: string,
|
|
348
|
+
): Record<string, unknown> | undefined {
|
|
349
|
+
const viteRoot = resolve(root);
|
|
350
|
+
for (let dir = viteRoot; ; dir = dirname(dir)) {
|
|
351
|
+
for (const name of WRANGLER_CONFIG_NAMES) {
|
|
352
|
+
const configPath = join(dir, name);
|
|
353
|
+
if (existsSync(configPath)) {
|
|
354
|
+
return {
|
|
355
|
+
configPath,
|
|
356
|
+
persist: { path: join(viteRoot, ".wrangler", "state", "v3") },
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (dirname(dir) === dir) return undefined;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
323
364
|
/**
|
|
324
365
|
* Resolve the buildEnv option into a concrete { env, dispose? } result.
|
|
325
366
|
* Handles all four input shapes: false, "auto", factory, plain object.
|
|
326
367
|
*/
|
|
327
|
-
async function resolveBuildEnv(
|
|
368
|
+
export async function resolveBuildEnv(
|
|
328
369
|
option: BuildEnvOption | undefined,
|
|
329
370
|
factoryCtx: BuildEnvFactoryContext,
|
|
330
371
|
): Promise<BuildEnvResult | null> {
|
|
@@ -348,7 +389,9 @@ async function resolveBuildEnv(
|
|
|
348
389
|
)) as {
|
|
349
390
|
getPlatformProxy: (opts?: any) => Promise<any>;
|
|
350
391
|
};
|
|
351
|
-
const proxy = await getPlatformProxy(
|
|
392
|
+
const proxy = await getPlatformProxy(
|
|
393
|
+
wranglerProxyOptions(factoryCtx.root),
|
|
394
|
+
);
|
|
352
395
|
return {
|
|
353
396
|
env: proxy.env as Record<string, unknown>,
|
|
354
397
|
dispose: proxy.dispose,
|
|
@@ -410,6 +453,7 @@ function resetPrerenderCollection(s: DiscoveryState): void {
|
|
|
410
453
|
s.staticManifestEntries = null;
|
|
411
454
|
s.shellCandidates = null;
|
|
412
455
|
s.prerenderPayloadValues = null;
|
|
456
|
+
s.buildData = [];
|
|
413
457
|
}
|
|
414
458
|
|
|
415
459
|
/**
|
|
@@ -1533,7 +1577,7 @@ export function createRouterDiscoveryPlugin(
|
|
|
1533
1577
|
maxSnapshotBytes,
|
|
1534
1578
|
captureTimeout,
|
|
1535
1579
|
buildEnv: s.resolvedBuildEnv,
|
|
1536
|
-
|
|
1580
|
+
versions: uniformVersions(version),
|
|
1537
1581
|
captureShellHTML: ssrModule.captureShellHTML,
|
|
1538
1582
|
debug: !!debugDiscovery,
|
|
1539
1583
|
});
|
|
@@ -2261,18 +2305,27 @@ export function createRouterDiscoveryPlugin(
|
|
|
2261
2305
|
}
|
|
2262
2306
|
},
|
|
2263
2307
|
|
|
2264
|
-
// Post-build
|
|
2265
|
-
//
|
|
2266
|
-
//
|
|
2267
|
-
//
|
|
2268
|
-
//
|
|
2269
|
-
//
|
|
2270
|
-
//
|
|
2308
|
+
// Post-build phases, after EVERY environment bundle is written.
|
|
2309
|
+
//
|
|
2310
|
+
// 1. Cache versions (discovery/router-versions-phase.ts): hashes the
|
|
2311
|
+
// server output as postprocessBundle left it and writes the per-router
|
|
2312
|
+
// table into the built version module. First, because phase 2 stamps
|
|
2313
|
+
// its entries with these versions and reads the same RSC out dir.
|
|
2314
|
+
// 2. PPR shell capture (producer B, #699): the shell prelude embeds built
|
|
2315
|
+
// client asset URLs (bootstrap entry), which do not exist at
|
|
2316
|
+
// buildStart. The kept temp server and the buildEnv were deferred AS A
|
|
2317
|
+
// PAIR in buildStart's finally; this finally is the pair's success-path
|
|
2318
|
+
// owner (buildEnd below owns the aborted-build path) — the phase itself
|
|
2319
|
+
// is a pure producer and tears down only the globals it installs.
|
|
2271
2320
|
buildApp: {
|
|
2272
2321
|
order: "post",
|
|
2273
2322
|
async handler(builder) {
|
|
2274
2323
|
try {
|
|
2275
|
-
await runShellPrerenderPhase(
|
|
2324
|
+
await runShellPrerenderPhase(
|
|
2325
|
+
s,
|
|
2326
|
+
builder as any,
|
|
2327
|
+
runRouterVersionsPhase(s, builder as any),
|
|
2328
|
+
);
|
|
2276
2329
|
} finally {
|
|
2277
2330
|
if (s.isBuildMode) {
|
|
2278
2331
|
const tempServer = s.shellPhaseTempServer;
|
|
@@ -2387,6 +2440,22 @@ export function createRouterDiscoveryPlugin(
|
|
|
2387
2440
|
// Record handler chunk metadata and RSC entry filename during RSC build.
|
|
2388
2441
|
// Used by closeBundle for handler code eviction and prerender data injection.
|
|
2389
2442
|
generateBundle(_options: any, bundle: any) {
|
|
2443
|
+
// Inputs of the per-router cache versions (discovery/build-versions.ts).
|
|
2444
|
+
// Each pass overwrites its slot: plugin-rsc runs the RSC and SSR builds
|
|
2445
|
+
// twice, and the real pass comes last.
|
|
2446
|
+
if (s.isBuildMode) {
|
|
2447
|
+
const envName = this.environment?.name;
|
|
2448
|
+
if (envName) {
|
|
2449
|
+
s.versionModuleFiles.set(envName, recordVersionModuleFiles(bundle));
|
|
2450
|
+
}
|
|
2451
|
+
if (envName === "rsc") {
|
|
2452
|
+
s.serverBuildGraph = recordServerGraph(this, bundle);
|
|
2453
|
+
} else if (envName === "client") {
|
|
2454
|
+
s.clientBuildGraph = recordClientGraph(this, bundle);
|
|
2455
|
+
} else if (envName === "ssr") {
|
|
2456
|
+
s.ssrBundle = recordBundleFiles(bundle);
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2390
2459
|
if (this.environment?.name !== "rsc") return;
|
|
2391
2460
|
const genStart = debugBuild ? performance.now() : 0;
|
|
2392
2461
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
import { gzipSync } from "node:zlib";
|
|
1
3
|
import type { ClientChunkMeta, ClientChunks } from "../plugin-types.js";
|
|
2
|
-
import { createRangoDebugger, NS } from "../debug.js";
|
|
4
|
+
import { createRangoDebugger, NS, type Debugger } from "../debug.js";
|
|
3
5
|
import { hashRefKey } from "../plugins/client-ref-hashing.js";
|
|
4
6
|
|
|
5
7
|
/** The callback shape @vitejs/plugin-rsc's `clientChunks` option accepts. */
|
|
@@ -97,6 +99,20 @@ const ROUTE_ROOT_DIRS = new Set([
|
|
|
97
99
|
"sections",
|
|
98
100
|
]);
|
|
99
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Markers that double as a conventional source root. `app/` is both a Next-style
|
|
104
|
+
* route root (`app/<segment>/…`) and the source root of many apps
|
|
105
|
+
* (`app/components`, `app/routes/<id>`). Keying on the segment after it put every
|
|
106
|
+
* route under `app/routes/` into one `app-routes` group, and a group is the
|
|
107
|
+
* loading unit, so rendering any one member downloaded every route's client code
|
|
108
|
+
* (#1022). A source-root marker therefore defers to a marker that IMMEDIATELY
|
|
109
|
+
* follows it when that inner marker has a route directory after it
|
|
110
|
+
* (`app/routes/<id>/…` -> `app-<id>`). Anything else after `app/` (including
|
|
111
|
+
* `app/components/`) is still the Next-style route id. Only these markers defer:
|
|
112
|
+
* `routes/view/<sub>/…` keeps `view` as the route id.
|
|
113
|
+
*/
|
|
114
|
+
const SOURCE_ROOT_DIRS = new Set(["app"]);
|
|
115
|
+
|
|
100
116
|
/**
|
|
101
117
|
* Built-in strategy used when `clientChunks: true` (also the default). Splits app
|
|
102
118
|
* client components by route/feature identity ONLY where it can recognize a route
|
|
@@ -116,8 +132,11 @@ const ROUTE_ROOT_DIRS = new Set([
|
|
|
116
132
|
* 1. Shared runtime (React / router / node_modules) -> `undefined` (never split).
|
|
117
133
|
* 2. A registered error/notFound fallback (`ctx.fallbackRefs`) -> `app-fallback`,
|
|
118
134
|
* regardless of location, so the error UI is decoupled from the happy path.
|
|
119
|
-
* 3.
|
|
120
|
-
* next segment (the route id), robust to any nesting depth.
|
|
135
|
+
* 3. The first {@link ROUTE_ROOT_DIRS} marker with a directory after it -> key on
|
|
136
|
+
* that next segment (the route id), robust to any nesting depth. A
|
|
137
|
+
* {@link SOURCE_ROOT_DIRS} marker (`app`) directly followed by another marker
|
|
138
|
+
* with a directory after it defers to that inner marker:
|
|
139
|
+
* `app/routes/<id>/…` -> `app-<id>`, while `app/<segment>/…` -> `app-<segment>`.
|
|
121
140
|
* 4. Otherwise `undefined` (inherit the default `serverChunk` grouping).
|
|
122
141
|
*/
|
|
123
142
|
export function directoryClientChunks(
|
|
@@ -140,17 +159,21 @@ export function directoryClientChunks(
|
|
|
140
159
|
}
|
|
141
160
|
const segments = meta.normalizedId.split("/").filter(Boolean);
|
|
142
161
|
const dirCount = segments.length - 1; // exclude the filename
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
162
|
+
// Route-root marker -> the segment after it is the route id. First marker wins,
|
|
163
|
+
// so a top-level route owns its whole subtree. The `< dirCount - 1` bound
|
|
164
|
+
// guarantees the segment after the marker is a directory, not the file.
|
|
165
|
+
const isMarkerAt = (i: number) =>
|
|
166
|
+
i < dirCount - 1 && ROUTE_ROOT_DIRS.has(segments[i].toLowerCase());
|
|
167
|
+
for (let i = 0; i < dirCount - 1; i++) {
|
|
168
|
+
if (!isMarkerAt(i)) continue;
|
|
169
|
+
// A source root (`app/`) yields to an inner marker right after it.
|
|
170
|
+
const marker =
|
|
171
|
+
SOURCE_ROOT_DIRS.has(segments[i].toLowerCase()) && isMarkerAt(i + 1)
|
|
172
|
+
? i + 1
|
|
173
|
+
: i;
|
|
174
|
+
const group = `app-${sanitizeGroup(segments[marker + 1])}`;
|
|
175
|
+
debugChunks?.("split %s -> %s", meta.normalizedId, group);
|
|
176
|
+
return group;
|
|
154
177
|
}
|
|
155
178
|
// No recognized route structure -> inherit the default serverChunk grouping.
|
|
156
179
|
// This is the actionable "silent" case: app code that did NOT split by route.
|
|
@@ -182,3 +205,50 @@ export function resolveClientChunks(
|
|
|
182
205
|
if (option === true) return (meta) => directoryClientChunks(meta, ctx);
|
|
183
206
|
return option;
|
|
184
207
|
}
|
|
208
|
+
|
|
209
|
+
/** @vitejs/plugin-rsc's client-reference map; its group modules sit under it. */
|
|
210
|
+
export const CLIENT_REFERENCES_MODULE_ID =
|
|
211
|
+
"\0virtual:vite-rsc/client-references";
|
|
212
|
+
|
|
213
|
+
/** Module-id prefix of the per-group virtual module @vitejs/plugin-rsc emits. */
|
|
214
|
+
const CLIENT_GROUP_PREFIX = `${CLIENT_REFERENCES_MODULE_ID}/group/`;
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Build-end group report under `DEBUG=rango:chunks`: one line per client
|
|
218
|
+
* reference group with its client-reference count and the size of the group's
|
|
219
|
+
* own chunk (code split into shared chunks such as `react`/`router` is not
|
|
220
|
+
* counted). A group is the loading unit (plugin-rsc imports the group's virtual
|
|
221
|
+
* module to resolve any one member), so a large group that an always-rendered
|
|
222
|
+
* component belongs to is downloaded on every route; this line makes that
|
|
223
|
+
* visible. Covers every group, including ones named by a custom `clientChunks`
|
|
224
|
+
* function or by plugin-rsc's default `serverChunk` grouping. `undefined` when
|
|
225
|
+
* the namespace is off, so a normal build does not register it. Group names are
|
|
226
|
+
* printed with NUL escaped: plugin-rsc's default group is named
|
|
227
|
+
* `facade:\0virtual:…`, and a raw NUL makes `grep` treat the output as binary
|
|
228
|
+
* and drop that line, usually the largest group. `log` is injectable for tests.
|
|
229
|
+
*/
|
|
230
|
+
export function clientChunksReport(
|
|
231
|
+
log: Debugger | undefined = debugChunks,
|
|
232
|
+
): Plugin | undefined {
|
|
233
|
+
if (!log) return undefined;
|
|
234
|
+
return {
|
|
235
|
+
name: "@rangojs/router:client-chunks-report",
|
|
236
|
+
apply: "build",
|
|
237
|
+
applyToEnvironment: (env) => env.name === "client",
|
|
238
|
+
generateBundle(_options, bundle) {
|
|
239
|
+
for (const chunk of Object.values(bundle)) {
|
|
240
|
+
if (chunk.type !== "chunk") continue;
|
|
241
|
+
const facade = chunk.facadeModuleId;
|
|
242
|
+
if (!facade?.startsWith(CLIENT_GROUP_PREFIX)) continue;
|
|
243
|
+
log(
|
|
244
|
+
"group %s: %d client reference(s), %d B (%d B gzip) -> %s",
|
|
245
|
+
facade.slice(CLIENT_GROUP_PREFIX.length).replaceAll("\0", "\\0"),
|
|
246
|
+
this.getModuleInfo(facade)?.importedIds.length ?? 0,
|
|
247
|
+
Buffer.byteLength(chunk.code),
|
|
248
|
+
gzipSync(chunk.code).length,
|
|
249
|
+
chunk.fileName,
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
};
|
|
254
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code-unit order, the same on every machine. Generated modules and the cache
|
|
3
|
+
* version inputs are sorted with it: `localeCompare` depends on the build
|
|
4
|
+
* machine's ICU data, and build output has to be byte-identical across machines
|
|
5
|
+
* (discovery/build-versions.ts hashes it).
|
|
6
|
+
*/
|
|
7
|
+
export function compareStrings(a: string, b: string): number {
|
|
8
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
9
|
+
}
|
|
@@ -72,11 +72,20 @@ export function getPackageAliases(): Record<string, string> {
|
|
|
72
72
|
return aliases;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* @vitejs/plugin-rsc puts these vendor specifiers in `optimizeDeps.include`,
|
|
77
|
+
* and Vite resolves them from the app root, where pnpm's strict layout does
|
|
78
|
+
* not link the plugin unless the app lists it (#1050). Aliased to the copy
|
|
79
|
+
* the router resolves, which therefore also wins over an app's own
|
|
80
|
+
* @vitejs/plugin-rsc. Must hold every vendor entry the plugin includes:
|
|
81
|
+
* optimize-deps-vendor-resolution.test.ts checks the resolved config.
|
|
82
|
+
*/
|
|
75
83
|
export function getVendorAliases(): Record<string, string> {
|
|
76
84
|
const specs = [
|
|
77
85
|
"@vitejs/plugin-rsc/vendor/react-server-dom/client.browser",
|
|
78
86
|
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
|
|
79
87
|
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge",
|
|
88
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/static.edge",
|
|
80
89
|
];
|
|
81
90
|
const aliases: Record<string, string> = {};
|
|
82
91
|
for (const spec of specs) {
|
|
@@ -199,8 +199,11 @@ export function resolvePrerenderError(
|
|
|
199
199
|
throw error;
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
+
/** Build scratch space, relative to the project root. Never shipped. */
|
|
203
|
+
export const RANGO_BUILD_DIR = "node_modules/.rangojs-router-build";
|
|
204
|
+
|
|
202
205
|
function getStagedAssetDir(projectRoot: string): string {
|
|
203
|
-
return resolve(projectRoot, "
|
|
206
|
+
return resolve(projectRoot, RANGO_BUILD_DIR, "rsc-assets");
|
|
204
207
|
}
|
|
205
208
|
|
|
206
209
|
export function resetStagedBuildAssets(projectRoot: string): void {
|
|
@@ -15,7 +15,7 @@ import type { HeadScriptsOption } from "../plugin-types.js";
|
|
|
15
15
|
|
|
16
16
|
// Cloudflare preset: @cloudflare/vite-plugin sets optimizeDeps.entries (string
|
|
17
17
|
// or array) on the rsc environment. Single source for both the discovery plugin
|
|
18
|
-
// and the
|
|
18
|
+
// and the entry bootstrap injector so they target the same entry.
|
|
19
19
|
export function resolveRscEntryFromConfig(
|
|
20
20
|
config: ResolvedConfig,
|
|
21
21
|
): string | undefined {
|