@vitejs/plugin-rsc 0.5.14 → 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-Ch1dPqbr.js → plugin-DBWiu_Dx.js} +211 -96
- 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 -0
- /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,6 +620,7 @@ 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 [
|
|
@@ -874,18 +979,19 @@ export function createRpcClient(params) {
|
|
|
874
979
|
assert(this.environment.mode === "dev");
|
|
875
980
|
const manifest = {
|
|
876
981
|
bootstrapScriptContent: `import(${serializeValueWithRuntime(assetsURL("@id/__x00__" + VIRTUAL_ENTRIES.browser, manager))})`,
|
|
877
|
-
clientReferenceDeps: {}
|
|
982
|
+
clientReferenceDeps: {},
|
|
983
|
+
cssLinkPrecedence: rscPluginOptions.cssLinkPrecedence
|
|
878
984
|
};
|
|
879
985
|
return `export default ${JSON.stringify(manifest, null, 2)}`;
|
|
880
986
|
}
|
|
881
987
|
},
|
|
882
988
|
generateBundle(_options, bundle) {
|
|
883
|
-
|
|
989
|
+
manager.bundles[this.environment.name] = bundle;
|
|
884
990
|
if (this.environment.name === "client") {
|
|
885
991
|
const filterAssets = rscPluginOptions.copyServerAssetsToClient ?? (() => true);
|
|
886
992
|
const rscBuildOptions = manager.config.environments.rsc.build;
|
|
887
993
|
const rscViteManifest = typeof rscBuildOptions.manifest === "string" ? rscBuildOptions.manifest : rscBuildOptions.manifest && ".vite/manifest.json";
|
|
888
|
-
for (const asset of Object.values(manager.
|
|
994
|
+
for (const asset of Object.values(manager.bundles["rsc"])) {
|
|
889
995
|
if (asset.fileName === rscViteManifest) continue;
|
|
890
996
|
if (asset.type === "asset" && filterAssets(asset.fileName)) this.emitFile({
|
|
891
997
|
type: "asset",
|
|
@@ -894,30 +1000,35 @@ export function createRpcClient(params) {
|
|
|
894
1000
|
});
|
|
895
1001
|
}
|
|
896
1002
|
const serverResources = {};
|
|
897
|
-
const rscAssetDeps = collectAssetDeps(manager.
|
|
1003
|
+
const rscAssetDeps = collectAssetDeps(manager.bundles["rsc"]);
|
|
898
1004
|
for (const [id, meta] of Object.entries(manager.serverResourcesMetaMap)) serverResources[meta.key] = assetsURLOfDeps({
|
|
899
1005
|
js: [],
|
|
900
1006
|
css: rscAssetDeps[id]?.deps.css ?? []
|
|
901
1007
|
}, manager);
|
|
902
1008
|
const assetDeps = collectAssetDeps(bundle);
|
|
903
|
-
|
|
904
|
-
assert(entry);
|
|
905
|
-
const entryUrl = assetsURL(entry.chunk.fileName, manager);
|
|
1009
|
+
let bootstrapScriptContent = "";
|
|
906
1010
|
const clientReferenceDeps = {};
|
|
907
1011
|
for (const meta of Object.values(manager.clientReferenceMetaMap)) {
|
|
908
1012
|
const deps = assetDeps[meta.groupChunkId]?.deps ?? {
|
|
909
1013
|
js: [],
|
|
910
1014
|
css: []
|
|
911
1015
|
};
|
|
912
|
-
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}) + ")"`);
|
|
913
1026
|
}
|
|
914
|
-
let bootstrapScriptContent;
|
|
915
|
-
if (typeof entryUrl === "string") bootstrapScriptContent = `import(${JSON.stringify(entryUrl)})`;
|
|
916
|
-
else bootstrapScriptContent = new RuntimeAsset(`"import(" + JSON.stringify(${entryUrl.runtime}) + ")"`);
|
|
917
1027
|
manager.buildAssetsManifest = {
|
|
918
1028
|
bootstrapScriptContent,
|
|
919
1029
|
clientReferenceDeps,
|
|
920
|
-
serverResources
|
|
1030
|
+
serverResources,
|
|
1031
|
+
cssLinkPrecedence: rscPluginOptions.cssLinkPrecedence
|
|
921
1032
|
};
|
|
922
1033
|
}
|
|
923
1034
|
},
|
|
@@ -941,6 +1052,7 @@ export default assetsManifest.bootstrapScriptContent;
|
|
|
941
1052
|
name: "rsc:bootstrap-script-content",
|
|
942
1053
|
async transform(code) {
|
|
943
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`);
|
|
944
1056
|
assert(this.environment.name !== "client");
|
|
945
1057
|
const output = new MagicString(code);
|
|
946
1058
|
for (const match of stripLiteral(code).matchAll(/import\s*\.\s*meta\s*\.\s*viteRsc\s*\.\s*loadBootstrapScriptContent\(([\s\S]*?)\)/dg)) {
|
|
@@ -997,6 +1109,7 @@ import.meta.hot.on("rsc:update", () => {
|
|
|
997
1109
|
return code;
|
|
998
1110
|
}),
|
|
999
1111
|
...vitePluginRscMinimal(rscPluginOptions, manager),
|
|
1112
|
+
...vitePluginImportEnvironment(manager),
|
|
1000
1113
|
...vitePluginFindSourceMapURL(),
|
|
1001
1114
|
...vitePluginRscCss(rscPluginOptions, manager),
|
|
1002
1115
|
{
|
|
@@ -1661,13 +1774,13 @@ function vitePluginRscCss(rscCssOptions = {}, manager) {
|
|
|
1661
1774
|
return generateResourcesCode(serializeValueWithRuntime(assetsURLOfDeps({
|
|
1662
1775
|
css: result.hrefs.map((href) => href.slice(1)),
|
|
1663
1776
|
js: []
|
|
1664
|
-
}, manager)), manager);
|
|
1777
|
+
}, manager)), manager, { cssLinkPrecedence: rscCssOptions.cssLinkPrecedence });
|
|
1665
1778
|
} else {
|
|
1666
1779
|
const key = manager.toRelativeId(importer);
|
|
1667
1780
|
manager.serverResourcesMetaMap[importer] = { key };
|
|
1668
1781
|
return `
|
|
1669
1782
|
import __vite_rsc_assets_manifest__ from "virtual:vite-rsc/assets-manifest";
|
|
1670
|
-
${generateResourcesCode(`__vite_rsc_assets_manifest__.serverResources[${JSON.stringify(key)}]`, manager)}
|
|
1783
|
+
${generateResourcesCode(`__vite_rsc_assets_manifest__.serverResources[${JSON.stringify(key)}]`, manager, { cssLinkPrecedence: rscCssOptions.cssLinkPrecedence })}
|
|
1671
1784
|
`;
|
|
1672
1785
|
}
|
|
1673
1786
|
}
|
|
@@ -1693,13 +1806,14 @@ export default function RemoveDuplicateServerCss() {
|
|
|
1693
1806
|
})
|
|
1694
1807
|
];
|
|
1695
1808
|
}
|
|
1696
|
-
function generateResourcesCode(depsCode, manager) {
|
|
1697
|
-
const
|
|
1809
|
+
function generateResourcesCode(depsCode, manager, options = {}) {
|
|
1810
|
+
const usePrecedence = options.cssLinkPrecedence !== false;
|
|
1811
|
+
const ResourcesFn = (React, deps, RemoveDuplicateServerCss, precedence) => {
|
|
1698
1812
|
return function Resources() {
|
|
1699
1813
|
return React.createElement(React.Fragment, null, [...deps.css.map((href) => React.createElement("link", {
|
|
1700
1814
|
key: "css:" + href,
|
|
1701
1815
|
rel: "stylesheet",
|
|
1702
|
-
precedence:
|
|
1816
|
+
...precedence ? { precedence } : {},
|
|
1703
1817
|
href,
|
|
1704
1818
|
"data-rsc-css-href": href
|
|
1705
1819
|
})), RemoveDuplicateServerCss && React.createElement(RemoveDuplicateServerCss, { key: "remove-duplicate-css" })]);
|
|
@@ -1714,6 +1828,7 @@ export const Resources = (${ResourcesFn.toString()})(
|
|
|
1714
1828
|
__vite_rsc_react__,
|
|
1715
1829
|
${depsCode},
|
|
1716
1830
|
RemoveDuplicateServerCss,
|
|
1831
|
+
${usePrecedence ? `"vite-rsc/importer-resources"` : `undefined`},
|
|
1717
1832
|
);
|
|
1718
1833
|
`;
|
|
1719
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 for downstream frameworks
|
|
88
|
-
* to implement custom build pipelines using `getPluginApi()`.
|
|
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
|
|
|
File without changes
|