Let's look at how to set up React Compiler 1.0 in your build pipeline to eliminate manual useMemo and useCallback boilerplate while keeping your components lightning fast.
What you'll learn:
- How to install and wire up
babel-plugin-react-compiler - Configuring ESLint rules to catch React rule violations early
- Managing incremental rollouts in large, existing codebases
- When you still need manual memoization as an escape hatch
Installing the Compiler and Babel Plugin
React Compiler operates at build time, analyzing your Control Flow Graph (CFG) via Babel to automatically memoize components and hooks. To get started, pull down the stable package with exact version pinning to avoid unexpected build shifts.
npm install --save-dev --save-exact babel-plugin-react-compiler@latest
Once installed, hook it into your Babel configuration. If you are using Next.js, Expo, or Vite, modern boilerplates often come with built-in presets or flags to turn this on instantly.
// babel.config.js
module.exports = {
plugins: [
['babel-plugin-react-compiler', {
// Target specific environments if you aren't on React 19 yet
target: '18'
}]
],
};
Speed Note: Pinning your exact compiler version with
--save-exactis crucial. Because minor compiler updates can alter memoization output, unpinned ranges might cause subtle effect timing shifts if your codebase has implicit dependency bugs.
Enforcing the Rules of React via ESLint
The compiler relies entirely on your code following the standard Rules of React. If your components mutate state during render or violate purity, the compiler's auto-memoization can trigger infinite loops or stale UI states.
Upgrade your ESLint setup to catch these issues before they hit production builds.
npm install --save-dev eslint-plugin-react-hooks@latest
Update your flat config to load the recommended preset:
// eslint.config.js
import reactHooks from 'eslint-plugin-react-hooks';
import { defineConfig } from 'eslint/config';
export default defineConfig([
reactHooks.configs.flat.recommended,
]);
Gotcha: If you previously installed
eslint-plugin-react-compilerseparately, remove it. The officialeslint-plugin-react-hookspackage now bundles these compiler-powered lint checks directly.
Handling Existing Code and Escape Hatches
You do not need to strip out existing useMemo or useCallback calls when adopting the compiler. In fact, removing them blindly can change compilation output unexpectedly. Keep them in place for legacy components, and treat them as an explicit escape hatch.
import { useState, useMemo } from 'react';
// The compiler automatically memoizes this component,
// but we keep useMemo here to stabilize a reference for an external effect.
export function DataDashboard({ rawData, filter }: { rawData: any[]; filter: string }) {
const processedItems = useMemo(() => {
return rawData.filter(item => item.category === filter);
}, [rawData, filter]);
const [selectedIndex, setSelectedIndex] = useState(0);
return (
<div>
<p>Showing {processedItems.length} items</p>
</div>
);
}
Tip: Use
useMemoanduseCallbackspecifically when passing stable references down to third-party hooks or library effects where exact reference equality prevents excessive re-firing.
Incremental Adoption in Large Codebases
If you manage a massive legacy app, flipping the compiler on globally can expose hidden bugs buried in old components. Use file-level gating or directory exclusions to roll it out incrementally.
// babel.config.js (Targeted rollout)
module.exports = {
plugins: [
['babel-plugin-react-compiler', {
sources: (filename) => {
// Only compile files inside the new feature directory for now
return filename.indexOf('src/features/dashboard') !== -1;
},
}],
],
};
Test your user flows thoroughly after enabling each directory. Focus particularly on components that rely heavily on useEffect synchronization, as fixing subtle rule violations early prevents production regressions.
Summary
React Compiler 1.0 takes the guesswork out of performance tuning by handling memoization at build time. By pairing the compiler plugin with strict ESLint checks and incremental rollouts, you can modernize your frontend architecture safely.
Next Steps:
- Add
babel-plugin-react-compilerto a staging branch and run your end-to-end test suite. - Upgrade
eslint-plugin-react-hooksto catch purity violations before compilation. - Pilot the compiler on a single isolated feature directory before rolling it out app-wide.