@vitejs/plugin-rsc 0.5.13 → 0.5.15
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 +34 -0
- package/dist/core/ssr.js +1 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/{plugin-DSNqWPmA.js → plugin-DBWiu_Dx.js} +211 -105
- package/dist/plugin-V6VFxi_0.d.ts +193 -0
- package/dist/plugin.d.ts +3 -161
- package/dist/plugin.js +1 -1
- package/dist/ssr.d.ts +22 -1
- package/dist/ssr.js +28 -8
- package/dist/transforms/index.d.ts +1 -1
- package/package.json +13 -2
- package/types/index.d.ts +23 -12
- /package/dist/{index-CFOPl4Gi.d.ts → index-DJ0AhQ9B.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -245,6 +245,33 @@ ssrModule.renderHTML(...);
|
|
|
245
245
|
export function renderHTML(...) {}
|
|
246
246
|
```
|
|
247
247
|
|
|
248
|
+
#### `import.meta.viteRsc.import`
|
|
249
|
+
|
|
250
|
+
- Type: `<T>(specifier: string, options: { environment: string }) => Promise<T>`
|
|
251
|
+
|
|
252
|
+
A more ergonomic alternative to `loadModule`:
|
|
253
|
+
|
|
254
|
+
1. No manual `rollupOptions.input` config needed - entries are auto-discovered
|
|
255
|
+
2. Specifier matches the path in `typeof import(...)` type annotations
|
|
256
|
+
|
|
257
|
+
**Comparison:**
|
|
258
|
+
|
|
259
|
+
```ts
|
|
260
|
+
// Before (loadModule) - requires vite.config.ts:
|
|
261
|
+
// environments.ssr.build.rollupOptions.input = { index: './entry.ssr.tsx' }
|
|
262
|
+
import.meta.viteRsc.loadModule<typeof import('./entry.ssr.tsx')>('ssr', 'index')
|
|
263
|
+
|
|
264
|
+
// After (import) - no config needed, auto-discovered
|
|
265
|
+
import.meta.viteRsc.import<typeof import('./entry.ssr.tsx')>(
|
|
266
|
+
'./entry.ssr.tsx',
|
|
267
|
+
{ environment: 'ssr' },
|
|
268
|
+
)
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
During development, this works the same as `loadModule`, using the `__VITE_ENVIRONMENT_RUNNER_IMPORT__` function to import modules in the target environment.
|
|
272
|
+
|
|
273
|
+
During production build, the plugin auto-discovers these imports and emits them as entries in the target environment. A manifest file (`__vite_rsc_env_imports_manifest.js`) is generated to map module specifiers to their output filenames.
|
|
274
|
+
|
|
248
275
|
### Available on `rsc` environment
|
|
249
276
|
|
|
250
277
|
#### `import.meta.viteRsc.loadCss`
|
|
@@ -616,6 +643,13 @@ Note that while there are official npm packages [`server-only`](https://www.npmj
|
|
|
616
643
|
|
|
617
644
|
This build-time validation is enabled by default and can be disabled by setting `validateImports: false` in the plugin options.
|
|
618
645
|
|
|
646
|
+
## Architecture Documentation
|
|
647
|
+
|
|
648
|
+
For developers interested in the internal architecture:
|
|
649
|
+
|
|
650
|
+
- **[docs/architecture.md](docs/architecture.md)** - Build pipeline, data flow, and key components
|
|
651
|
+
- **[docs/bundler-comparison.md](docs/bundler-comparison.md)** - How different bundlers approach RSC
|
|
652
|
+
|
|
619
653
|
## Credits
|
|
620
654
|
|
|
621
655
|
This project builds on fundamental techniques and insights from pioneering Vite RSC implementations.
|
package/dist/core/ssr.js
CHANGED
|
@@ -9,10 +9,7 @@ function setRequireModule(options) {
|
|
|
9
9
|
const requireModule = memoize((id) => {
|
|
10
10
|
return options.load(removeReferenceCacheTag(id));
|
|
11
11
|
});
|
|
12
|
-
|
|
13
|
-
return requireModule(id);
|
|
14
|
-
};
|
|
15
|
-
globalThis.__vite_rsc_client_require__ = clientRequire;
|
|
12
|
+
globalThis.__vite_rsc_client_require__ = requireModule;
|
|
16
13
|
setInternalRequire();
|
|
17
14
|
}
|
|
18
15
|
function createServerConsumerManifest() {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import "./
|
|
2
|
-
import
|
|
1
|
+
import { c as getPluginApi, r as PluginApi, s as RscPluginOptions, u as vitePluginRsc } from "./plugin-V6VFxi_0.js";
|
|
2
|
+
import "./index-DJ0AhQ9B.js";
|
|
3
3
|
export { type PluginApi, type RscPluginOptions, vitePluginRsc as default, getPluginApi };
|
package/dist/index.js
CHANGED
|
@@ -155,65 +155,6 @@ async function findSourceMapURL(server, filename, environmentName) {
|
|
|
155
155
|
};
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
//#endregion
|
|
159
|
-
//#region src/plugins/resolved-id-proxy.ts
|
|
160
|
-
const RESOLVED_ID_PROXY_PREFIX = "virtual:vite-rsc/resolved-id/";
|
|
161
|
-
function toResolvedIdProxy(resolvedId) {
|
|
162
|
-
return RESOLVED_ID_PROXY_PREFIX + encodeURIComponent(resolvedId);
|
|
163
|
-
}
|
|
164
|
-
function withResolvedIdProxy(resolvedId) {
|
|
165
|
-
return resolvedId.startsWith("\0") ? toResolvedIdProxy(resolvedId) : resolvedId;
|
|
166
|
-
}
|
|
167
|
-
function fromResolvedIdProxy(source) {
|
|
168
|
-
if (!source.startsWith(RESOLVED_ID_PROXY_PREFIX)) return;
|
|
169
|
-
const clean = source.split("?")[0];
|
|
170
|
-
return decodeURIComponent(clean.slice(29));
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Vite plugin that resolves proxy import specifiers to the original resolved IDs.
|
|
174
|
-
*/
|
|
175
|
-
function vitePluginResolvedIdProxy() {
|
|
176
|
-
return {
|
|
177
|
-
name: "rsc:resolved-id-proxy",
|
|
178
|
-
resolveId: { handler(source) {
|
|
179
|
-
const originalId = fromResolvedIdProxy(source);
|
|
180
|
-
if (originalId !== void 0) return originalId;
|
|
181
|
-
} }
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
//#endregion
|
|
186
|
-
//#region src/plugins/scan.ts
|
|
187
|
-
function scanBuildStripPlugin({ manager }) {
|
|
188
|
-
return {
|
|
189
|
-
name: "rsc:scan-strip",
|
|
190
|
-
apply: "build",
|
|
191
|
-
enforce: "post",
|
|
192
|
-
async transform(code, _id, _options) {
|
|
193
|
-
if (!manager.isScanBuild) return;
|
|
194
|
-
return {
|
|
195
|
-
code: await transformScanBuildStrip(code),
|
|
196
|
-
map: { mappings: "" }
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
const importGlobRE = /\bimport\.meta\.glob(?:<\w+>)?\s*\(/g;
|
|
202
|
-
async function transformScanBuildStrip(code) {
|
|
203
|
-
const [imports] = esModuleLexer.parse(code);
|
|
204
|
-
let output = imports.map((e) => e.n && `import ${JSON.stringify(e.n)};\n`).filter(Boolean).join("");
|
|
205
|
-
if (importGlobRE.test(code)) {
|
|
206
|
-
walk(await parseAstAsync(code), { enter(node) {
|
|
207
|
-
if (node.type === "CallExpression" && node.callee.type === "MemberExpression" && node.callee.object.type === "MetaProperty" && node.callee.object.meta.type === "Identifier" && node.callee.object.meta.name === "import" && node.callee.object.property.type === "Identifier" && node.callee.object.property.name === "meta" && node.callee.property.type === "Identifier" && node.callee.property.name === "glob") {
|
|
208
|
-
const importMetaGlob = code.slice(node.start, node.end);
|
|
209
|
-
output += `console.log(${importMetaGlob});\n`;
|
|
210
|
-
}
|
|
211
|
-
} });
|
|
212
|
-
output += "";
|
|
213
|
-
}
|
|
214
|
-
return output;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
158
|
//#endregion
|
|
218
159
|
//#region src/plugins/utils.ts
|
|
219
160
|
function sortObject(o) {
|
|
@@ -284,6 +225,183 @@ function getFetchHandlerExport(exports) {
|
|
|
284
225
|
throw new Error("Invalid server handler entry");
|
|
285
226
|
}
|
|
286
227
|
|
|
228
|
+
//#endregion
|
|
229
|
+
//#region src/plugins/import-environment.ts
|
|
230
|
+
const ENV_IMPORTS_MANIFEST_NAME = "__vite_rsc_env_imports_manifest.js";
|
|
231
|
+
const ENV_IMPORTS_MANIFEST_PLACEHOLDER = "virtual:vite-rsc/env-imports-manifest";
|
|
232
|
+
const ENV_IMPORTS_ENTRY_FALLBACK = "virtual:vite-rsc/env-imports-entry-fallback";
|
|
233
|
+
function ensureEnvironmentImportsEntryFallback({ environments }) {
|
|
234
|
+
for (const [name, config] of Object.entries(environments)) {
|
|
235
|
+
if (name === "client") continue;
|
|
236
|
+
const input = normalizeRollupOpitonsInput(config.build?.rollupOptions?.input);
|
|
237
|
+
if (Object.keys(input).length === 0) {
|
|
238
|
+
config.build = config.build || {};
|
|
239
|
+
config.build.rollupOptions = config.build.rollupOptions || {};
|
|
240
|
+
config.build.rollupOptions.input = { __vite_rsc_env_imports_entry_fallback: ENV_IMPORTS_ENTRY_FALLBACK };
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function vitePluginImportEnvironment(manager) {
|
|
245
|
+
return [{
|
|
246
|
+
name: "rsc:import-environment",
|
|
247
|
+
resolveId(source) {
|
|
248
|
+
if (source === ENV_IMPORTS_MANIFEST_PLACEHOLDER) return {
|
|
249
|
+
id: ENV_IMPORTS_MANIFEST_PLACEHOLDER,
|
|
250
|
+
external: true
|
|
251
|
+
};
|
|
252
|
+
},
|
|
253
|
+
buildStart() {
|
|
254
|
+
if (this.environment.mode !== "build") return;
|
|
255
|
+
const emitted = /* @__PURE__ */ new Set();
|
|
256
|
+
for (const byTargetEnv of Object.values(manager.environmentImportMetaMap)) {
|
|
257
|
+
const imports = byTargetEnv[this.environment.name];
|
|
258
|
+
if (!imports) continue;
|
|
259
|
+
for (const meta of Object.values(imports)) if (!emitted.has(meta.resolvedId)) {
|
|
260
|
+
emitted.add(meta.resolvedId);
|
|
261
|
+
this.emitFile({
|
|
262
|
+
type: "chunk",
|
|
263
|
+
id: meta.resolvedId
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
transform: { async handler(code, id) {
|
|
269
|
+
if (!code.includes("import.meta.viteRsc.import")) return;
|
|
270
|
+
const { server } = manager;
|
|
271
|
+
const s = new MagicString(code);
|
|
272
|
+
for (const match of stripLiteral(code).matchAll(/import\.meta\.viteRsc\.import\s*(<[\s\S]*?>)?\s*\(([\s\S]*?)\)/dg)) {
|
|
273
|
+
const [argStart, argEnd] = match.indices[2];
|
|
274
|
+
const [specifier, options] = evalValue(`[${code.slice(argStart, argEnd).trim()}]`);
|
|
275
|
+
const environmentName = options.environment;
|
|
276
|
+
let resolvedId;
|
|
277
|
+
if (this.environment.mode === "dev") {
|
|
278
|
+
const targetEnv$1 = server.environments[environmentName];
|
|
279
|
+
assert(targetEnv$1, `[vite-rsc] unknown environment '${environmentName}'`);
|
|
280
|
+
const resolved = await targetEnv$1.pluginContainer.resolveId(specifier, id);
|
|
281
|
+
assert(resolved, `[vite-rsc] failed to resolve '${specifier}' in environment '${environmentName}'`);
|
|
282
|
+
resolvedId = resolved.id;
|
|
283
|
+
} else {
|
|
284
|
+
const targetEnvConfig = manager.config.environments[environmentName];
|
|
285
|
+
assert(targetEnvConfig, `[vite-rsc] unknown environment '${environmentName}'`);
|
|
286
|
+
const resolved = await this.resolve(specifier, id);
|
|
287
|
+
assert(resolved, `[vite-rsc] failed to resolve '${specifier}' in environment '${environmentName}'`);
|
|
288
|
+
resolvedId = resolved.id;
|
|
289
|
+
}
|
|
290
|
+
const sourceEnv = this.environment.name;
|
|
291
|
+
const targetEnv = environmentName;
|
|
292
|
+
manager.environmentImportMetaMap[sourceEnv] ??= {};
|
|
293
|
+
manager.environmentImportMetaMap[sourceEnv][targetEnv] ??= {};
|
|
294
|
+
manager.environmentImportMetaMap[sourceEnv][targetEnv][resolvedId] = {
|
|
295
|
+
resolvedId,
|
|
296
|
+
targetEnv,
|
|
297
|
+
sourceEnv,
|
|
298
|
+
specifier
|
|
299
|
+
};
|
|
300
|
+
let replacement;
|
|
301
|
+
if (this.environment.mode === "dev") replacement = `globalThis.__VITE_ENVIRONMENT_RUNNER_IMPORT__(${JSON.stringify(environmentName)}, ${JSON.stringify(resolvedId)})`;
|
|
302
|
+
else {
|
|
303
|
+
const relativeId = manager.toRelativeId(resolvedId);
|
|
304
|
+
replacement = `(await import(${JSON.stringify(ENV_IMPORTS_MANIFEST_PLACEHOLDER)})).default[${JSON.stringify(relativeId)}]()`;
|
|
305
|
+
}
|
|
306
|
+
const [start, end] = match.indices[0];
|
|
307
|
+
s.overwrite(start, end, replacement);
|
|
308
|
+
}
|
|
309
|
+
if (s.hasChanged()) return {
|
|
310
|
+
code: s.toString(),
|
|
311
|
+
map: s.generateMap({ hires: "boundary" })
|
|
312
|
+
};
|
|
313
|
+
} },
|
|
314
|
+
renderChunk(code, chunk) {
|
|
315
|
+
if (code.includes(ENV_IMPORTS_MANIFEST_PLACEHOLDER)) {
|
|
316
|
+
const replacement = normalizeRelativePath(path.relative(path.join(chunk.fileName, ".."), ENV_IMPORTS_MANIFEST_NAME));
|
|
317
|
+
code = code.replaceAll(ENV_IMPORTS_MANIFEST_PLACEHOLDER, () => replacement);
|
|
318
|
+
return { code };
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}, createVirtualPlugin(ENV_IMPORTS_ENTRY_FALLBACK.slice(8), () => {
|
|
322
|
+
return `export default "__vite_rsc_env_imports_entry_fallback";`;
|
|
323
|
+
})];
|
|
324
|
+
}
|
|
325
|
+
function writeEnvironmentImportsManifest(manager) {
|
|
326
|
+
if (Object.keys(manager.environmentImportMetaMap).length === 0) return;
|
|
327
|
+
for (const [sourceEnv, byTargetEnv] of Object.entries(manager.environmentImportMetaMap)) {
|
|
328
|
+
const sourceOutDir = manager.config.environments[sourceEnv].build.outDir;
|
|
329
|
+
const manifestPath = path.join(sourceOutDir, ENV_IMPORTS_MANIFEST_NAME);
|
|
330
|
+
let code = "export default {\n";
|
|
331
|
+
for (const [_targetEnv, imports] of Object.entries(byTargetEnv)) for (const [resolvedId, meta] of Object.entries(imports)) {
|
|
332
|
+
const bundle = manager.bundles[meta.targetEnv];
|
|
333
|
+
if (!bundle) throw new Error(`[vite-rsc] missing bundle for environment import: ${meta.targetEnv}`);
|
|
334
|
+
const chunk = Object.values(bundle).find((c) => c.type === "chunk" && c.facadeModuleId === resolvedId);
|
|
335
|
+
if (!chunk) throw new Error(`[vite-rsc] missing output for environment import: ${resolvedId}`);
|
|
336
|
+
const targetOutDir = manager.config.environments[meta.targetEnv].build.outDir;
|
|
337
|
+
const relativePath = normalizeRelativePath(path.relative(sourceOutDir, path.join(targetOutDir, chunk.fileName)));
|
|
338
|
+
const relativeId = manager.toRelativeId(resolvedId);
|
|
339
|
+
code += ` ${JSON.stringify(relativeId)}: () => import(${JSON.stringify(relativePath)}),\n`;
|
|
340
|
+
}
|
|
341
|
+
code += "}\n";
|
|
342
|
+
fs.writeFileSync(manifestPath, code);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
//#endregion
|
|
347
|
+
//#region src/plugins/resolved-id-proxy.ts
|
|
348
|
+
const RESOLVED_ID_PROXY_PREFIX = "virtual:vite-rsc/resolved-id/";
|
|
349
|
+
function toResolvedIdProxy(resolvedId) {
|
|
350
|
+
return RESOLVED_ID_PROXY_PREFIX + encodeURIComponent(resolvedId);
|
|
351
|
+
}
|
|
352
|
+
function withResolvedIdProxy(resolvedId) {
|
|
353
|
+
return resolvedId.startsWith("\0") ? toResolvedIdProxy(resolvedId) : resolvedId;
|
|
354
|
+
}
|
|
355
|
+
function fromResolvedIdProxy(source) {
|
|
356
|
+
if (!source.startsWith(RESOLVED_ID_PROXY_PREFIX)) return;
|
|
357
|
+
const clean = source.split("?")[0];
|
|
358
|
+
return decodeURIComponent(clean.slice(29));
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Vite plugin that resolves proxy import specifiers to the original resolved IDs.
|
|
362
|
+
*/
|
|
363
|
+
function vitePluginResolvedIdProxy() {
|
|
364
|
+
return {
|
|
365
|
+
name: "rsc:resolved-id-proxy",
|
|
366
|
+
resolveId: { handler(source) {
|
|
367
|
+
const originalId = fromResolvedIdProxy(source);
|
|
368
|
+
if (originalId !== void 0) return originalId;
|
|
369
|
+
} }
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
//#endregion
|
|
374
|
+
//#region src/plugins/scan.ts
|
|
375
|
+
function scanBuildStripPlugin({ manager }) {
|
|
376
|
+
return {
|
|
377
|
+
name: "rsc:scan-strip",
|
|
378
|
+
apply: "build",
|
|
379
|
+
enforce: "post",
|
|
380
|
+
async transform(code, _id, _options) {
|
|
381
|
+
if (!manager.isScanBuild) return;
|
|
382
|
+
return {
|
|
383
|
+
code: await transformScanBuildStrip(code),
|
|
384
|
+
map: { mappings: "" }
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
const importGlobRE = /\bimport\.meta\.glob(?:<\w+>)?\s*\(/g;
|
|
390
|
+
async function transformScanBuildStrip(code) {
|
|
391
|
+
const [imports] = esModuleLexer.parse(code);
|
|
392
|
+
let output = imports.map((e) => e.n && `import ${JSON.stringify(e.n)};\n`).filter(Boolean).join("");
|
|
393
|
+
if (importGlobRE.test(code)) {
|
|
394
|
+
walk(await parseAstAsync(code), { enter(node) {
|
|
395
|
+
if (node.type === "CallExpression" && node.callee.type === "MemberExpression" && node.callee.object.type === "MetaProperty" && node.callee.object.meta.type === "Identifier" && node.callee.object.meta.name === "import" && node.callee.object.property.type === "Identifier" && node.callee.object.property.name === "meta" && node.callee.property.type === "Identifier" && node.callee.property.name === "glob") {
|
|
396
|
+
const importMetaGlob = code.slice(node.start, node.end);
|
|
397
|
+
output += `console.log(${importMetaGlob});\n`;
|
|
398
|
+
}
|
|
399
|
+
} });
|
|
400
|
+
output += "";
|
|
401
|
+
}
|
|
402
|
+
return output;
|
|
403
|
+
}
|
|
404
|
+
|
|
287
405
|
//#endregion
|
|
288
406
|
//#region src/plugins/validate-import.ts
|
|
289
407
|
function validateImportPlugin() {
|
|
@@ -380,13 +498,14 @@ function resolvePackage(name) {
|
|
|
380
498
|
var RscPluginManager = class {
|
|
381
499
|
server;
|
|
382
500
|
config;
|
|
383
|
-
|
|
501
|
+
bundles = {};
|
|
384
502
|
buildAssetsManifest;
|
|
385
503
|
isScanBuild = false;
|
|
386
504
|
clientReferenceMetaMap = {};
|
|
387
505
|
clientReferenceGroups = {};
|
|
388
506
|
serverReferenceMetaMap = {};
|
|
389
507
|
serverResourcesMetaMap = {};
|
|
508
|
+
environmentImportMetaMap = {};
|
|
390
509
|
stabilize() {
|
|
391
510
|
this.clientReferenceMetaMap = sortObject(this.clientReferenceMetaMap);
|
|
392
511
|
this.serverResourcesMetaMap = sortObject(this.serverResourcesMetaMap);
|
|
@@ -401,6 +520,9 @@ var RscPluginManager = class {
|
|
|
401
520
|
fs.writeFileSync(manifestPath, assetsManifestCode);
|
|
402
521
|
}
|
|
403
522
|
}
|
|
523
|
+
writeEnvironmentImportsManifest() {
|
|
524
|
+
writeEnvironmentImportsManifest(this);
|
|
525
|
+
}
|
|
404
526
|
};
|
|
405
527
|
/** @experimental */
|
|
406
528
|
function getPluginApi(config) {
|
|
@@ -465,29 +587,11 @@ function vitePluginRsc(rscPluginOptions = {}) {
|
|
|
465
587
|
const logStep = (msg) => {
|
|
466
588
|
builder.config.logger.info(colors.blue(msg));
|
|
467
589
|
};
|
|
468
|
-
if (!builder.environments.ssr?.config.build.rollupOptions.input) {
|
|
469
|
-
manager.isScanBuild = true;
|
|
470
|
-
builder.environments.rsc.config.build.write = false;
|
|
471
|
-
builder.environments.client.config.build.write = false;
|
|
472
|
-
logStep("[1/4] analyze client references...");
|
|
473
|
-
await builder.build(builder.environments.rsc);
|
|
474
|
-
logStep("[2/4] analyze server references...");
|
|
475
|
-
await builder.build(builder.environments.client);
|
|
476
|
-
manager.isScanBuild = false;
|
|
477
|
-
builder.environments.rsc.config.build.write = true;
|
|
478
|
-
builder.environments.client.config.build.write = true;
|
|
479
|
-
logStep("[3/4] build rsc environment...");
|
|
480
|
-
await builder.build(builder.environments.rsc);
|
|
481
|
-
manager.stabilize();
|
|
482
|
-
logStep("[4/4] build client environment...");
|
|
483
|
-
await builder.build(builder.environments.client);
|
|
484
|
-
manager.writeAssetsManifest(["rsc"]);
|
|
485
|
-
return;
|
|
486
|
-
}
|
|
487
590
|
const rscOutDir = builder.environments.rsc.config.build.outDir;
|
|
488
591
|
const ssrOutDir = builder.environments.ssr.config.build.outDir;
|
|
489
592
|
const rscInsideSsr = path.normalize(rscOutDir).startsWith(path.normalize(ssrOutDir) + path.sep);
|
|
490
593
|
const tempRscOutDir = path.join(builder.config.root, "node_modules", ".vite-rsc-temp", "rsc");
|
|
594
|
+
ensureEnvironmentImportsEntryFallback(builder.config);
|
|
491
595
|
manager.isScanBuild = true;
|
|
492
596
|
builder.environments.rsc.config.build.write = false;
|
|
493
597
|
builder.environments.ssr.config.build.write = false;
|
|
@@ -516,18 +620,10 @@ function vitePluginRsc(rscPluginOptions = {}) {
|
|
|
516
620
|
fs.renameSync(tempRscOutDir, rscOutDir);
|
|
517
621
|
}
|
|
518
622
|
manager.writeAssetsManifest(["ssr", "rsc"]);
|
|
623
|
+
manager.writeEnvironmentImportsManifest();
|
|
519
624
|
};
|
|
520
625
|
let hasReactServerDomWebpack = false;
|
|
521
626
|
return [
|
|
522
|
-
{
|
|
523
|
-
name: "rsc:builder-api",
|
|
524
|
-
buildApp: {
|
|
525
|
-
order: "pre",
|
|
526
|
-
async handler(builder) {
|
|
527
|
-
builder.rsc = { manager };
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
},
|
|
531
627
|
{
|
|
532
628
|
name: "rsc",
|
|
533
629
|
async config(config, env) {
|
|
@@ -883,18 +979,19 @@ export function createRpcClient(params) {
|
|
|
883
979
|
assert(this.environment.mode === "dev");
|
|
884
980
|
const manifest = {
|
|
885
981
|
bootstrapScriptContent: `import(${serializeValueWithRuntime(assetsURL("@id/__x00__" + VIRTUAL_ENTRIES.browser, manager))})`,
|
|
886
|
-
clientReferenceDeps: {}
|
|
982
|
+
clientReferenceDeps: {},
|
|
983
|
+
cssLinkPrecedence: rscPluginOptions.cssLinkPrecedence
|
|
887
984
|
};
|
|
888
985
|
return `export default ${JSON.stringify(manifest, null, 2)}`;
|
|
889
986
|
}
|
|
890
987
|
},
|
|
891
988
|
generateBundle(_options, bundle) {
|
|
892
|
-
|
|
989
|
+
manager.bundles[this.environment.name] = bundle;
|
|
893
990
|
if (this.environment.name === "client") {
|
|
894
991
|
const filterAssets = rscPluginOptions.copyServerAssetsToClient ?? (() => true);
|
|
895
992
|
const rscBuildOptions = manager.config.environments.rsc.build;
|
|
896
993
|
const rscViteManifest = typeof rscBuildOptions.manifest === "string" ? rscBuildOptions.manifest : rscBuildOptions.manifest && ".vite/manifest.json";
|
|
897
|
-
for (const asset of Object.values(manager.
|
|
994
|
+
for (const asset of Object.values(manager.bundles["rsc"])) {
|
|
898
995
|
if (asset.fileName === rscViteManifest) continue;
|
|
899
996
|
if (asset.type === "asset" && filterAssets(asset.fileName)) this.emitFile({
|
|
900
997
|
type: "asset",
|
|
@@ -903,30 +1000,35 @@ export function createRpcClient(params) {
|
|
|
903
1000
|
});
|
|
904
1001
|
}
|
|
905
1002
|
const serverResources = {};
|
|
906
|
-
const rscAssetDeps = collectAssetDeps(manager.
|
|
1003
|
+
const rscAssetDeps = collectAssetDeps(manager.bundles["rsc"]);
|
|
907
1004
|
for (const [id, meta] of Object.entries(manager.serverResourcesMetaMap)) serverResources[meta.key] = assetsURLOfDeps({
|
|
908
1005
|
js: [],
|
|
909
1006
|
css: rscAssetDeps[id]?.deps.css ?? []
|
|
910
1007
|
}, manager);
|
|
911
1008
|
const assetDeps = collectAssetDeps(bundle);
|
|
912
|
-
|
|
913
|
-
assert(entry);
|
|
914
|
-
const entryUrl = assetsURL(entry.chunk.fileName, manager);
|
|
1009
|
+
let bootstrapScriptContent = "";
|
|
915
1010
|
const clientReferenceDeps = {};
|
|
916
1011
|
for (const meta of Object.values(manager.clientReferenceMetaMap)) {
|
|
917
1012
|
const deps = assetDeps[meta.groupChunkId]?.deps ?? {
|
|
918
1013
|
js: [],
|
|
919
1014
|
css: []
|
|
920
1015
|
};
|
|
921
|
-
clientReferenceDeps[meta.referenceKey] = assetsURLOfDeps(
|
|
1016
|
+
clientReferenceDeps[meta.referenceKey] = assetsURLOfDeps(deps, manager);
|
|
1017
|
+
}
|
|
1018
|
+
if (!rscPluginOptions.customClientEntry) {
|
|
1019
|
+
const entry = Object.values(assetDeps).find((v) => v.chunk.name === "index" && v.chunk.isEntry);
|
|
1020
|
+
if (!entry) throw new Error(`[vite-rsc] Client build must have an entry chunk named "index". Use 'customClientEntry' option to disable this requirement.`);
|
|
1021
|
+
const entryDeps = assetsURLOfDeps(entry.deps, manager);
|
|
1022
|
+
for (const [key, deps] of Object.entries(clientReferenceDeps)) clientReferenceDeps[key] = mergeAssetDeps(deps, entryDeps);
|
|
1023
|
+
const entryUrl = assetsURL(entry.chunk.fileName, manager);
|
|
1024
|
+
if (typeof entryUrl === "string") bootstrapScriptContent = `import(${JSON.stringify(entryUrl)})`;
|
|
1025
|
+
else bootstrapScriptContent = new RuntimeAsset(`"import(" + JSON.stringify(${entryUrl.runtime}) + ")"`);
|
|
922
1026
|
}
|
|
923
|
-
let bootstrapScriptContent;
|
|
924
|
-
if (typeof entryUrl === "string") bootstrapScriptContent = `import(${JSON.stringify(entryUrl)})`;
|
|
925
|
-
else bootstrapScriptContent = new RuntimeAsset(`"import(" + JSON.stringify(${entryUrl.runtime}) + ")"`);
|
|
926
1027
|
manager.buildAssetsManifest = {
|
|
927
1028
|
bootstrapScriptContent,
|
|
928
1029
|
clientReferenceDeps,
|
|
929
|
-
serverResources
|
|
1030
|
+
serverResources,
|
|
1031
|
+
cssLinkPrecedence: rscPluginOptions.cssLinkPrecedence
|
|
930
1032
|
};
|
|
931
1033
|
}
|
|
932
1034
|
},
|
|
@@ -950,6 +1052,7 @@ export default assetsManifest.bootstrapScriptContent;
|
|
|
950
1052
|
name: "rsc:bootstrap-script-content",
|
|
951
1053
|
async transform(code) {
|
|
952
1054
|
if (!code.includes("loadBootstrapScriptContent") || !/import\s*\.\s*meta\s*\.\s*viteRsc\s*\.\s*loadBootstrapScriptContent/.test(code)) return;
|
|
1055
|
+
assert(!rscPluginOptions.customClientEntry, `[vite-rsc] 'import.meta.viteRsc.loadBootstrapScriptContent' cannot be used with 'customClientEntry' option`);
|
|
953
1056
|
assert(this.environment.name !== "client");
|
|
954
1057
|
const output = new MagicString(code);
|
|
955
1058
|
for (const match of stripLiteral(code).matchAll(/import\s*\.\s*meta\s*\.\s*viteRsc\s*\.\s*loadBootstrapScriptContent\(([\s\S]*?)\)/dg)) {
|
|
@@ -1006,6 +1109,7 @@ import.meta.hot.on("rsc:update", () => {
|
|
|
1006
1109
|
return code;
|
|
1007
1110
|
}),
|
|
1008
1111
|
...vitePluginRscMinimal(rscPluginOptions, manager),
|
|
1112
|
+
...vitePluginImportEnvironment(manager),
|
|
1009
1113
|
...vitePluginFindSourceMapURL(),
|
|
1010
1114
|
...vitePluginRscCss(rscPluginOptions, manager),
|
|
1011
1115
|
{
|
|
@@ -1670,13 +1774,13 @@ function vitePluginRscCss(rscCssOptions = {}, manager) {
|
|
|
1670
1774
|
return generateResourcesCode(serializeValueWithRuntime(assetsURLOfDeps({
|
|
1671
1775
|
css: result.hrefs.map((href) => href.slice(1)),
|
|
1672
1776
|
js: []
|
|
1673
|
-
}, manager)), manager);
|
|
1777
|
+
}, manager)), manager, { cssLinkPrecedence: rscCssOptions.cssLinkPrecedence });
|
|
1674
1778
|
} else {
|
|
1675
1779
|
const key = manager.toRelativeId(importer);
|
|
1676
1780
|
manager.serverResourcesMetaMap[importer] = { key };
|
|
1677
1781
|
return `
|
|
1678
1782
|
import __vite_rsc_assets_manifest__ from "virtual:vite-rsc/assets-manifest";
|
|
1679
|
-
${generateResourcesCode(`__vite_rsc_assets_manifest__.serverResources[${JSON.stringify(key)}]`, manager)}
|
|
1783
|
+
${generateResourcesCode(`__vite_rsc_assets_manifest__.serverResources[${JSON.stringify(key)}]`, manager, { cssLinkPrecedence: rscCssOptions.cssLinkPrecedence })}
|
|
1680
1784
|
`;
|
|
1681
1785
|
}
|
|
1682
1786
|
}
|
|
@@ -1702,13 +1806,14 @@ export default function RemoveDuplicateServerCss() {
|
|
|
1702
1806
|
})
|
|
1703
1807
|
];
|
|
1704
1808
|
}
|
|
1705
|
-
function generateResourcesCode(depsCode, manager) {
|
|
1706
|
-
const
|
|
1809
|
+
function generateResourcesCode(depsCode, manager, options = {}) {
|
|
1810
|
+
const usePrecedence = options.cssLinkPrecedence !== false;
|
|
1811
|
+
const ResourcesFn = (React, deps, RemoveDuplicateServerCss, precedence) => {
|
|
1707
1812
|
return function Resources() {
|
|
1708
1813
|
return React.createElement(React.Fragment, null, [...deps.css.map((href) => React.createElement("link", {
|
|
1709
1814
|
key: "css:" + href,
|
|
1710
1815
|
rel: "stylesheet",
|
|
1711
|
-
precedence:
|
|
1816
|
+
...precedence ? { precedence } : {},
|
|
1712
1817
|
href,
|
|
1713
1818
|
"data-rsc-css-href": href
|
|
1714
1819
|
})), RemoveDuplicateServerCss && React.createElement(RemoveDuplicateServerCss, { key: "remove-duplicate-css" })]);
|
|
@@ -1723,6 +1828,7 @@ export const Resources = (${ResourcesFn.toString()})(
|
|
|
1723
1828
|
__vite_rsc_react__,
|
|
1724
1829
|
${depsCode},
|
|
1725
1830
|
RemoveDuplicateServerCss,
|
|
1831
|
+
${usePrecedence ? `"vite-rsc/importer-resources"` : `undefined`},
|
|
1726
1832
|
);
|
|
1727
1833
|
`;
|
|
1728
1834
|
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { s as TransformWrapExportFilter } from "./index-DJ0AhQ9B.js";
|
|
2
|
+
import MagicString from "magic-string";
|
|
3
|
+
import { Plugin, ResolvedConfig, Rollup, ViteDevServer, parseAstAsync } from "vite";
|
|
4
|
+
|
|
5
|
+
//#region src/plugins/import-environment.d.ts
|
|
6
|
+
type EnvironmentImportMeta = {
|
|
7
|
+
resolvedId: string;
|
|
8
|
+
targetEnv: string;
|
|
9
|
+
sourceEnv: string;
|
|
10
|
+
specifier: string;
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/plugin.d.ts
|
|
14
|
+
type ClientReferenceMeta = {
|
|
15
|
+
importId: string;
|
|
16
|
+
referenceKey: string;
|
|
17
|
+
packageSource?: string;
|
|
18
|
+
exportNames: string[];
|
|
19
|
+
renderedExports: string[];
|
|
20
|
+
serverChunk?: string;
|
|
21
|
+
groupChunkId?: string;
|
|
22
|
+
};
|
|
23
|
+
type ServerRerferenceMeta = {
|
|
24
|
+
importId: string;
|
|
25
|
+
referenceKey: string;
|
|
26
|
+
exportNames: string[];
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* @experimental
|
|
30
|
+
*/
|
|
31
|
+
declare class RscPluginManager {
|
|
32
|
+
server: ViteDevServer;
|
|
33
|
+
config: ResolvedConfig;
|
|
34
|
+
bundles: Record<string, Rollup.OutputBundle>;
|
|
35
|
+
buildAssetsManifest: AssetsManifest | undefined;
|
|
36
|
+
isScanBuild: boolean;
|
|
37
|
+
clientReferenceMetaMap: Record<string, ClientReferenceMeta>;
|
|
38
|
+
clientReferenceGroups: Record<string, ClientReferenceMeta[]>;
|
|
39
|
+
serverReferenceMetaMap: Record<string, ServerRerferenceMeta>;
|
|
40
|
+
serverResourcesMetaMap: Record<string, {
|
|
41
|
+
key: string;
|
|
42
|
+
}>;
|
|
43
|
+
environmentImportMetaMap: Record<string, Record<string, Record<string, EnvironmentImportMeta>>>;
|
|
44
|
+
stabilize(): void;
|
|
45
|
+
toRelativeId(id: string): string;
|
|
46
|
+
writeAssetsManifest(environmentNames: string[]): void;
|
|
47
|
+
writeEnvironmentImportsManifest(): void;
|
|
48
|
+
}
|
|
49
|
+
type RscPluginOptions = {
|
|
50
|
+
/**
|
|
51
|
+
* shorthand for configuring `environments.(name).build.rollupOptions.input.index`
|
|
52
|
+
*/
|
|
53
|
+
entries?: Partial<Record<"client" | "ssr" | "rsc", string>>;
|
|
54
|
+
/** @default { enviornmentName: "rsc", entryName: "index" } */
|
|
55
|
+
serverHandler?: {
|
|
56
|
+
environmentName: string;
|
|
57
|
+
entryName: string;
|
|
58
|
+
} | false;
|
|
59
|
+
/** @default false */
|
|
60
|
+
loadModuleDevProxy?: boolean;
|
|
61
|
+
rscCssTransform?: false | {
|
|
62
|
+
filter?: (id: string) => boolean;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* This option allows customizing how client build copies assets from server build.
|
|
66
|
+
* By default, all assets are copied, but frameworks can establish server asset convention
|
|
67
|
+
* to tighten security using this option.
|
|
68
|
+
*/
|
|
69
|
+
copyServerAssetsToClient?: (fileName: string) => boolean;
|
|
70
|
+
/**
|
|
71
|
+
* This option allows disabling action closure encryption for debugging purpose.
|
|
72
|
+
* @default true
|
|
73
|
+
*/
|
|
74
|
+
enableActionEncryption?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* By default, the plugin uses a build-time generated encryption key for
|
|
77
|
+
* "use server" closure argument binding.
|
|
78
|
+
* This can be overwritten by configuring `defineEncryptionKey` option,
|
|
79
|
+
* for example, to obtain a key through environment variable during runtime.
|
|
80
|
+
* cf. https://nextjs.org/docs/app/guides/data-security#overwriting-encryption-keys-advanced
|
|
81
|
+
*/
|
|
82
|
+
defineEncryptionKey?: string;
|
|
83
|
+
/** Escape hatch for Waku's `allowServer` */
|
|
84
|
+
keepUseCientProxy?: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Enable build-time validation of 'client-only' and 'server-only' imports
|
|
87
|
+
* @default true
|
|
88
|
+
*/
|
|
89
|
+
validateImports?: boolean;
|
|
90
|
+
/**
|
|
91
|
+
* use `Plugin.buildApp` hook (introduced on Vite 7) instead of `builder.buildApp` configuration
|
|
92
|
+
* for better composability with other plugins.
|
|
93
|
+
* @default true since Vite 7
|
|
94
|
+
*/
|
|
95
|
+
useBuildAppHook?: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Skip the default buildApp orchestration for downstream frameworks
|
|
98
|
+
* to implement custom build pipelines using `getPluginApi()`.
|
|
99
|
+
* @experimental
|
|
100
|
+
* @default false
|
|
101
|
+
*/
|
|
102
|
+
customBuildApp?: boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Custom environment configuration
|
|
105
|
+
* @experimental
|
|
106
|
+
* @default { browser: 'client', ssr: 'ssr', rsc: 'rsc' }
|
|
107
|
+
*/
|
|
108
|
+
environment?: {
|
|
109
|
+
browser?: string;
|
|
110
|
+
ssr?: string;
|
|
111
|
+
rsc?: string;
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Custom chunking strategy for client reference modules.
|
|
115
|
+
*
|
|
116
|
+
* This function allows you to group multiple client components into
|
|
117
|
+
* custom chunks instead of having each module in its own chunk.
|
|
118
|
+
* By default, client chunks are grouped by `meta.serverChunk`.
|
|
119
|
+
*/
|
|
120
|
+
clientChunks?: (meta: {
|
|
121
|
+
/** client reference module id */
|
|
122
|
+
id: string;
|
|
123
|
+
/** normalized client reference module id */
|
|
124
|
+
normalizedId: string;
|
|
125
|
+
/** server chunk which includes a corresponding client reference proxy module */
|
|
126
|
+
serverChunk: string;
|
|
127
|
+
}) => string | undefined;
|
|
128
|
+
/**
|
|
129
|
+
* Controls whether CSS links use React's `precedence` attribute.
|
|
130
|
+
* @experimental
|
|
131
|
+
* @default true
|
|
132
|
+
*/
|
|
133
|
+
cssLinkPrecedence?: boolean;
|
|
134
|
+
/**
|
|
135
|
+
* Opt out of the default "index" client entry convention.
|
|
136
|
+
* When enabled, the plugin will not:
|
|
137
|
+
* - Require an entry chunk named "index"
|
|
138
|
+
* - Automatically include client entry deps in each client reference's dependencies
|
|
139
|
+
*
|
|
140
|
+
* Note: `import.meta.viteRsc.loadBootstrapScriptContent` cannot be used with this option.
|
|
141
|
+
*
|
|
142
|
+
* Use this when you manually handle client entry setup and preloading.
|
|
143
|
+
*
|
|
144
|
+
* @experimental
|
|
145
|
+
* @default false
|
|
146
|
+
*/
|
|
147
|
+
customClientEntry?: boolean;
|
|
148
|
+
};
|
|
149
|
+
type PluginApi = {
|
|
150
|
+
manager: RscPluginManager;
|
|
151
|
+
};
|
|
152
|
+
/** @experimental */
|
|
153
|
+
declare function getPluginApi(config: Pick<ResolvedConfig, "plugins">): PluginApi | undefined;
|
|
154
|
+
/** @experimental */
|
|
155
|
+
declare function vitePluginRscMinimal(rscPluginOptions?: RscPluginOptions, manager?: RscPluginManager): Plugin[];
|
|
156
|
+
declare global {
|
|
157
|
+
function __VITE_ENVIRONMENT_RUNNER_IMPORT__(environmentName: string, id: string): Promise<any>;
|
|
158
|
+
}
|
|
159
|
+
declare function vitePluginRsc(rscPluginOptions?: RscPluginOptions): Plugin[];
|
|
160
|
+
declare class RuntimeAsset {
|
|
161
|
+
runtime: string;
|
|
162
|
+
constructor(value: string);
|
|
163
|
+
}
|
|
164
|
+
type AssetsManifest = {
|
|
165
|
+
bootstrapScriptContent: string | RuntimeAsset;
|
|
166
|
+
clientReferenceDeps: Record<string, AssetDeps>;
|
|
167
|
+
serverResources?: Record<string, Pick<AssetDeps, "css">>;
|
|
168
|
+
cssLinkPrecedence?: boolean;
|
|
169
|
+
};
|
|
170
|
+
type AssetDeps = {
|
|
171
|
+
js: (string | RuntimeAsset)[];
|
|
172
|
+
css: (string | RuntimeAsset)[];
|
|
173
|
+
};
|
|
174
|
+
type ResolvedAssetsManifest = {
|
|
175
|
+
bootstrapScriptContent: string;
|
|
176
|
+
clientReferenceDeps: Record<string, ResolvedAssetDeps>;
|
|
177
|
+
serverResources?: Record<string, Pick<ResolvedAssetDeps, "css">>;
|
|
178
|
+
cssLinkPrecedence?: boolean;
|
|
179
|
+
};
|
|
180
|
+
type ResolvedAssetDeps = {
|
|
181
|
+
js: string[];
|
|
182
|
+
css: string[];
|
|
183
|
+
};
|
|
184
|
+
declare function transformRscCssExport(options: {
|
|
185
|
+
ast: Awaited<ReturnType<typeof parseAstAsync>>;
|
|
186
|
+
code: string;
|
|
187
|
+
id?: string;
|
|
188
|
+
filter: TransformWrapExportFilter;
|
|
189
|
+
}): Promise<{
|
|
190
|
+
output: MagicString;
|
|
191
|
+
} | undefined>;
|
|
192
|
+
//#endregion
|
|
193
|
+
export { ResolvedAssetsManifest as a, getPluginApi as c, vitePluginRscMinimal as d, ResolvedAssetDeps as i, transformRscCssExport as l, AssetsManifest as n, RscPluginManager as o, PluginApi as r, RscPluginOptions as s, AssetDeps as t, vitePluginRsc as u };
|
package/dist/plugin.d.ts
CHANGED
|
@@ -1,161 +1,3 @@
|
|
|
1
|
-
import { s as
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
//#region src/plugin.d.ts
|
|
6
|
-
type ClientReferenceMeta = {
|
|
7
|
-
importId: string;
|
|
8
|
-
referenceKey: string;
|
|
9
|
-
packageSource?: string;
|
|
10
|
-
exportNames: string[];
|
|
11
|
-
renderedExports: string[];
|
|
12
|
-
serverChunk?: string;
|
|
13
|
-
groupChunkId?: string;
|
|
14
|
-
};
|
|
15
|
-
type ServerRerferenceMeta = {
|
|
16
|
-
importId: string;
|
|
17
|
-
referenceKey: string;
|
|
18
|
-
exportNames: string[];
|
|
19
|
-
};
|
|
20
|
-
/**
|
|
21
|
-
* @experimental
|
|
22
|
-
*/
|
|
23
|
-
declare class RscPluginManager {
|
|
24
|
-
server: ViteDevServer;
|
|
25
|
-
config: ResolvedConfig;
|
|
26
|
-
rscBundle: Rollup.OutputBundle;
|
|
27
|
-
buildAssetsManifest: AssetsManifest | undefined;
|
|
28
|
-
isScanBuild: boolean;
|
|
29
|
-
clientReferenceMetaMap: Record<string, ClientReferenceMeta>;
|
|
30
|
-
clientReferenceGroups: Record<string, ClientReferenceMeta[]>;
|
|
31
|
-
serverReferenceMetaMap: Record<string, ServerRerferenceMeta>;
|
|
32
|
-
serverResourcesMetaMap: Record<string, {
|
|
33
|
-
key: string;
|
|
34
|
-
}>;
|
|
35
|
-
stabilize(): void;
|
|
36
|
-
toRelativeId(id: string): string;
|
|
37
|
-
writeAssetsManifest(environmentNames: string[]): void;
|
|
38
|
-
}
|
|
39
|
-
type RscPluginOptions = {
|
|
40
|
-
/**
|
|
41
|
-
* shorthand for configuring `environments.(name).build.rollupOptions.input.index`
|
|
42
|
-
*/
|
|
43
|
-
entries?: Partial<Record<"client" | "ssr" | "rsc", string>>;
|
|
44
|
-
/** @default { enviornmentName: "rsc", entryName: "index" } */
|
|
45
|
-
serverHandler?: {
|
|
46
|
-
environmentName: string;
|
|
47
|
-
entryName: string;
|
|
48
|
-
} | false;
|
|
49
|
-
/** @default false */
|
|
50
|
-
loadModuleDevProxy?: boolean;
|
|
51
|
-
rscCssTransform?: false | {
|
|
52
|
-
filter?: (id: string) => boolean;
|
|
53
|
-
};
|
|
54
|
-
/**
|
|
55
|
-
* This option allows customizing how client build copies assets from server build.
|
|
56
|
-
* By default, all assets are copied, but frameworks can establish server asset convention
|
|
57
|
-
* to tighten security using this option.
|
|
58
|
-
*/
|
|
59
|
-
copyServerAssetsToClient?: (fileName: string) => boolean;
|
|
60
|
-
/**
|
|
61
|
-
* This option allows disabling action closure encryption for debugging purpose.
|
|
62
|
-
* @default true
|
|
63
|
-
*/
|
|
64
|
-
enableActionEncryption?: boolean;
|
|
65
|
-
/**
|
|
66
|
-
* By default, the plugin uses a build-time generated encryption key for
|
|
67
|
-
* "use server" closure argument binding.
|
|
68
|
-
* This can be overwritten by configuring `defineEncryptionKey` option,
|
|
69
|
-
* for example, to obtain a key through environment variable during runtime.
|
|
70
|
-
* cf. https://nextjs.org/docs/app/guides/data-security#overwriting-encryption-keys-advanced
|
|
71
|
-
*/
|
|
72
|
-
defineEncryptionKey?: string;
|
|
73
|
-
/** Escape hatch for Waku's `allowServer` */
|
|
74
|
-
keepUseCientProxy?: boolean;
|
|
75
|
-
/**
|
|
76
|
-
* Enable build-time validation of 'client-only' and 'server-only' imports
|
|
77
|
-
* @default true
|
|
78
|
-
*/
|
|
79
|
-
validateImports?: boolean;
|
|
80
|
-
/**
|
|
81
|
-
* use `Plugin.buildApp` hook (introduced on Vite 7) instead of `builder.buildApp` configuration
|
|
82
|
-
* for better composability with other plugins.
|
|
83
|
-
* @default true since Vite 7
|
|
84
|
-
*/
|
|
85
|
-
useBuildAppHook?: boolean;
|
|
86
|
-
/**
|
|
87
|
-
* Skip the default buildApp orchestration and expose utilities on `builder.rsc`
|
|
88
|
-
* for downstream frameworks to implement custom build pipelines.
|
|
89
|
-
* @experimental
|
|
90
|
-
* @default false
|
|
91
|
-
*/
|
|
92
|
-
customBuildApp?: boolean;
|
|
93
|
-
/**
|
|
94
|
-
* Custom environment configuration
|
|
95
|
-
* @experimental
|
|
96
|
-
* @default { browser: 'client', ssr: 'ssr', rsc: 'rsc' }
|
|
97
|
-
*/
|
|
98
|
-
environment?: {
|
|
99
|
-
browser?: string;
|
|
100
|
-
ssr?: string;
|
|
101
|
-
rsc?: string;
|
|
102
|
-
};
|
|
103
|
-
/**
|
|
104
|
-
* Custom chunking strategy for client reference modules.
|
|
105
|
-
*
|
|
106
|
-
* This function allows you to group multiple client components into
|
|
107
|
-
* custom chunks instead of having each module in its own chunk.
|
|
108
|
-
* By default, client chunks are grouped by `meta.serverChunk`.
|
|
109
|
-
*/
|
|
110
|
-
clientChunks?: (meta: {
|
|
111
|
-
/** client reference module id */
|
|
112
|
-
id: string;
|
|
113
|
-
/** normalized client reference module id */
|
|
114
|
-
normalizedId: string;
|
|
115
|
-
/** server chunk which includes a corresponding client reference proxy module */
|
|
116
|
-
serverChunk: string;
|
|
117
|
-
}) => string | undefined;
|
|
118
|
-
};
|
|
119
|
-
type PluginApi = {
|
|
120
|
-
manager: RscPluginManager;
|
|
121
|
-
};
|
|
122
|
-
/** @experimental */
|
|
123
|
-
declare function getPluginApi(config: Pick<ResolvedConfig, "plugins">): PluginApi | undefined;
|
|
124
|
-
/** @experimental */
|
|
125
|
-
declare function vitePluginRscMinimal(rscPluginOptions?: RscPluginOptions, manager?: RscPluginManager): Plugin[];
|
|
126
|
-
declare global {
|
|
127
|
-
function __VITE_ENVIRONMENT_RUNNER_IMPORT__(environmentName: string, id: string): Promise<any>;
|
|
128
|
-
}
|
|
129
|
-
declare function vitePluginRsc(rscPluginOptions?: RscPluginOptions): Plugin[];
|
|
130
|
-
declare class RuntimeAsset {
|
|
131
|
-
runtime: string;
|
|
132
|
-
constructor(value: string);
|
|
133
|
-
}
|
|
134
|
-
type AssetsManifest = {
|
|
135
|
-
bootstrapScriptContent: string | RuntimeAsset;
|
|
136
|
-
clientReferenceDeps: Record<string, AssetDeps>;
|
|
137
|
-
serverResources?: Record<string, Pick<AssetDeps, "css">>;
|
|
138
|
-
};
|
|
139
|
-
type AssetDeps = {
|
|
140
|
-
js: (string | RuntimeAsset)[];
|
|
141
|
-
css: (string | RuntimeAsset)[];
|
|
142
|
-
};
|
|
143
|
-
type ResolvedAssetsManifest = {
|
|
144
|
-
bootstrapScriptContent: string;
|
|
145
|
-
clientReferenceDeps: Record<string, ResolvedAssetDeps>;
|
|
146
|
-
serverResources?: Record<string, Pick<ResolvedAssetDeps, "css">>;
|
|
147
|
-
};
|
|
148
|
-
type ResolvedAssetDeps = {
|
|
149
|
-
js: string[];
|
|
150
|
-
css: string[];
|
|
151
|
-
};
|
|
152
|
-
declare function transformRscCssExport(options: {
|
|
153
|
-
ast: Awaited<ReturnType<typeof parseAstAsync>>;
|
|
154
|
-
code: string;
|
|
155
|
-
id?: string;
|
|
156
|
-
filter: TransformWrapExportFilter;
|
|
157
|
-
}): Promise<{
|
|
158
|
-
output: MagicString;
|
|
159
|
-
} | undefined>;
|
|
160
|
-
//#endregion
|
|
161
|
-
export { AssetDeps, AssetsManifest, PluginApi, ResolvedAssetDeps, ResolvedAssetsManifest, type RscPluginManager, RscPluginOptions, vitePluginRsc as default, getPluginApi, transformRscCssExport, vitePluginRscMinimal };
|
|
1
|
+
import { a as ResolvedAssetsManifest, c as getPluginApi, d as vitePluginRscMinimal, i as ResolvedAssetDeps, l as transformRscCssExport, n as AssetsManifest, o as RscPluginManager, r as PluginApi, s as RscPluginOptions, t as AssetDeps, u as vitePluginRsc } from "./plugin-V6VFxi_0.js";
|
|
2
|
+
import "./index-DJ0AhQ9B.js";
|
|
3
|
+
export { AssetDeps, AssetsManifest, PluginApi, ResolvedAssetDeps, ResolvedAssetsManifest, RscPluginManager, RscPluginOptions, vitePluginRsc as default, getPluginApi, transformRscCssExport, vitePluginRscMinimal };
|
package/dist/plugin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "./cjs-DH9Oa3zy.js";
|
|
2
|
-
import { i as vitePluginRscMinimal, n as transformRscCssExport, r as vitePluginRsc, t as getPluginApi } from "./plugin-
|
|
2
|
+
import { i as vitePluginRscMinimal, n as transformRscCssExport, r as vitePluginRsc, t as getPluginApi } from "./plugin-DBWiu_Dx.js";
|
|
3
3
|
import "./transforms-D4jDIHgD.js";
|
|
4
4
|
import "./rpc-DbBe389F.js";
|
|
5
5
|
|
package/dist/ssr.d.ts
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
1
|
import { createServerConsumerManifest, setRequireModule } from "./core/ssr.js";
|
|
2
|
+
import { i as ResolvedAssetDeps } from "./plugin-V6VFxi_0.js";
|
|
3
|
+
import "./index-DJ0AhQ9B.js";
|
|
2
4
|
import { callServer, createFromReadableStream, createServerReference, findSourceMapURL } from "./react/ssr.js";
|
|
3
|
-
|
|
5
|
+
|
|
6
|
+
//#region src/ssr.d.ts
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Callback type for client reference dependency notifications.
|
|
10
|
+
* Called during SSR when a client component's dependencies are loaded.
|
|
11
|
+
* @experimental
|
|
12
|
+
*/
|
|
13
|
+
type OnClientReference = (reference: {
|
|
14
|
+
id: string;
|
|
15
|
+
deps: ResolvedAssetDeps;
|
|
16
|
+
}) => void;
|
|
17
|
+
/**
|
|
18
|
+
* Register a callback to be notified when client reference dependencies are loaded.
|
|
19
|
+
* Called during SSR when a client component is accessed.
|
|
20
|
+
* @experimental
|
|
21
|
+
*/
|
|
22
|
+
declare function setOnClientReference(callback: OnClientReference | undefined): void;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { OnClientReference, callServer, createFromReadableStream, createServerConsumerManifest, createServerReference, findSourceMapURL, setOnClientReference, setRequireModule };
|
package/dist/ssr.js
CHANGED
|
@@ -6,6 +6,15 @@ import * as ReactDOM from "react-dom";
|
|
|
6
6
|
import assetsManifest from "virtual:vite-rsc/assets-manifest";
|
|
7
7
|
|
|
8
8
|
//#region src/ssr.tsx
|
|
9
|
+
let onClientReference;
|
|
10
|
+
/**
|
|
11
|
+
* Register a callback to be notified when client reference dependencies are loaded.
|
|
12
|
+
* Called during SSR when a client component is accessed.
|
|
13
|
+
* @experimental
|
|
14
|
+
*/
|
|
15
|
+
function setOnClientReference(callback) {
|
|
16
|
+
onClientReference = callback;
|
|
17
|
+
}
|
|
9
18
|
initialize();
|
|
10
19
|
function initialize() {
|
|
11
20
|
setRequireModule({ load: async (id) => {
|
|
@@ -20,7 +29,7 @@ function initialize() {
|
|
|
20
29
|
return wrapResourceProxy(await import(
|
|
21
30
|
/* @vite-ignore */
|
|
22
31
|
id
|
|
23
|
-
), {
|
|
32
|
+
), id, {
|
|
24
33
|
js: [],
|
|
25
34
|
css: (await import(
|
|
26
35
|
/* @vite-ignore */
|
|
@@ -33,16 +42,27 @@ function initialize() {
|
|
|
33
42
|
} else {
|
|
34
43
|
const import_ = clientReferences.default[id];
|
|
35
44
|
if (!import_) throw new Error(`client reference not found '${id}'`);
|
|
36
|
-
const deps = assetsManifest.clientReferenceDeps[id]
|
|
37
|
-
|
|
38
|
-
|
|
45
|
+
const deps = assetsManifest.clientReferenceDeps[id] ?? {
|
|
46
|
+
js: [],
|
|
47
|
+
css: []
|
|
48
|
+
};
|
|
49
|
+
preloadDeps(deps);
|
|
50
|
+
onClientReference?.({
|
|
51
|
+
id,
|
|
52
|
+
deps
|
|
53
|
+
});
|
|
54
|
+
return wrapResourceProxy(await import_(), id, deps);
|
|
39
55
|
}
|
|
40
56
|
} });
|
|
41
57
|
}
|
|
42
|
-
function wrapResourceProxy(mod, deps) {
|
|
58
|
+
function wrapResourceProxy(mod, id, deps) {
|
|
43
59
|
return new Proxy(mod, { get(target, p, receiver) {
|
|
44
60
|
if (p in mod) {
|
|
45
|
-
|
|
61
|
+
preloadDeps(deps);
|
|
62
|
+
onClientReference?.({
|
|
63
|
+
id,
|
|
64
|
+
deps
|
|
65
|
+
});
|
|
46
66
|
}
|
|
47
67
|
return Reflect.get(target, p, receiver);
|
|
48
68
|
} });
|
|
@@ -54,9 +74,9 @@ function preloadDeps(deps) {
|
|
|
54
74
|
});
|
|
55
75
|
for (const href of deps.css) ReactDOM.preinit(href, {
|
|
56
76
|
as: "style",
|
|
57
|
-
precedence: "vite-rsc/client-reference"
|
|
77
|
+
precedence: assetsManifest.cssLinkPrecedence !== false ? "vite-rsc/client-reference" : void 0
|
|
58
78
|
});
|
|
59
79
|
}
|
|
60
80
|
|
|
61
81
|
//#endregion
|
|
62
|
-
export { callServer, createFromReadableStream, createServerConsumerManifest, createServerReference, findSourceMapURL, setRequireModule };
|
|
82
|
+
export { callServer, createFromReadableStream, createServerConsumerManifest, createServerReference, findSourceMapURL, setOnClientReference, setRequireModule };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as transformDirectiveProxyExport, c as TransformWrapExportOptions, d as transformHoistInlineDirective, i as TransformProxyExportOptions, l as transformWrapExport, n as getExportNames, o as transformProxyExport, r as hasDirective, s as TransformWrapExportFilter, t as transformServerActionServer, u as findDirectives } from "../index-
|
|
1
|
+
import { a as transformDirectiveProxyExport, c as TransformWrapExportOptions, d as transformHoistInlineDirective, i as TransformProxyExportOptions, l as transformWrapExport, n as getExportNames, o as transformProxyExport, r as hasDirective, s as TransformWrapExportFilter, t as transformServerActionServer, u as findDirectives } from "../index-DJ0AhQ9B.js";
|
|
2
2
|
export { TransformProxyExportOptions, TransformWrapExportFilter, TransformWrapExportOptions, findDirectives, getExportNames, hasDirective, transformDirectiveProxyExport, transformHoistInlineDirective, transformProxyExport, transformServerActionServer, transformWrapExport };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vitejs/plugin-rsc",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.15",
|
|
4
4
|
"description": "React Server Components (RSC) support for Vite.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"@playwright/test": "^1.57.0",
|
|
54
54
|
"@tsconfig/strictest": "^2.0.8",
|
|
55
55
|
"@types/estree": "^1.0.8",
|
|
56
|
-
"@types/node": "^24.10.
|
|
56
|
+
"@types/node": "^24.10.9",
|
|
57
57
|
"@types/react": "^19.2.8",
|
|
58
58
|
"@types/react-dom": "^19.2.3",
|
|
59
59
|
"@vitejs/plugin-react": "workspace:*",
|
|
@@ -75,5 +75,16 @@
|
|
|
75
75
|
"react-server-dom-webpack": {
|
|
76
76
|
"optional": true
|
|
77
77
|
}
|
|
78
|
+
},
|
|
79
|
+
"compatiblePackages": {
|
|
80
|
+
"schemaVersion": 1,
|
|
81
|
+
"rolldown": {
|
|
82
|
+
"type": "incompatible",
|
|
83
|
+
"reason": "Uses Vite-specific APIs"
|
|
84
|
+
},
|
|
85
|
+
"rollup": {
|
|
86
|
+
"type": "incompatible",
|
|
87
|
+
"reason": "Uses Vite-specific APIs"
|
|
88
|
+
}
|
|
78
89
|
}
|
|
79
90
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -4,6 +4,29 @@ declare global {
|
|
|
4
4
|
loadCss: (importer?: string) => import('react').ReactNode
|
|
5
5
|
loadModule: <T>(environmentName: string, entryName?: string) => Promise<T>
|
|
6
6
|
loadBootstrapScriptContent: (entryName: string) => Promise<string>
|
|
7
|
+
/**
|
|
8
|
+
* Import a module from another environment using a module specifier.
|
|
9
|
+
*
|
|
10
|
+
* A more ergonomic alternative to `loadModule` that takes a relative path
|
|
11
|
+
* instead of an entry name, so the specifier matches what you'd use in
|
|
12
|
+
* `typeof import(...)` type annotations.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const ssr = await import.meta.viteRsc.import<typeof import('./entry.ssr')>(
|
|
17
|
+
* './entry.ssr',
|
|
18
|
+
* { environment: 'ssr' }
|
|
19
|
+
* );
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @param specifier - Relative path to the module (e.g., './entry.ssr')
|
|
23
|
+
* @param options - Options object with `environment` specifying the target environment
|
|
24
|
+
* @returns Promise resolving to the module exports
|
|
25
|
+
*/
|
|
26
|
+
import: <T>(
|
|
27
|
+
specifier: string,
|
|
28
|
+
options: { environment: string },
|
|
29
|
+
) => Promise<T>
|
|
7
30
|
}
|
|
8
31
|
}
|
|
9
32
|
|
|
@@ -17,18 +40,6 @@ declare module 'vite' {
|
|
|
17
40
|
/** Options for `@vitejs/plugin-rsc` */
|
|
18
41
|
rsc?: import('@vitejs/plugin-rsc').RscPluginOptions
|
|
19
42
|
}
|
|
20
|
-
|
|
21
|
-
interface ViteBuilder {
|
|
22
|
-
/**
|
|
23
|
-
* RSC plugin API exposed for custom build pipelines.
|
|
24
|
-
* Available when using `rsc({ customBuildApp: true })`.
|
|
25
|
-
* @experimental
|
|
26
|
-
*/
|
|
27
|
-
rsc: {
|
|
28
|
-
/** Access to internal RscPluginManager for controlling build phases */
|
|
29
|
-
manager: import('@vitejs/plugin-rsc').RscPluginManager
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
43
|
}
|
|
33
44
|
|
|
34
45
|
export {}
|
|
File without changes
|