Skip to content

react({ compiler: true }) captures build.sourcemap in a closure, so under builder.sharedPlugins the last environment's setting applies to every build #1434

Closed

Description

@MichalJZ

Related plugins

Describe the bug

createReactCompilerPlugin (the react({ compiler: true }) path) keeps the sourcemap decision in a closure written by configResolved:

let sourcemap = true;
// ...
configResolved(config) {
  sourcemap = config.command !== "build" || !!config.build.sourcemap;
},

Under builder.sharedPlugins: true one plugin instance serves every environment, and the builder resolves environment configs sequentially, calling configResolved on that shared instance once per environment. The closure therefore ends up holding the last environment's build.sourcemap - for every build.

With the common setup "client sourcemaps on, server sourcemaps off" (client declared first), the compiler transforms client files with sourcemap: false: rolldown reports SOURCEMAP_BROKEN for each file the compiler touched, and the emitted client sourcemaps skip the compiler's transform. In our app the mappings were wrong enough that a component's string resolved to an unrelated asset module instead of its source file, so symbolicated stack traces (Sentry) pointed at wrong files and lines.

Three flips in the reproduction isolate the cause - each produces zero warnings:

change warnings shows
ssr.build.sourcemap: true 0 the captured value is the problem
swap the order of the environments keys (same values) 0 the last-resolved environment wins
remove builder.sharedPlugins 0 separate instances keep their own values

The same transform handler already reads this.environment?.config.consumer, so reading this.environment.config.build.sourcemap there instead of the closure fixes it and removes the dependence on environment declaration order - verified by patching the dist locally: every state in the table above builds with zero warnings, and the client sourcemaps regain the compiler's stage. jsxDevelopment next to it is captured the same way - isProduction rarely differs between environments, but it is the same pattern.

Practical impact: TanStack Start sets builder.sharedPlugins: true, so any Start app using compiler: true with server sourcemaps disabled gets broken client sourcemaps.

Reproduction

https://github.com/MichalJZ/plugin-react-compiler-sourcemap-sharedplugins-repro

Steps to reproduce

npm install
npx vite build

The client build prints [SOURCEMAP_BROKEN] ... (vite:react-compiler) twice. Apply any of the three flips from the table above (the README repeats them) and it prints none.

System Info

  System:
    OS: macOS 26.6.2
  Binaries:
    Node: 24.18.0
    npm: 11.16.0
  npmPackages:
    @vitejs/plugin-react: ^6.1.0 => 6.1.0
    vite: ^8.2.2 => 8.2.2
    oxc-transform-react: ^0.145.0 => 0.145.0

Build-only - vite build, any browser.

Used Package Manager

npm

Logs

[plugin vite:react-compiler] [SOURCEMAP_BROKEN] Sourcemap is likely to be incorrect: a plugin (vite:react-compiler) was used to transform files, but didn't generate a sourcemap for the transformation. Consult the plugin documentation for help: https://rolldown.rs/guide/troubleshooting#warning-sourcemap-is-likely-to-be-incorrect

Validations

  • Follow our Code of Conduct
  • Read the Contributing Guidelines.
  • Read the docs.
  • Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
  • The provided reproduction is a minimal reproducible example of the bug.

Activity

  1. dawNotPoi commented on Aug 24, 2026

    @dawNotPoi

    I can work on this and add a regression test.

  2. added theissue type on Aug 28, 2026
  3. locked and limited conversation to collaborators on Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions