Trust is earned, not given

A different perspective

2026-06-09 · Projects

React.js, part 19: the React Compiler in production — the eslint plugin, bailouts, and measuring the win

Part 19from the React.js series · 20 parts in all

Turning on an optimizing compiler is the kind of change that either does nothing or does something surprising. Part 19 is the production checklist for the React Compiler: enabling it without breaking behavior, finding the code it silently skipped, and proving the result.

Enable it, then read the linter

npm i -D babel-plugin-react-compiler eslint-plugin-react-compiler
// eslint.config.js
import reactCompiler from 'eslint-plugin-react-compiler';

export default [
  { plugins: { 'react-compiler': reactCompiler },
    rules: { 'react-compiler/react-compiler': 'error' } },
];

The compiler only optimizes code it can prove pure, so the eslint rule is the real instrument: every warning is a function the compiler is going to bail out of, left running exactly as it does today. Fixing those warnings is what turns the compiler from "on" into "effective".

The bailouts that show up most

Measure, do not assume

The compiler reduces wasted renders; it does not reduce the work of the renders that happen. So measure both:

// 1. Render counts, per component, in a real interaction.
<Profiler id="Cart" onRender={(id, phase, actualDuration) =>
  series.push({ id, phase, ms: actualDuration })}>
  <Cart />
</Profiler>

// 2. Whether memoized props are now stable (the compiler's actual win):
//    a child wrapped in React.memo that used to re-render on every parent
//    render should now re-render only when its inputs change.

Roll it out behind a flag if you can, compare interaction timings on a slow device rather than a fast dev machine, and keep the useMemo calls that express a real cache boundary even after the compiler handles the incidental ones. Next: where React is going — the Activity component and rendering trees that are not on screen.