Skip to content

fix(rsc): drop Server Function source from client sourcemaps - #1497

Draft
james-elicx wants to merge 2 commits into
vitejs:mainfrom
james-elicx:fix/rsc-client-action-sourcemap
Draft

james-elicx wants to merge 2 commits into
vitejs:mainfrom
james-elicx:fix/rsc-client-action-sourcemap

Conversation

@james-elicx

@james-elicx james-elicx commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Description

In a production build with client sourcemaps enabled (build.sourcemap: true or --sourcemap), the browser .js.map publishes the full source of any "use server" module imported by a client component. That includes code paths and constants that only ever run on the server.

In the browser environment, rsc:use-server replaces the module with createServerReference() proxies, so the implementation never reaches browser JavaScript. But the proxy's transform map (output.generateMap({ hires: 'boundary' })) maps it back to the original module. The bundler then embeds that module in the chunk map's sourcesContent.

This PR returns { mappings: '' } for the proxy in browser builds. Dev builds and the SSR environment keep generateMap(...), so dev source locations (findSourceMapURL) are unaffected. This matches Next.js, which drops the original spans when compiling server actions for the client layer in production but keeps them in development and server builds (the is_react_server_layer || is_development checks in crates/next-custom-transforms/src/transforms/server_actions.rs, from vercel/next.js#76157). Next.js's matching e2e test is "should not expose action content in sourcemaps" in test/e2e/app-dir/actions/app-action.test.ts.

Draft: blocked on Rolldown

The new e2e test (source map build in e2e/source-map.test.ts) builds examples/source-map with --sourcemap. It then checks that no client map carries a "use server" module's source, while the client component importing the action keeps its own.

Without this change With this change
Vite 7 (Rollup) fails passes
Vite 8 (Rolldown 1.2.12) fails fails

Rollup documents map: { mappings: '' } as the way to return a transform with no sourcemap. It builds sources and sourcesContent only from files that traced mappings reach, so the module drops out. Rolldown doesn't support that yet:

  • normalize_transform_sourcemap fills an empty map's sources and sourcesContent with the module id and its pre-transform code.
  • collapse_sourcemaps copies sources and sourcesContent wholesale from the first map in the chain, whether or not any mapping reaches them. So an earlier transform's map (for example TypeScript stripping) keeps the original even when a later transform returns { mappings: '' } or no map.

Feature request on Rolldown: rolldown/rolldown#11176

I'll mark this ready once Rolldown supports it. The Vite 7 CI job should already pass with this change.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant