@vitejs/plugin-rsc 0.5.30 → 0.5.31

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 CHANGED
@@ -25,10 +25,15 @@ npm create vite@latest -- --template rsc
25
25
 
26
26
  **Integration examples:**
27
27
 
28
- - [`./examples/basic`](./examples/basic) - Advanced RSC features and testing
29
- - This is mainly used for e2e testing and includes various advanced RSC usages (e.g. `"use cache"` example).
30
- - [`./examples/performance-track`](./examples/performance-track) - Minimal React Server Components performance track probe.
28
+ - [`./examples/basic`](./examples/basic) - Comprehensive showcase of standard RSC features and the primary E2E test fixture.
29
+ - [`./examples/use-cache`](./examples/use-cache) - Minimal cache feature inspired by Next.js's `"use cache"`, built with generic transform and RSC runtime APIs.
30
+ - [`./examples/custom-server-function`](./examples/custom-server-function) - Third-party Server Function directive integration using server reference claims.
31
31
  - [`./examples/ssg`](./examples/ssg) - Static site generation with MDX and client components for interactivity.
32
+ - [`./examples/ppr`](./examples/ppr) - Partial prerendering with a reusable static HTML shell and request-time RSC content.
33
+ - [`./examples/no-ssr`](./examples/no-ssr) - RSC application without an SSR environment.
34
+ - [`./examples/client-first`](./examples/client-first) - Experimental client-owned page that consumes RSC function results.
35
+ - [`./examples/browser-mode`](./examples/browser-mode) - Advanced setup that runs both RSC and React client environments in the browser with custom module loading.
36
+ - [`./examples/performance-track`](./examples/performance-track) - Minimal React Server Components performance track probe.
32
37
  - [`./examples/react-router`](./examples/react-router) - React Router RSC integration
