Lauren Tan, Joe Savona and Mofei Zhang announced React Compiler 1.0 on October 7, 2025, the first stable release. The compiler runs at build time and adds memoization to your components and hooks without code changes. It works for React and React Native, and with React 17 and up.
The project took almost a decade. The team tried Prepack in 2017, Xuan Huang demoed a new approach in 2021, and the beta shipped on October 21, 2024. Along the way the team rewrote the compiler around a control flow graph, which lets it analyze data flow and mutation in detail.
What Meta measured
- faster initial loads and navigations, at most
- 12%
- faster on certain interactions
- 2.5x+
- change in memory use
- 0
Those numbers come from the Meta Quest Store. Sanity Studio and Wakelet published their own case studies. The team adds that your results will vary, so treat 12% as an upper bound and measure your own app.
The compiler can memoize code that you can't memoize by hand, such as values computed after an early return:
export default function ThemeProvider(props) {
if (!props.children) return null;
// Hooks rules forbid useMemo here. The compiler memoizes it anyway.
const theme = mergeTheme(props.theme, use(ThemeContext));
return <ThemeContext value={theme}>{props.children}</ThemeContext>;
}
Step 1: lint before you compile
The compiler's checks ship as lint rules in eslint-plugin-react-hooks, and they don't need the compiler installed. The team recommends the upgrade for any React app, and I agree. If you use the old eslint-plugin-react-compiler, delete it.
// eslint.config.js
import reactHooks from "eslint-plugin-react-hooks";
import { defineConfig } from "eslint/config";
export default defineConfig([reactHooks.configs.flat.recommended]);
Three rules catch the most real bugs. set-state-in-render finds render loops, set-state-in-effect flags expensive work in effects, and refs blocks reading refs during render. The team says these checks often expose latent bugs. Fix them first. Code that breaks the Rules of React is code the compiler may skip or change in ways you didn't expect.
Step 2: compile one directory
Pin the exact version. The team warns that future releases may change how they memoize, and an effect that depends on a memoized value can then fire more or less often.
npm install --save-dev --save-exact babel-plugin-react-compiler@latest
Then scope it with Babel overrides:
// babel.config.js
module.exports = {
overrides: [
{
test: "./src/features/checkout/**/*.{js,jsx,ts,tsx}",
plugins: ["babel-plugin-react-compiler"],
},
],
};
Pick a directory with heavy derived values, frequent re-renders and good test coverage. Skip code that mutates objects in place, or the subscription hook your team avoids touching. If one component misbehaves, add "use no memo" at the top of its body to exclude it while you investigate.
For tighter control, compilationMode: "annotation" compiles only functions that start with "use memo".
Step 3: gate it in production
The gating option compiles both versions and picks one at runtime through your feature flag system:
["babel-plugin-react-compiler", {
gating: {
source: "ReactCompilerFeatureFlags",
importSpecifierName: "isCompilerEnabled",
},
}]
isCompilerEnabled() returns your flag value. With it you can A/B test the compiler on 5% of users, compare your Core Web Vitals, and turn it off without a deploy.
What to do with useMemo and useCallback
| Code | Team guidance |
|---|---|
| New components | Rely on the compiler. Use useMemo or useCallback only where you need exact control |
| Existing memoization | Leave it, or test with care before removing it, since removal can change compiled output |
| Memoized value used as an effect dependency | Keep useMemo as the escape hatch |
Resist the cleanup PR that strips useCallback from the repo. It changes the compiler's output and buys you nothing you can measure.
Your build tool
New apps can start with the compiler on: Expo SDK 54 enables it by default, and create-vite and create-next-app offer compiler templates. The compiler runs as a Babel plugin today. The team is building an swc plugin with Kang Dongyoon, still experimental, and says it makes Next.js builds with the compiler much faster on 15.3.1 or later. Oxc support is in progress. Vite users add the Babel plugin to vite-plugin-react.
React 17 and 18 apps set a target in the compiler config and add react-compiler-runtime as a dependency.
This week
- Upgrade
eslint-plugin-react-hooks, turn onrecommended, and count the violations. That number sizes the rollout. - Install the compiler with
--save-exactand compile one directory behind the gating flag. - Record an interaction trace on that directory before and after, on a mid-range phone.
- Leave existing
useMemocalls alone until the compiled build has run in production for a few weeks.
Volodymyr Chornous

