@rangojs/router 0.0.0-experimental.145 → 0.0.0-experimental.146
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 -40
- package/dist/vite/index.js +34 -9
- package/package.json +1 -1
- package/src/cache/cache-scope.ts +30 -1
- package/src/cache/handle-snapshot.ts +22 -1
- package/src/cache/shell-snapshot.ts +47 -0
- package/src/cache/types.ts +13 -0
- package/src/deps/ssr.ts +4 -1
- package/src/router/loader-resolution.ts +16 -0
- package/src/router/match-api.ts +9 -2
- package/src/router/match-handlers.ts +13 -0
- package/src/router/segment-resolution/mask-nested.ts +19 -3
- package/src/rsc/rsc-rendering.ts +54 -2
- package/src/rsc/shell-capture.ts +94 -4
- package/src/segment-system.tsx +49 -19
- package/src/server/request-context.ts +47 -0
- package/src/ssr/index.tsx +104 -13
- package/src/ssr/inject-rsc-eager.ts +2 -2
- package/src/ssr/preinit-client-references.ts +106 -0
- package/src/vite/index.ts +1 -0
- package/src/vite/plugin-types.ts +33 -0
- package/src/vite/plugins/virtual-entries.ts +37 -4
- package/src/vite/rango.ts +10 -2
- package/src/vite/utils/shared-utils.ts +4 -2
package/src/vite/plugin-types.ts
CHANGED
|
@@ -107,6 +107,11 @@ export type ClientChunks =
|
|
|
107
107
|
|
|
108
108
|
// -- Plugin options ---------------------------------------------------------
|
|
109
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Document script strategy. See {@link RangoBaseOptions.headScripts}.
|
|
112
|
+
*/
|
|
113
|
+
export type HeadScriptsOption = "preinit" | "preload";
|
|
114
|
+
|
|
110
115
|
/**
|
|
111
116
|
* Base options shared by all presets
|
|
112
117
|
*/
|
|
@@ -126,6 +131,34 @@ interface RangoBaseOptions {
|
|
|
126
131
|
*/
|
|
127
132
|
clientChunks?: ClientChunks;
|
|
128
133
|
|
|
134
|
+
/**
|
|
135
|
+
* How the document ships its JavaScript.
|
|
136
|
+
*
|
|
137
|
+
* - `"preinit"` (**default**): client-reference chunks render as EXECUTING
|
|
138
|
+
* `<script type="module" async>` tags hoisted into `<head>` (upgrading
|
|
139
|
+
* plugin-rsc's modulepreload hints in place), and the browser entry ships
|
|
140
|
+
* as Fizz `bootstrapModules` — a head `modulepreload fetchpriority=low`
|
|
141
|
+
* hint plus the executing end-of-shell `id="_R_"` module script. Chunk
|
|
142
|
+
* execution overlaps body streaming instead of waiting for the hydration
|
|
143
|
+
* import walk; under PPR everything lands in the stored shell prelude.
|
|
144
|
+
* - `"preload"`: the previous behavior — `<link rel="modulepreload">` hints
|
|
145
|
+
* only, entry as an inline `import()` script at end of shell. Chunks
|
|
146
|
+
* fetch+compile early but execute only when hydration imports them.
|
|
147
|
+
*
|
|
148
|
+
* Build-only for the chunk half: plugin-rsc resolves no JS deps per client
|
|
149
|
+
* reference in dev, so dev documents carry no head chunk scripts in either
|
|
150
|
+
* mode (the bootstrap conversion does apply in dev). Trades and upstream
|
|
151
|
+
* limits are documented in src/ssr/preinit-client-references.ts.
|
|
152
|
+
*
|
|
153
|
+
* Wired in the generated virtual SSR entry
|
|
154
|
+
* (`src/ssr/preinit-client-references.ts` has the mechanism); apps with a
|
|
155
|
+
* custom SSR entry choose per-handler via `SSRDependencies.headScripts` and
|
|
156
|
+
* `installClientReferencePreinit`.
|
|
157
|
+
*
|
|
158
|
+
* @default "preinit"
|
|
159
|
+
*/
|
|
160
|
+
headScripts?: HeadScriptsOption;
|
|
161
|
+
|
|
129
162
|
/**
|
|
130
163
|
* Filter which files route discovery scans, by glob. Paths are matched
|
|
131
164
|
* root-relative (e.g. `src/routes/**`). `include` restricts discovery to
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { HeadScriptsOption } from "../plugin-types.js";
|
|
2
|
+
|
|
1
3
|
export const VIRTUAL_ENTRY_BROWSER: string = `
|
|
2
4
|
import {
|
|
3
5
|
createFromReadableStream,
|
|
@@ -36,21 +38,49 @@ async function initializeApp() {
|
|
|
36
38
|
initializeApp().catch(console.error);
|
|
37
39
|
`.trim();
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Generate the virtual SSR entry. `headScripts` mirrors the rango() plugin
|
|
43
|
+
* option: "preinit" (default) installs the client-reference preinit hook and
|
|
44
|
+
* lets the SSR handlers convert the bootstrap to `bootstrapModules`;
|
|
45
|
+
* "preload" omits the hook and pins the handlers to the hint-only strategy.
|
|
46
|
+
*/
|
|
47
|
+
export function getVirtualEntrySSR(
|
|
48
|
+
headScripts: HeadScriptsOption = "preinit",
|
|
49
|
+
): string {
|
|
50
|
+
const preinit = headScripts !== "preload";
|
|
51
|
+
// The preload variant drops exactly three preinit-only lines, all built
|
|
52
|
+
// here so the template below stays a single unconditional shape.
|
|
53
|
+
const depsImportNames = preinit
|
|
54
|
+
? "createFromReadableStream,\n setOnClientReference,"
|
|
55
|
+
: "createFromReadableStream,";
|
|
56
|
+
const ssrImportNames = preinit ? "\n installClientReferencePreinit," : "";
|
|
57
|
+
const install = preinit
|
|
58
|
+
? `
|
|
59
|
+
// Upgrade client-reference modulepreload hints to executing module scripts in
|
|
60
|
+
// the document head, for every render pass (live SSR, shell capture, resume).
|
|
61
|
+
// See src/ssr/preinit-client-references.ts for the full rationale.
|
|
62
|
+
installClientReferencePreinit(setOnClientReference);
|
|
63
|
+
`
|
|
64
|
+
: "";
|
|
65
|
+
const hs = JSON.stringify(headScripts);
|
|
66
|
+
return `
|
|
67
|
+
import {
|
|
68
|
+
${depsImportNames}
|
|
69
|
+
} from "@rangojs/router/internal/deps/ssr";
|
|
41
70
|
import { renderToReadableStream, resume } from "react-dom/server.edge";
|
|
42
71
|
import { prerender } from "react-dom/static.edge";
|
|
43
72
|
import { injectRSCPayload } from "@rangojs/router/internal/deps/html-stream-server";
|
|
44
73
|
import {
|
|
45
74
|
createSSRHandler,
|
|
46
75
|
createShellCaptureHandler,
|
|
47
|
-
createShellResumeHandler
|
|
76
|
+
createShellResumeHandler,${ssrImportNames}
|
|
48
77
|
} from "@rangojs/router/ssr";
|
|
49
|
-
|
|
78
|
+
${install}
|
|
50
79
|
export const renderHTML = createSSRHandler({
|
|
51
80
|
createFromReadableStream,
|
|
52
81
|
renderToReadableStream,
|
|
53
82
|
injectRSCPayload,
|
|
83
|
+
headScripts: ${hs},
|
|
54
84
|
loadBootstrapScriptContent: () =>
|
|
55
85
|
import.meta.viteRsc.loadBootstrapScriptContent("index"),
|
|
56
86
|
});
|
|
@@ -61,6 +91,7 @@ export const captureShellHTML = createShellCaptureHandler({
|
|
|
61
91
|
injectRSCPayload,
|
|
62
92
|
prerender,
|
|
63
93
|
resume,
|
|
94
|
+
headScripts: ${hs},
|
|
64
95
|
loadBootstrapScriptContent: () =>
|
|
65
96
|
import.meta.viteRsc.loadBootstrapScriptContent("index"),
|
|
66
97
|
});
|
|
@@ -71,10 +102,12 @@ export const resumeShellHTML = createShellResumeHandler({
|
|
|
71
102
|
injectRSCPayload,
|
|
72
103
|
prerender,
|
|
73
104
|
resume,
|
|
105
|
+
headScripts: ${hs},
|
|
74
106
|
loadBootstrapScriptContent: () =>
|
|
75
107
|
import.meta.viteRsc.loadBootstrapScriptContent("index"),
|
|
76
108
|
});
|
|
77
109
|
`.trim();
|
|
110
|
+
}
|
|
78
111
|
|
|
79
112
|
/**
|
|
80
113
|
* Virtual modules an RSC entry must import at startup to register the data the
|
package/src/vite/rango.ts
CHANGED
|
@@ -239,7 +239,11 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
239
239
|
},
|
|
240
240
|
});
|
|
241
241
|
|
|
242
|
-
plugins.push(
|
|
242
|
+
plugins.push(
|
|
243
|
+
createVirtualEntriesPlugin(finalEntries, undefined, {
|
|
244
|
+
headScripts: resolvedOptions.headScripts,
|
|
245
|
+
}),
|
|
246
|
+
);
|
|
243
247
|
plugins.push(performanceTracksPlugin());
|
|
244
248
|
plugins.push(
|
|
245
249
|
rsc({
|
|
@@ -476,7 +480,11 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
476
480
|
},
|
|
477
481
|
});
|
|
478
482
|
|
|
479
|
-
plugins.push(
|
|
483
|
+
plugins.push(
|
|
484
|
+
createVirtualEntriesPlugin(finalEntries, routerRef, {
|
|
485
|
+
headScripts: resolvedOptions.headScripts,
|
|
486
|
+
}),
|
|
487
|
+
);
|
|
480
488
|
plugins.push(performanceTracksPlugin());
|
|
481
489
|
plugins.push(
|
|
482
490
|
rsc({
|
|
@@ -5,12 +5,13 @@ import { getPublishedPackageName } from "./package-resolution.js";
|
|
|
5
5
|
import { performanceTracksOptimizeDepsPlugin } from "../plugins/performance-tracks.js";
|
|
6
6
|
import {
|
|
7
7
|
VIRTUAL_ENTRY_BROWSER,
|
|
8
|
-
|
|
8
|
+
getVirtualEntrySSR,
|
|
9
9
|
getVirtualEntryRSC,
|
|
10
10
|
getVirtualEntryRSCHost,
|
|
11
11
|
getVirtualVersionContent,
|
|
12
12
|
VIRTUAL_IDS,
|
|
13
13
|
} from "../plugins/virtual-entries.js";
|
|
14
|
+
import type { HeadScriptsOption } from "../plugin-types.js";
|
|
14
15
|
|
|
15
16
|
// Cloudflare preset: @cloudflare/vite-plugin sets optimizeDeps.entries (string
|
|
16
17
|
// or array) on the rsc environment. Single source for both the discovery plugin
|
|
@@ -109,6 +110,7 @@ export function normalizeHostRouterEntry(
|
|
|
109
110
|
export function createVirtualEntriesPlugin(
|
|
110
111
|
entries: { client: string; ssr: string; rsc?: string },
|
|
111
112
|
routerPathRef?: { path?: string; kind?: "router" | "host" },
|
|
113
|
+
options?: { headScripts?: HeadScriptsOption },
|
|
112
114
|
): Plugin {
|
|
113
115
|
// Build virtual modules map based on which entries use virtual IDs
|
|
114
116
|
const virtualModules: Record<string, string> = {};
|
|
@@ -117,7 +119,7 @@ export function createVirtualEntriesPlugin(
|
|
|
117
119
|
virtualModules[VIRTUAL_IDS.browser] = VIRTUAL_ENTRY_BROWSER;
|
|
118
120
|
}
|
|
119
121
|
if (entries.ssr === VIRTUAL_IDS.ssr) {
|
|
120
|
-
virtualModules[VIRTUAL_IDS.ssr] =
|
|
122
|
+
virtualModules[VIRTUAL_IDS.ssr] = getVirtualEntrySSR(options?.headScripts);
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
// RSC entry is resolved lazily in load() because routerPath may be
|