Describe the bug
@vitejs/plugin-rsc's rsc:use-client transform throws
Error: unsupported ExportAllDeclaration
at transformProxyExport (.../plugin-rsc/dist/transforms/index.js:338:90)
for any "use client" module that re-exports another module with export * from '...' or export * as Ns from '...'. This is a common pattern in real-world React code (barrel files for groups of client components), and it ships in the Next.js rsc-basic e2e suite (components/export-all/), so any Vite/RSC framework that aims to be a drop-in replacement for the Next.js App Router build pipeline hits this immediately.
Reproduction
A "use client" file containing:
"use client";
export * from "./one";
triggers the error during the RSC environment build.
Source
The throw is unconditional once ignoreExportAllDeclaration is false (which is the default for the use-client path):
// dist/transforms/index.js around line 338
if (!options.ignoreExportAllDeclaration && node.type === "ExportAllDeclaration")
throw new Error("unsupported ExportAllDeclaration");
There is no public option on the use-client plugin to flip this, and the * case isn't routed through the proxy generator.
Expected behavior
export * from '...' and export * as Ns from '...' should be handled inside a "use client" boundary. Two reasonable options:
- Resolve at transform time — enumerate the target module's named exports and emit one client-reference proxy per name (skipping
default, matching ESM export * semantics).
- Forward at module-graph time — leave the declaration in place and let the bundler resolve it natively after the proxies for the target module are emitted. This is conceptually what Next.js's flight loader does: it falls back to
assumedSourceType === "module" when clientRefs contains * so webpack handles the re-export (next-flight-loader/index.ts).
Current workaround
In cloudflare/vinext we added a pre-pass plugin that runs before rsc:use-client in the RSC environment, parses each "use client" module, and rewrites:
export * from '...' → export { a, b, c, ... } from '...' (named exports enumerated by resolving the target via this.resolve + this.load, recursing through chained export *)
export * as Ns from '...' → import * as Ns from '...'; export { Ns };
Tracking PR: cloudflare/vinext#1373
Plugin source: https://github.com/cloudflare/vinext/blob/fix/issue-1352-use-client-export-all/packages/vinext/src/plugins/use-client-export-all.ts
This works for relative imports inside the user's graph but cannot handle bare-specifier targets that the RSC plugin's package-source path will eventually proxy — those still hit the error.
System info
@vitejs/plugin-rsc@0.5.26 on Vite 8 / Rolldown.
Describe the bug
@vitejs/plugin-rsc'srsc:use-clienttransform throwsfor any
"use client"module that re-exports another module withexport * from '...'orexport * as Ns from '...'. This is a common pattern in real-world React code (barrel files for groups of client components), and it ships in the Next.jsrsc-basice2e suite (components/export-all/), so any Vite/RSC framework that aims to be a drop-in replacement for the Next.js App Router build pipeline hits this immediately.Reproduction
A
"use client"file containing:triggers the error during the RSC environment build.
Source
The throw is unconditional once
ignoreExportAllDeclarationis false (which is the default for the use-client path):There is no public option on the use-client plugin to flip this, and the
*case isn't routed through the proxy generator.Expected behavior
export * from '...'andexport * as Ns from '...'should be handled inside a"use client"boundary. Two reasonable options:default, matching ESMexport *semantics).assumedSourceType === "module"whenclientRefscontains*so webpack handles the re-export (next-flight-loader/index.ts).Current workaround
In cloudflare/vinext we added a pre-pass plugin that runs before
rsc:use-clientin the RSC environment, parses each"use client"module, and rewrites:export * from '...'→export { a, b, c, ... } from '...'(named exports enumerated by resolving the target viathis.resolve+this.load, recursing through chainedexport *)export * as Ns from '...'→import * as Ns from '...'; export { Ns };Tracking PR: cloudflare/vinext#1373
Plugin source: https://github.com/cloudflare/vinext/blob/fix/issue-1352-use-client-export-all/packages/vinext/src/plugins/use-client-export-all.ts
This works for relative imports inside the user's graph but cannot handle bare-specifier targets that the RSC plugin's package-source path will eventually proxy — those still hit the error.
System info
@vitejs/plugin-rsc@0.5.26on Vite 8 / Rolldown.