Repository navigation
[Due for payment 2026-11-05] [DX] Consolidate on the OXC React Compiler and delete the Babel one #101668
Description
Background
Bundle native builds with Re.Pack + OXC transform pipeline moved native app source onto the same OXC loader the web build already uses. Native and web now run the same Rust React Compiler.
Jest is the only consumer of the Babel React Compiler left. jest.config.js:24 routes to babel-jest unless the run is a Reassure perf run, which already uses config/babel/oxcJestTransformer.js.
Problem
Because two compilers are still in play, we maintain a whole layer of tooling whose only job is to reconcile them:
config/reactCompiler/checkBoth.mjsruns OXC, then runs Babel again on every file OXC memoized.scripts/lint/processors/ReactCompilerWorker.tscalls that for every linted file, so lint pays for two compilers.scripts/react-compiler-divergence-audit.tsexists solely to find files where the two disagree.scripts/react-compiler-compliance-check.tsenforces a third rule — "no new divergence" — on top of compile and no-regress, and carries an inline Babel analysis plus a dynamic-import workaround that exists only so Jest can import the module without pulling in ESM-onlyoxc-transform-react.REACT_COMPILER_FINGERPRINT_FILESlists both configs plus both checkers, so an edit to either busts the whole lint cache.
Divergence is not just overhead — it is a live bug class. A divergent file ships unmemoized on one platform.
Solution
Make OXC the only React Compiler, then delete everything that exists to compare the two.
- Make
config/babel/oxcJestTransformer.jsthe default Jest transform, not just the perf-run transform. Test files may need to stay onbabel-jestforjest.mockhoisting — confirm and document which. - Drop
babel-plugin-react-compilerfrombabel.config.jsandpackage.json, and deleteconfig/babel/reactCompilerConfig.js. - Delete
config/reactCompiler/checkBoth.mjs,checkWithBabel.mjs, their.d.mtsfiles, andscripts/check-both-compilers-runner.mjs. - Delete
scripts/react-compiler-divergence-audit.tsand itsreact-compiler-divergence-auditnpm script. - Reduce
react-compiler-compliance-checkto a single OXC path: keep "new files must compile" and "modified files must not regress", drop the divergence rule and the inline Babel analysis. - Point
ReactCompilerWorkeratcheckWithOxc.mjsdirectly and trimREACT_COMPILER_FINGERPRINT_FILESto the files that still exist. - Drop the now-stale
buildDependenciesentry forreactCompilerConfig.jsinconfig/repack/rspack.config.mjs:89. - Update the Memoization section of
CLAUDE.mdandcontributingGuides/REACT_COMPILER.md, which both still describe two compilers.
Expected wins
- Lint's React Compiler stage stops running a second compiler per file.
- One less required CI workflow shape:
react-compiler-compliance.ymldrops a compiler and a rule. - Jest stops transforming through Babel, which was measured as roughly half of each Reassure measure job.
- The memoization-divergence bug class disappears.
Sequencing note
babel.config.js still applies the Babel React Compiler on the BUNDLER=metro fallback path. Once the plugin is gone, a Metro fallback build runs unmemoized. Either land this after Metro is removed, or accept that — Metro is a debug escape hatch, not a shipped path. Whoever picks this up should make that call explicitly.
Verification
Full Jest suite green, Reassure baselines unchanged beyond noise, npm run lint clean, and a native + web build that boots with Memo badges visible in React DevTools.
Related
- Parent: [DX] Replace Metro with Re.Pack + a Rust transform pipeline for native builds
- Sibling follow-up: [DX] Remove Metro from the repo
- Context: [Tracking] Use React Compiler to enforce the Rules of React
Requested by elirangoshen as a follow-up on Bundle native builds with Re.Pack + OXC transform pipeline.
Activity
elirangoshen commentedon Sep 23, 2026
Suggestion: split this into three PRs, since the checklist cannot all land at once. Happy to do it another way if you'd rather.
The blocker is the sequencing note: HybridApp release builds still bundle through Metro, so
babel-plugin-react-compileris what memoizes them. Delete it before HybridApp moves onto Re.Pack and release builds ship unmemoized.1. Consolidate on the OXC React Compiler — #102081 (draft)
Makes the OXC transform the default for Jest and deletes everything that existed only to reconcile two compilers. The Metro lane is untouched, so this is safe on its own.
2. Move HybridApp bundling onto Re.Pack (Mobile-Expensify)
Mobile-Expensify/Android/build.gradlehas nocliFile/bundleCommandoverride andtools/react-native-xcode.shstill points at React Native's CLI, so both default to Metro. Pointing them at Rock is what lets the Babel plugin go.3. Remove
babel-plugin-react-compiler(App)Drops the plugin from
babel.config.jsandpackage.json, inlines and deletesconfig/babel/reactCompilerConfig.js, and removes itsbuildDependenciesentry. Only safe after 2.As far as I can tell only 3 depends on 2, and 1 is independent and could merge at any point.
One correction to the checklist: the
buildDependenciesentry forreactCompilerConfig.jsis not stale today.config/babel/oxcReactCompilerConfig.jsrequires that file, so the entry is a real dependency until 3 removes both.elirangoshen commentedon Sep 23, 2026
Suggestion: split this into three PRs, since the checklist cannot all land at once.
The blocker is the sequencing note: HybridApp release builds still bundle through Metro, so
babel-plugin-react-compileris what memoizes them. Delete it before HybridApp moves onto Re.Pack and release builds ship unmemoized.This is the 3 pr's Id suggest to do:
**1. Consolidate on the OXC React Compiler — #102081 **
Makes the OXC transform the default for Jest and deletes everything that existed only to reconcile two compilers. The Metro lane is untouched, so this is safe on its own.
2. Move HybridApp bundling onto Re.Pack (Mobile-Expensify)
Mobile-Expensify/Android/build.gradlehas nocliFile/bundleCommandoverride andtools/react-native-xcode.shstill points at React Native's CLI, so both default to Metro. Pointing them at Rock is what lets the Babel plugin go.3. Remove
babel-plugin-react-compiler(App)Drops the plugin from
babel.config.jsandpackage.json, inlines and deletesconfig/babel/reactCompilerConfig.js, and removes itsbuildDependenciesentry. Only safe after 2.What do you think ? @roryabraham
roryabraham commentedon Sep 23, 2026
Sounds good, except I think 1 and 2 can happen in parallel, and I would finish 2 before cleaning up and consolidating React Compiler-related CI/validation scripts and configs:
scripts/react-compiler-*config/reactCompilerconfig/babelscripts/lint/processors/ReactComplier*melvin-bot commentedon Sep 28, 2026
Triggered auto assignment to @rlinoz, see https://stackoverflow.com/c/expensify/questions/7972 for more details.
Julesssss commentedon Sep 30, 2026
We think this PR introduced this bug.
elirangoshen commentedon Sep 30, 2026
Ill check it tomorrow
33 remaining items
melvin-bot commentedon Oct 20, 2026
Triggered auto assignment to @mallenexpensify (
Awaiting Payment)[-][Due for payment 2026-10-07] [DX] Consolidate on the OXC React Compiler and delete the Babel one[/-][+][DX] Consolidate on the OXC React Compiler and delete the Babel one[/+]mallenexpensify commentedon Oct 21, 2026
Please comment and tag me if/when payment is due, thx
[-][DX] Consolidate on the OXC React Compiler and delete the Babel one[/-][+][Due for payment 2026-11-05] [DX] Consolidate on the OXC React Compiler and delete the Babel one[/+]melvin-bot commentedon Oct 29, 2026
@aimane-chnaif
The solution for this issue has been 🚀 deployed to production 🚀 in version 9.5.24-8 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:
If no regressions arise, payment will be issued on 2026-11-05. 🎊
The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the Contributor+ Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]. If no checklist is needed for this issue, you can click: [no checklist button]