33
38
  - Demonstrates how to integrate [experimental React Router RSC API](https://remix.run/blog/rsc-preview). React Router now provides [official RSC support](https://reactrouter.com/how-to/react-server-components), so it's recommended to follow React Router's official documentation for the latest integration.
34
39
 
@@ -525,6 +530,29 @@ This module provides Vite-integrated RSC runtime APIs based on
525
530
  - `createTemporaryReferenceSet`: Creates a temporary reference set shared by deserialization and reply serialization
526
531
  - `setServerCallback`: Configures how server functions are called
527
532
 
533
+ ### Low-level runtime entry points
534
+
535
+ The runtime APIs are exposed through two layers:
536
+
537
+ - `@vitejs/plugin-rsc/rsc`, `@vitejs/plugin-rsc/ssr`, and
538
+ `@vitejs/plugin-rsc/browser` are the recommended entry points for application
539
+ and framework runtime code. They initialize the plugin's built-in module
540
+ loading using the manifests generated by Vite and re-export the corresponding
541
+ React runtime APIs described above.
542
+ - `@vitejs/plugin-rsc/react/rsc`, `@vitejs/plugin-rsc/react/ssr`, and
543
+ `@vitejs/plugin-rsc/react/browser` are low-level runtime adapters. They are
544
+ used by code generated for `"use client"` and `"use server"`, and by custom
545
+ integrations that provide module loading through `setRequireModule` instead
546
+ of using the plugin's generated manifests.
547
+
548
+ The two layers share the same module loader within an environment, which allows
549
+ generated code to use `/react/*` after a top-level entry initializes the
550
+ built-in loader. Application code should continue using the top-level entries,
551
+ which re-export the same runtime APIs. Direct use of `/react/*` is only needed
552
+ by custom integrations that install their own loaders, such as the
553
+ [`examples/browser-mode`](./examples/browser-mode) example, which runs the RSC
554
+ and React client environments in the browser.
555
+
528
556
  ## Tips
529
557
 
530
558
  ### CSS Support
@@ -1,5 +1,5 @@
1
1
  import { t as ClientReferenceMetadata } from "./rsc-C3UdJLOW.js";
2
- import { i as ResolvedAssetDeps } from "./plugin-CaLiN8ED.js";
2
+ import { i as ResolvedAssetDeps } from "./plugin-DQCCjJl0.js";
3
3
  //#region src/rsc/client-reference.d.ts
4
4
  type OnClientReference = (metadata: ClientReferenceMetadata & {
5
5
  deps: ResolvedAssetDeps;
@@ -526,6 +526,59 @@ interface AwaitExpression extends BaseExpression {
526
526
  }
527
527
  //#endregion
528
528
  //#region src/transforms/hoist.d.ts
529
+ /**
530
+ * Turns an inline directive function into a module-level registered function.
531
+ * Conceptually:
532
+ *
533
+ * ```js
534
+ * function Component() {
535
+ * const x = 1
536
+ * async function action(y) {
537
+ * "use server"
538
+ * return x + y
539
+ * }
540
+ * }
541
+ * ```
542
+ *
543
+ * becomes:
544
+ *
545
+ * ```js
546
+ * function Component() {
547
+ * const x = 1
548
+ * const action = __RUNTIME__($$hoist_0_action).bind(null, x)
549
+ * }
550
+ * export async function $$hoist_0_action(x, y) {
551
+ * "use server"
552
+ * return x + y
553
+ * }
554
+ * ```
555
+ *
556
+ * The generated export is `$$hoist_0_action`, so `names` contains
557
+ * `['$$hoist_0_action']` for this example.
558
+ *
559
+ * Here, `__RUNTIME__(...)` represents the registration expression returned by the
560
+ * `runtime` callback. When `encode` and `decode` are provided, the closure
561
+ * captures instead travel as one encoded bound argument:
562
+ *
563
+ * ```js
564
+ * function Component() {
565
+ * const x = 1
566
+ * const action = __RUNTIME__($$hoist_0_action).bind(
567
+ * null,
568
+ * __ENCODE__([x]),
569
+ * )
570
+ * }
571
+ *
572
+ * export async function $$hoist_0_action($$hoist_encoded, y) {
573
+ * const [x] = __DECODE__($$hoist_encoded)
574
+ * "use server"
575
+ * return x + y
576
+ * }
577
+ * ```
578
+ *
579
+ * In this second sketch, `__ENCODE__(...)` and `__DECODE__(...)` likewise
580
+ * represent the expressions returned by those code-generation callbacks.
581
+ */
529
582
  declare function transformHoistInlineDirective(input: string, ast: Program, { runtime, rejectNonAsyncFunction, ...options }: {
530
583
  runtime: (value: string, name: string, meta: {
531
584
  directiveMatch: RegExpMatchArray;
@@ -534,6 +587,7 @@ declare function transformHoistInlineDirective(input: string, ast: Program, { ru
534
587
  rejectNonAsyncFunction?: boolean;
535
588
  encode?: (value: string) => string;
536
589
  decode?: (value: string) => string;
590
+ /** Keep generated hoisted declarations module-local instead of exporting them. */
537
591
  noExport?: boolean;
538
592
  }): {
539
593
  output: MagicString;
@@ -627,9 +681,11 @@ declare function transformServerActionServer(input: string, ast: Program, option
627
681
  }): {
628
682
  exportNames: string[];
629
683
  output: MagicString;
684
+ referenceNames: string[];
630
685
  } | {
631
686
  output: MagicString;
632
687
  names: string[];
688
+ referenceNames: string[];
633
689
  };
634
690
  //#endregion
635
691
  //#region src/transforms/expand-export-all.d.ts
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { c as getPluginApi, r as PluginApi, s as RscPluginOptions, u as vitePluginRsc } from "./plugin-CaLiN8ED.js";
2
- export { type PluginApi, type RscPluginOptions, vitePluginRsc as default, getPluginApi };
1
+ import { c as getPluginApi, o as RscPluginManager, r as PluginApi, s as RscPluginOptions, u as vitePluginRsc } from "./plugin-DQCCjJl0.js";
2
+ export { type PluginApi, type RscPluginManager, type RscPluginOptions, vitePluginRsc as default, getPluginApi };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { r as vitePluginRsc, t as getPluginApi } from "./plugin-ByvxS0by.js";
1
+ import { r as vitePluginRsc, t as getPluginApi } from "./plugin-DbK8rF7n.js";
2
2
  export { vitePluginRsc as default, getPluginApi };
@@ -1,4 +1,4 @@
1
- import { a as __commonJSMin } from "./plugin-ByvxS0by.js";
1
+ import { a as __commonJSMin } from "./plugin-DbK8rF7n.js";
2
2
  //#region ../../node_modules/.pnpm/picocolors@1.1.1/node_modules/picocolors/picocolors.js
3
3
  var require_picocolors = /* @__PURE__ */ __commonJSMin(((exports, module) => {
4
4
  let p = process || {};
@@ -1,4 +1,4 @@
1
- import { f as TransformWrapExportFilter } from "./index-BjJe9jqG.js";
1
+ import { f as TransformWrapExportFilter } from "./index-COzKOTR1.js";
2
2
  import MagicString from "magic-string";
3
3
  import { Plugin, ResolvedConfig, Rollup, ViteDevServer, parseAstAsync } from "vite";
4
4
  //#region src/plugins/import-environment.d.ts
@@ -9,6 +9,30 @@ type EnvironmentImportMeta = {
9
9
  specifier: string;
10
10
  };
11
11
  //#endregion
12
+ //#region src/plugins/server-reference.d.ts
13
+ type ServerReferenceMeta = {
14
+ importId: string;
15
+ referenceKey: string;
16
+ exportNames: string[];
17
+ };
18
+ type ServerReferenceClaimMap = DefaultMap<string, Map<string, ServerReferenceMeta>>;
19
+ declare class ServerReferencesManager {
20
+ private manager;
21
+ claimMap: ServerReferenceClaimMap;
22
+ metaMap: Map<string, ServerReferenceMeta>;
23
+ constructor(manager: RscPluginManager);
24
+ resolve(id: string, serverEnvironmentName: string): ServerReferenceMeta;
25
+ replaceClaim(owner: string, id: string, meta: ServerReferenceMeta): void;
26
+ deleteClaim(owner: string, id: string): void;
27
+ findByReferenceKey(referenceKey: string): ServerReferenceMeta | undefined;
28
+ private normalizeImportId;
29
+ }
30
+ declare class DefaultMap<K, V> extends Map<K, V> {
31
+ private createDefault;
32
+ constructor(createDefault: (key: K) => V);
33
+ override get(key: K): V;
34
+ }
35
+ //#endregion
12
36
  //#region src/plugin.d.ts
13
37
  type ClientReferenceMeta = {
14
38
  importId: string;
@@ -19,11 +43,6 @@ type ClientReferenceMeta = {
19
43
  serverChunk?: string;
20
44
  groupChunkId?: string;
21
45
  };
22
- type ServerReferenceMeta = {
23
- importId: string;
24
- referenceKey: string;
25
- exportNames: string[];
26
- };
27
46
  /**
28
47
  * @experimental
29
48
  */
@@ -35,7 +54,7 @@ declare class RscPluginManager {
35
54
  isScanBuild: boolean;
36
55
  clientReferenceMetaMap: Record<string, ClientReferenceMeta>;
37
56
  clientReferenceGroups: Record<string, ClientReferenceMeta[]>;
38
- serverReferenceMetaMap: Record<string, ServerReferenceMeta>;
57
+ serverReferences: ServerReferencesManager;
39
58
  serverResourcesMetaMap: Record<string, {
40
59
  key: string;
41
60
  }>;
@@ -50,7 +69,7 @@ type RscPluginOptions = {
50
69
  * shorthand for configuring `environments.(name).build.rollupOptions.input.index`
51
70
  */
52
71
  entries?: Partial<Record<"client" | "ssr" | "rsc", string>>;
53
- /** @default { enviornmentName: "rsc", entryName: "index" } */
72
+ /** @default { environmentName: "rsc", entryName: "index" } */
54
73
  serverHandler?: {
55
74
  environmentName: string;
56
75
  entryName: string;
@@ -78,6 +97,11 @@ type RscPluginOptions = {
78
97
  */
79
98
  defineEncryptionKey?: string;
80
99
  /** Escape hatch for Waku's `allowServer` */
100
+ keepUseClientProxy?: boolean;
101
+ /**
102
+ * @deprecated This option contains a typo. Use `keepUseClientProxy` instead.
103
+ * It will be removed in the next breaking release.
104
+ */
81
105
  keepUseCientProxy?: boolean;
82
106
  /**
83
107
  * Enable build-time validation of 'client-only' and 'server-only' imports
@@ -226,7 +226,7 @@ function getEntrySource(config, name) {
226
226
  throw new Error(`[vite-rsc:getEntrySource] expected 'build.rollupOptions.input' to be an object with a '${name}' property that is a string, but got ${JSON.stringify(input)}`);
227
227
  }
228
228
  function getFallbackRollupEntry(input = {}) {
229
- const inputEntries = Object.entries(normalizeRollupOpitonsInput(input));
229
+ const inputEntries = Object.entries(normalizeRollupOptionsInput(input));
230
230
  if (inputEntries.length === 1) {
231
231
  const [name, source] = inputEntries[0];
232
232
  return {
@@ -236,7 +236,7 @@ function getFallbackRollupEntry(input = {}) {
236
236
  }
237
237
  throw new Error(`[vite-rsc] cannot determine fallback entry name from multiple entries, please specify the entry name explicitly`);
238
238
  }
239
- function normalizeRollupOpitonsInput(input = {}) {
239
+ function normalizeRollupOptionsInput(input = {}) {
240
240
  if (typeof input === "string") input = [input];
241
241
  if (Array.isArray(input)) return Object.fromEntries(input.map((file) => [path.basename(file).slice(0, -path.extname(file).length), file]));
242
242
  return input;
@@ -260,7 +260,7 @@ const ENV_IMPORTS_ENTRY_FALLBACK = "virtual:vite-rsc/env-imports-entry-fallback"
260
260
  function ensureEnvironmentImportsEntryFallback({ environments }) {
261
261
  for (const [name, config] of Object.entries(environments)) {
262
262
  if (name === "client") continue;
263
- const input = normalizeRollupOpitonsInput(config.build?.rollupOptions?.input);
263
+ const input = normalizeRollupOptionsInput(config.build?.rollupOptions?.input);
264
264
  if (Object.keys(input).length === 0) {
265
265
  config.build = config.build || {};
266
266
  config.build.rollupOptions = config.build.rollupOptions || {};
@@ -439,6 +439,80 @@ async function transformScanBuildStrip(code) {
439
439
  return output;
440
440
  }
441
441
  //#endregion
442
+ //#region src/plugins/server-reference.ts
443
+ var ServerReferencesManager = class {
444
+ manager;
445
+ claimMap = new DefaultMap(() => /* @__PURE__ */ new Map());
446
+ metaMap = /* @__PURE__ */ new Map();
447
+ constructor(manager) {
448
+ this.manager = manager;
449
+ }
450
+ resolve(id, serverEnvironmentName) {
451
+ const importId = this.normalizeImportId(id);
452
+ return {
453
+ importId,
454
+ referenceKey: this.manager.config.command === "build" ? hashString(this.manager.toRelativeId(importId)) : normalizeViteImportAnalysisUrl(this.manager.server.environments[serverEnvironmentName], importId),
455
+ exportNames: []
456
+ };
457
+ }
458
+ replaceClaim(owner, id, meta) {
459
+ this.claimMap.get(id).set(owner, meta);
460
+ this.metaMap = deriveMetaMap(this.claimMap);
461
+ }
462
+ deleteClaim(owner, id) {
463
+ const ownerMap = this.claimMap.get(id);
464
+ ownerMap.delete(owner);
465
+ if (ownerMap.size === 0) this.claimMap.delete(id);
466
+ this.metaMap = deriveMetaMap(this.claimMap);
467
+ }
468
+ findByReferenceKey(referenceKey) {
469
+ for (const meta of this.metaMap.values()) if (meta.referenceKey === referenceKey) return meta;
470
+ }
471
+ normalizeImportId(id) {
472
+ return this.manager.config.command !== "build" && id.includes("/node_modules/") ? cleanUrl(id) : id;
473
+ }
474
+ };
475
+ function deriveMetaMap(claimMap) {
476
+ const normalizedClaimMap = new DefaultMap(() => /* @__PURE__ */ new Map());
477
+ for (const claims of claimMap.values()) for (const [owner, claim] of claims) normalizedClaimMap.get(claim.importId).set(owner, claim);
478
+ const metaMap = /* @__PURE__ */ new Map();
479
+ for (const [importId, claims] of normalizedClaimMap) metaMap.set(importId, aggregateClaims(importId, claims));
480
+ return metaMap;
481
+ }
482
+ function aggregateClaims(importId, claims) {
483
+ let aggregate;
484
+ const exportOwners = /* @__PURE__ */ new Map();
485
+ for (const [claimOwner, claim] of claims) {
486
+ if (!aggregate) aggregate = {
487
+ importId: claim.importId,
488
+ referenceKey: claim.referenceKey,
489
+ exportNames: []
490
+ };
491
+ else if (aggregate.importId !== claim.importId || aggregate.referenceKey !== claim.referenceKey) throw new Error(`[vite-rsc] conflicting server reference identity for '${importId}'`);
492
+ for (const name of claim.exportNames) {
493
+ const existingOwner = exportOwners.get(name);
494
+ if (existingOwner && existingOwner !== claimOwner) throw new Error(`[vite-rsc] server reference '${claim.referenceKey}#${name}' is claimed by both '${existingOwner}' and '${claimOwner}'`);
495
+ exportOwners.set(name, claimOwner);
496
+ }
497
+ }
498
+ assert(aggregate);
499
+ aggregate.exportNames = [...exportOwners.keys()].sort();
500
+ return aggregate;
501
+ }
502
+ var DefaultMap = class extends Map {
503
+ createDefault;
504
+ constructor(createDefault) {
505
+ super();
506
+ this.createDefault = createDefault;
507
+ }
508
+ get(key) {
509
+ if (super.has(key)) return super.get(key);
510
+ const value = this.createDefault(key);
511
+ this.set(key, value);
512
+ return value;
513
+ }
514
+ };
515
+ //#endregion
442
516
  //#region src/plugins/validate-import.ts
443
517
  function validateImportPlugin() {
444
518
  return {
@@ -543,7 +617,7 @@ var RscPluginManager = class {
543
617
  isScanBuild = false;
544
618
  clientReferenceMetaMap = {};
545
619
  clientReferenceGroups = {};
546
- serverReferenceMetaMap = {};
620
+ serverReferences = new ServerReferencesManager(this);
547
621
  serverResourcesMetaMap = {};
548
622
  environmentImportMetaMap = {};
549
623
  stabilize() {
@@ -614,13 +688,13 @@ function vitePluginRscMinimal(rscPluginOptions = {}, manager = new RscPluginMana
614
688
  if (Object.values(manager.clientReferenceMetaMap).find((meta) => meta.referenceKey === parsed.id)) return `export {}`;
615
689
  }
616
690
  if (parsed.type === "server") {
617
- let meta = Object.values(manager.serverReferenceMetaMap).find((meta) => meta.referenceKey === parsed.id);
691
+ let meta = manager.serverReferences.findByReferenceKey(parsed.id);
618
692
  if (!meta) {
619
693
  try {
620
694
  const id = (await this.resolve(parsed.id))?.id ?? parsed.id;
621
695
  if (isFileLoadingAllowed(manager.config, slash(cleanUrl(id)))) await this.environment.transformRequest(parsed.id);
622
696
  } catch {}
623
- meta = Object.values(manager.serverReferenceMetaMap).find((meta) => meta.referenceKey === parsed.id);
697
+ meta = manager.serverReferences.findByReferenceKey(parsed.id);
624
698
  }
625
699
  if (meta) return `export {}`;
626
700
  }
@@ -636,7 +710,7 @@ function vitePluginRscMinimal(rscPluginOptions = {}, manager = new RscPluginMana
636
710
  function vitePluginRsc(rscPluginOptions = {}) {
637
711
  const manager = new RscPluginManager();
638
712
  const buildApp = async (builder) => {
639
- const colors = await import("./picocolors-D_Y2lyXp.js").then((m) => /* @__PURE__ */ __toESM(m.default, 1));
713
+ const colors = await import("./picocolors-BVMUFdce.js").then((m) => /* @__PURE__ */ __toESM(m.default, 1));
640
714
  const logStep = (msg) => {
641
715
  builder.config.logger.info(colors.blue(msg));
642
716
  };
@@ -1317,7 +1391,7 @@ function vitePluginUseClient(useClientPluginOptions, manager) {
1317
1391
  const result = withRollupError(this, transformDirectiveProxyExport)(ast, {
1318
1392
  directive: "use client",
1319
1393
  code,
1320
- keep: !!useClientPluginOptions.keepUseCientProxy,
1394
+ keep: !!(useClientPluginOptions.keepUseClientProxy ?? useClientPluginOptions.keepUseCientProxy),
1321
1395
  runtime: (name, meta) => {
1322
1396
  let proxyValue = `() => { throw new Error("Unexpectedly client reference export '" + ` + JSON.stringify(name) + ` + "' is called on server") }`;
1323
1397
  if (meta?.value) proxyValue = `(${meta.value})`;
@@ -1441,7 +1515,12 @@ function vitePluginUseClient(useClientPluginOptions, manager) {
1441
1515
  const resolved = await this.resolve(source, importer, options);
1442
1516
  if (resolved && resolved.id.includes("/node_modules/")) {
1443
1517
  const rootImporter = path.join(this.environment.config.root, "index.html");
1444
- const resolvedAtRoot = await this.resolve(source, rootImporter, options);
1518
+ let resolvedAtRoot;
1519
+ try {
1520
+ resolvedAtRoot = await this.resolve(source, rootImporter, options);
1521
+ } catch {
1522
+ return;
1523
+ }
1445
1524
  if (!resolvedAtRoot || resolvedAtRoot.id !== resolved.id) return;
1446
1525
  packageSources.set(resolved.id, source);
1447
1526
  return resolved;
@@ -1577,11 +1656,12 @@ function vitePluginUseServer(useServerPluginOptions, manager) {
1577
1656
  const serverEnvironmentName = useServerPluginOptions.environment?.rsc ?? "rsc";
1578
1657
  const browserEnvironmentName = useServerPluginOptions.environment?.browser ?? "client";
1579
1658
  const debug = createDebug("vite-rsc:use-server");
1659
+ const pluginName = "rsc:use-server";
1580
1660
  return [{
1581
- name: "rsc:use-server",
1661
+ name: pluginName,
1582
1662
  transform: { async handler(code, id) {
1583
1663
  if (!code.includes("use server")) {
1584
- delete manager.serverReferenceMetaMap[id];
1664
+ manager.serverReferences.deleteClaim(pluginName, id);
1585
1665
  return;
1586
1666
  }
1587
1667
  let ast = await parseAstAsync(code);
@@ -1597,37 +1677,32 @@ function vitePluginUseServer(useServerPluginOptions, manager) {
1597
1677
  ast = await parseAstAsync(code);
1598
1678
  }
1599
1679
  }
1600
- let normalizedId_;
1601
- const getNormalizedId = () => {
1602
- if (!normalizedId_) {
1603
- if (this.environment.mode === "dev" && id.includes("/node_modules/")) {
1604
- debug(`internal server reference created through a package imported in ${this.environment.name} environment: ${id}`);
1605
- id = cleanUrl(id);
1606
- }
1607
- if (manager.config.command === "build") normalizedId_ = hashString(manager.toRelativeId(id));
1608
- else normalizedId_ = normalizeViteImportAnalysisUrl(manager.server.environments[serverEnvironmentName], id);
1680
+ let serverReference_;
1681
+ const getServerReference = () => {
1682
+ if (!serverReference_) {
1683
+ if (this.environment.mode === "dev" && id.includes("/node_modules/")) debug(`internal server reference created through a package imported in ${this.environment.name} environment: ${id}`);
1684
+ serverReference_ = manager.serverReferences.resolve(id, serverEnvironmentName);
1609
1685
  }
1610
- return normalizedId_;
1686
+ return serverReference_;
1611
1687
  };
1612
1688
  if (this.environment.name === serverEnvironmentName) {
1613
1689
  const transformServerActionServer_ = withRollupError(this, transformServerActionServer);
1614
1690
  const enableEncryption = useServerPluginOptions.enableActionEncryption ?? true;
1615
1691
  const result = transformServerActionServer_(code, ast, {
1616
- runtime: (value, name) => `$$ReactServer.registerServerReference(${value}, ${JSON.stringify(getNormalizedId())}, ${JSON.stringify(name)})`,
1692
+ runtime: (value, name) => `$$ReactServer.registerServerReference(${value}, ${JSON.stringify(getServerReference().referenceKey)}, ${JSON.stringify(name)})`,
1617
1693
  rejectNonAsyncFunction: true,
1618
1694
  encode: enableEncryption ? (value) => `__vite_rsc_encryption_runtime.encryptActionBoundArgs(${value})` : void 0,
1619
1695
  decode: enableEncryption ? (value) => `await __vite_rsc_encryption_runtime.decryptActionBoundArgs(${value})` : void 0
1620
1696
  });
1621
1697
  const output = result.output;
1622
1698
  if (!result || !output.hasChanged()) {
1623
- delete manager.serverReferenceMetaMap[id];
1699
+ manager.serverReferences.deleteClaim(pluginName, id);
1624
1700
  return;
1625
1701
  }
1626
- manager.serverReferenceMetaMap[id] = {
1627
- importId: id,
1628
- referenceKey: getNormalizedId(),
1629
- exportNames: "names" in result ? result.names : result.exportNames
1630
- };
1702
+ manager.serverReferences.replaceClaim(pluginName, id, {
1703
+ ...getServerReference(),
1704
+ exportNames: result.referenceNames
1705
+ });
1631
1706
  const importSource = resolvePackage(`${PKG_NAME}/react/rsc/server`);
1632
1707
  output.prepend(`import * as $$ReactServer from "${importSource}";\n`);
1633
1708
  if (enableEncryption) {
@@ -1640,23 +1715,28 @@ function vitePluginUseServer(useServerPluginOptions, manager) {
1640
1715
  };
1641
1716
  } else {
1642
1717
  if (!hasDirective(ast.body, "use server")) {
1643
- delete manager.serverReferenceMetaMap[id];
1718
+ manager.serverReferences.deleteClaim(pluginName, id);
1644
1719
  return;
1645
1720
  }
1646
1721
  const result = withRollupError(this, transformDirectiveProxyExport)(ast, {
1647
1722
  code,
1648
- runtime: (name) => `$$ReactClient.createServerReference(${JSON.stringify(getNormalizedId() + "#" + name)},$$ReactClient.callServer, undefined, ` + (this.environment.mode === "dev" ? `$$ReactClient.findSourceMapURL,` : "undefined,") + `${JSON.stringify(name)})`,
1723
+ runtime: (name) => `$$ReactClient.createServerReference(${JSON.stringify(getServerReference().referenceKey + "#" + name)},$$ReactClient.callServer, undefined, ` + (this.environment.mode === "dev" ? `$$ReactClient.findSourceMapURL,` : "undefined,") + `${JSON.stringify(name)})`,
1649
1724
  directive: "use server",
1650
1725
  rejectNonAsyncFunction: true
1651
1726
  });
1652
- if (!result) return;
1727
+ if (!result) {
1728
+ manager.serverReferences.deleteClaim(pluginName, id);
1729
+ return;
1730
+ }
1653
1731
  const output = result?.output;
1654
- if (!output?.hasChanged()) return;
1655
- manager.serverReferenceMetaMap[id] = {
1656
- importId: id,
1657
- referenceKey: getNormalizedId(),
1732
+ if (!output?.hasChanged()) {
1733
+ manager.serverReferences.deleteClaim(pluginName, id);
1734
+ return;
1735
+ }
1736
+ manager.serverReferences.replaceClaim(pluginName, id, {
1737
+ ...getServerReference(),
1658
1738
  exportNames: result.exportNames
1659
- };
1739
+ });
1660
1740
  const name = this.environment.name === browserEnvironmentName ? "browser" : "ssr";
1661
1741
  const importSource = resolvePackage(`${PKG_NAME}/react/${name}`);
1662
1742
  output.prepend(`import * as $$ReactClient from "${importSource}";\n`);
@@ -1672,7 +1752,7 @@ function vitePluginUseServer(useServerPluginOptions, manager) {
1672
1752
  map: null
1673
1753
  };
1674
1754
  let code = "";
1675
- for (const meta of Object.values(manager.serverReferenceMetaMap)) {
1755
+ for (const meta of manager.serverReferences.metaMap.values()) {
1676
1756
  const key = JSON.stringify(meta.referenceKey);
1677
1757
  const id = JSON.stringify(meta.importId);
1678
1758
  const exports = meta.exportNames.map((name) => name === "default" ? "default: _default" : name).sort();
package/dist/plugin.d.ts CHANGED
@@ -1,2 +1,2 @@
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-CaLiN8ED.js";
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-DQCCjJl0.js";
2
2
  export { AssetDeps, AssetsManifest, PluginApi, ResolvedAssetDeps, ResolvedAssetsManifest, type RscPluginManager, RscPluginOptions, vitePluginRsc as default, getPluginApi, transformRscCssExport, vitePluginRscMinimal };
package/dist/plugin.js CHANGED
@@ -1,2 +1,2 @@
1
- import { i as vitePluginRscMinimal, n as transformRscCssExport, r as vitePluginRsc, t as getPluginApi } from "./plugin-ByvxS0by.js";
1
+ import { i as vitePluginRscMinimal, n as transformRscCssExport, r as vitePluginRsc, t as getPluginApi } from "./plugin-DbK8rF7n.js";
2
2
  export { vitePluginRsc as default, getPluginApi, transformRscCssExport, vitePluginRscMinimal };
@@ -1,6 +1,6 @@
1
1
  import { a as createServerManifest, o as loadServerAction, r as createClientManifest, s as setRequireModule } from "../rsc-C3UdJLOW.js";
2
2
  import { a as registerClientReference, i as decodeReply, n as decodeAction, o as registerServerReference, r as decodeFormState, t as createTemporaryReferenceSet } from "../server-ZBjqNTqU.js";
3
- import { t as OnClientReference } from "../client-reference-DT0MYgPn.js";
3
+ import { t as OnClientReference } from "../client-reference-DR15qkcN.js";
4
4
  //#region src/rsc/server.d.ts
5
5
  declare function renderToReadableStream<T>(data: T, options?: object, extraOptions?: {
6
6
  /**
@@ -1,5 +1,5 @@
1
1
  import { d as RenderToReadableStreamOptions, u as PrerenderResult } from "../index-C5IY2S-e.js";
2
- import { t as OnClientReference } from "../client-reference-DT0MYgPn.js";
2
+ import { t as OnClientReference } from "../client-reference-DR15qkcN.js";
3
3
  //#region src/rsc/static.d.ts
4
4
  declare function prerender<T>(data: T, options?: RenderToReadableStreamOptions, extraOptions?: {
5
5
  /**
package/dist/ssr.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { s as EncodeFormActionCallback } from "./index-C5IY2S-e.js";
2
2
  import { createServerConsumerManifest, setRequireModule } from "./core/ssr.js";
3
- import { i as ResolvedAssetDeps } from "./plugin-CaLiN8ED.js";
3
+ import { i as ResolvedAssetDeps } from "./plugin-DQCCjJl0.js";
4
4
  import { callServer, createFromReadableStream, createServerReference, createTemporaryReferenceSet, encodeReply, findSourceMapURL } from "./react/ssr.js";
5
5
  //#region src/ssr.d.ts
6
6
  /**
@@ -1,2 +1,2 @@
1
- import { a as extractIdentifiers, c as validateNonAsyncFunction, d as transformProxyExport, f as TransformWrapExportFilter, g as transformHoistInlineDirective, h as findDirectives, i as transformServerActionServer, l as TransformProxyExportOptions, m as transformWrapExport, n as TransformExpandExportAllOptions, o as extractNames, p as TransformWrapExportOptions, r as transformExpandExportAll, s as hasDirective, t as TransformExpandExportAllContext, u as transformDirectiveProxyExport } from "../index-BjJe9jqG.js";
1
+ import { a as extractIdentifiers, c as validateNonAsyncFunction, d as transformProxyExport, f as TransformWrapExportFilter, g as transformHoistInlineDirective, h as findDirectives, i as transformServerActionServer, l as TransformProxyExportOptions, m as transformWrapExport, n as TransformExpandExportAllOptions, o as extractNames, p as TransformWrapExportOptions, r as transformExpandExportAll, s as hasDirective, t as TransformExpandExportAllContext, u as transformDirectiveProxyExport } from "../index-COzKOTR1.js";
2
2
  export { TransformExpandExportAllContext, TransformExpandExportAllOptions, TransformProxyExportOptions, TransformWrapExportFilter, TransformWrapExportOptions, extractIdentifiers, extractNames, findDirectives, hasDirective, transformDirectiveProxyExport, transformExpandExportAll, transformHoistInlineDirective, transformProxyExport, transformServerActionServer, transformWrapExport, validateNonAsyncFunction };
@@ -3,6 +3,59 @@ import { a as validateNonAsyncFunction, i as hasDirective, n as extractIdentifie
3
3
  import MagicString from "magic-string";
4
4
  import { walk } from "estree-walker";
5
5
  //#region src/transforms/hoist.ts
6
+ /**
7
+ * Turns an inline directive function into a module-level registered function.
8
+ * Conceptually:
9
+ *
10
+ * ```js
11
+ * function Component() {
12
+ * const x = 1
13
+ * async function action(y) {
14
+ * "use server"
15
+ * return x + y
16
+ * }
17
+ * }
18
+ * ```
19
+ *
20
+ * becomes:
21
+ *
22
+ * ```js
23
+ * function Component() {
24
+ * const x = 1
25
+ * const action = __RUNTIME__($$hoist_0_action).bind(null, x)
26
+ * }
27
+ * export async function $$hoist_0_action(x, y) {
28
+ * "use server"
29
+ * return x + y
30
+ * }
31
+ * ```
32
+ *
33
+ * The generated export is `$$hoist_0_action`, so `names` contains
34
+ * `['$$hoist_0_action']` for this example.
35
+ *
36
+ * Here, `__RUNTIME__(...)` represents the registration expression returned by the
37
+ * `runtime` callback. When `encode` and `decode` are provided, the closure
38
+ * captures instead travel as one encoded bound argument:
39
+ *
40
+ * ```js
41
+ * function Component() {
42
+ * const x = 1
43
+ * const action = __RUNTIME__($$hoist_0_action).bind(
44
+ * null,
45
+ * __ENCODE__([x]),
46
+ * )
47
+ * }
48
+ *
49
+ * export async function $$hoist_0_action($$hoist_encoded, y) {
50
+ * const [x] = __DECODE__($$hoist_encoded)
51
+ * "use server"
52
+ * return x + y
53
+ * }
54
+ * ```
55
+ *
56
+ * In this second sketch, `__ENCODE__(...)` and `__DECODE__(...)` likewise
57
+ * represent the expressions returned by those code-generation callbacks.
58
+ */
6
59
  function transformHoistInlineDirective(input, ast, { runtime, rejectNonAsyncFunction, ...options }) {
7
60
  if (!input.endsWith("\n")) input += "\n";
8
61
  const output = new MagicString(input);
@@ -378,11 +431,21 @@ function transformProxyExport(ast, options) {
378
431
  //#endregion
379
432
  //#region src/transforms/server-action.ts
380
433
  function transformServerActionServer(input, ast, options) {
381
- if (hasDirective(ast.body, "use server")) return transformWrapExport(input, ast, options);
382
- return transformHoistInlineDirective(input, ast, {
434
+ if (hasDirective(ast.body, "use server")) {
435
+ const result = transformWrapExport(input, ast, options);
436
+ return {
437
+ ...result,
438
+ referenceNames: result.exportNames
439
+ };
440
+ }
441
+ const result = transformHoistInlineDirective(input, ast, {
383
442
  ...options,
384
443
  directive: "use server"
385
444
  });
445
+ return {
446
+ ...result,
447
+ referenceNames: result.names
448
+ };
386
449
  }
387
450
  //#endregion
388
451
  //#region src/transforms/expand-export-all.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitejs/plugin-rsc",
3
- "version": "0.5.30",
3
+ "version": "0.5.31",
4
4
  "description": "React Server Components (RSC) support for Vite.",
5
5
  "keywords": [
6
6
  "react",
@@ -28,35 +28,24 @@
28
28
  "./transforms": "./dist/transforms/index.js",
29
29
  "./*": "./dist/*.js"
30
30
  },
31
- "scripts": {
32
- "test": "vitest",
33
- "test-e2e": "playwright test --project=chromium",
34
- "test-e2e-ci": "playwright test",
35
- "tsc": "tsc -b ./tsconfig.json ./e2e/tsconfig.json ./examples/*/tsconfig.json",
36
- "tsc-dev": "pnpm tsc --watch --preserveWatchOutput",
37
- "dev": "tsdown --sourcemap --watch src",
38
- "build": "tsdown",
39
- "prepack": "tsdown"
40
- },
41
31
  "dependencies": {
42
32
  "@rolldown/pluginutils": "^1.0.1",
43
33
  "es-module-lexer": "^2.3.1",
44
34
  "estree-walker": "^3.0.3",
45
35
  "magic-string": "^0.30.21",
46
- "srvx": "^0.11.22",
36
+ "srvx": "^0.12.4",
47
37
  "strip-literal": "^3.1.0",
48
38
  "turbo-stream": "^3.2.0",
49
39
  "vitefu": "^1.1.3"
50
40
  },
51
41
  "devDependencies": {
52
42
  "@hiogawa/utils": "^1.7.0",
53
- "@playwright/test": "^1.61.1",
43
+ "@playwright/test": "^1.62.0",
54
44
  "@tsconfig/strictest": "^2.0.8",
55
45
  "@types/estree": "^1.0.9",
56
46
  "@types/node": "^24.13.3",
57
47
  "@types/react": "^19.2.17",
58
48
  "@types/react-dom": "^19.2.3",
59
- "@vitejs/plugin-react": "workspace:*",
60
49
  "@vitejs/test-dep-cjs-and-esm": "./test-dep/cjs-and-esm",
61
50
  "@vitejs/test-dep-cjs-falsy-primitive": "./test-dep/cjs-falsy-primitive",
62
51
  "picocolors": "^1.1.1",
@@ -64,7 +53,8 @@
64
53
  "react-dom": "^19.2.8",
65
54
  "react-server-dom-webpack": "^19.2.8",
66
55
  "tinyexec": "^1.2.4",
67
- "tsdown": "^0.22.7"
56
+ "tsdown": "^0.22.14",
57
+ "@vitejs/plugin-react": "6.0.4"
68
58
  },
69
59
  "peerDependencies": {
70
60
  "react": "*",
@@ -87,5 +77,14 @@
87
77
  "type": "incompatible",
88
78
  "reason": "Uses Vite-specific APIs"
89
79
  }
80
+ },
81
+ "scripts": {
82
+ "test": "vitest",
83
+ "test-e2e": "playwright test --project=chromium",
84
+ "test-e2e-ci": "playwright test",
85
+ "tsc": "tsc -b ./tsconfig.json ./e2e/tsconfig.json ./examples/*/tsconfig.json",
86
+ "tsc-dev": "pnpm tsc --watch --preserveWatchOutput",
87
+ "dev": "tsdown --sourcemap --watch src",
88
+ "build": "tsdown"
90
89
  }
91
- }
90
+ }