[Bug]: jsc.transform.reactCompiler drops source-map mappings for compiled component/hook bodies
System Info
npmPackages: @rspack/core: 2.1.10 @rsbuild/core: 2.1.13 @rsbuild/plugin-react: 2.1.0 @rsbuild/plugin-babel: 2.0.1 react: 19.2.8 react-dom: 19.2.8 babel-plugin-react-compiler: 1.0.0
Details
Warning: AI SLOP BELOW (I don't have the time to do a proper issue report, hoping this can help a little, I will use @rsbuild/plugin-babel for the time being, which works fine, don't hesitate to close this if something is wrong, but the issue is real)
================================
Enabling React Compiler through jsc.transform.reactCompiler (builtin:swc-loader, typically via Rsbuild pluginReact({ reactCompiler: true })) produces a valid but incomplete JavaScript source map.
Compiled React components and custom hooks retain mappings only for tokens the transform does not rewrite (typically the import list and the function signature). Mappings for the compiled function body are almost entirely missing. Non-React modules in the same generated chunk still map correctly.
This is not a missing .map file, a failed upload, or the old cheap-* / columns: false issue (#6793). We use devtool / output.sourceMap.js: "hidden-source-map" (full maps with columns). SourceMap.findEntry(generatedLine, generatedColumn) returns an original location for untransformed code in the same file, and returns nothing for columns that belong to a compiled body. Error trackers that do an exact lookup therefore report those frames as unmapped (e.g. AppSignal :4294967295:4294967295).
The compiler does run: the compiled output is larger and react/compiler-runtime is present in the graph. This is a source-map emission / composition bug, not a skipped transform.
Quantitative check on a production chunk (VLQ walk of mappings + module.SourceMap.findEntry):
| Original source | reactCompiler: true (SWC) |
reactCompiler off |
Babel babel-plugin-react-compiler instead of SWC |
|---|---|---|---|
custom hook (~80 LOC, useState + useCallback + async I/O) |
1 mapping (signature line only) | ~170 (full original line span) | ~170 (full original line span) |
| function component (~70 LOC) | 4 mappings (import line only) | ~140 | ~300 (body + compiler names such as _c) |
non-React .ts module in the same chunk |
full-file mappings | unchanged | unchanged |
On that chunk, hundreds of app .ts/.tsx sources had < 10 % of the mapping count they have with the compiler disabled.
Controls:
reactCompiler: false— body mappings restored.- Disable SWC
reactCompiler, runbabel-plugin-react-compilerfirst (@rsbuild/plugin-babel,sourceMaps: true) — body mappings restored, compiler still active.
The Babel compiler can emit usable locations. jsc.transform.reactCompiler does not compose them into the loader source map.
Expected: generated positions that originated from a compiled function body map back to the original .tsx/.ts line/column, the same way builtin:swc-loader does without reactCompiler.
Reproduce link
No response
Reproduce Steps
(Still AI slop, I didn't test the reproduction steps)
- Scaffold a React + TypeScript Rsbuild app (
npm create rsbuild@latest, React, TypeScript). - Enable the SWC React Compiler and a full JS source map:
import { defineConfig } from "@rsbuild/core";
import { pluginReact } from "@rsbuild/plugin-react";
export default defineConfig({
output: {
sourceMap: { js: "hidden-source-map" },
},
plugins: [
pluginReact({
reactCompiler: true,
}),
],
});- Add a custom hook (plain
.ts) that usesuseState/useCallbackand an async call, and a.tsxcomponent that calls that hook from an event handler. Keep a non-React.tshelper in the same module graph (no hooks, no JSX). npx rsbuild build --mode=production.- Open the emitted
dist/static/js/**/*.js.mapwhosesourcesinclude the hook and the component. Decodemappings(or usenew (require("node:module").SourceMap)(payload).findEntry(line, column)). - Observe: the hook/component have mappings only on the import/signature lines;
findEntryat a column inside the compiled body is unmapped. The non-React helper in the same map still resolves. - Repeat with
reactCompiler: false(or withbabel-plugin-react-compilerinstead ofjsc.transform.reactCompiler). Body mappings come back.
Source: web-infra-dev/rspack