React Compiler: The Repo That Turns UI Code Into a Language

Inside `facebook/react`, the next frontier is not rendering. It is compile-time analysis that infers reactivity, automates memoization, and treats components like code to be optimized, not just executed.

10 min read • View on GitHub • More from facebook

A wide black-ink editorial scene of JSX pages entering a mechanical press and emerging as a cleaner, optimized component sheet. The machine has distinct stages that suggest parsing, analysis, and output, explaining that React now rewrites UI code before it runs.
React Compiler turns ordinary components into something the toolchain can reason about, optimize, and re-emit.

I like to describe this as “referentially transparent UI.” Which is to say your user interface is generally a pure function of some set of inputs, and it emits the same kind of virtual DOM structure every single time for some given data input.

Pete Hunt, Engineering Manager at Instagram, React Core Team Member · React: Facebook's Functional Turn on Writing Javascript
Key Takeaways

React spent years teaching developers a simple deal: describe the UI, and React will manage the updates. The compiler changes that deal. In `facebook/react`, the codebase now contains a pipeline that can lower component code into an internal representation, infer reactivity, optimize the result, and write back better JavaScript than most humans would handcraft.

That is a bigger shift than a faster renderer. It moves React from a library you call at runtime to a system that can inspect your code before it runs. The most important performance question is no longer just where to memoize. It is whether the compiler can prove that memoization is needed at all.

Why This Compiler Exists

Manual memoization has always been a tax. It adds noise, spreads performance concerns through the codebase, and fails quietly when the dependency list is wrong. React Compiler exists to absorb that burden, so the system can infer reactive boundaries instead of forcing developers to draw them by hand.

I might add for the sake of discussion, that many systems advertise some kind of reactivity, but they usually require that you set up some kind of point-to-point listeners and won’t work on structured data. This API reacts to any state or property changes, and works with data of any form (as deeply structured as the graph itself) so I think the name is fitting.

Jordan Walke, Creator of React · Our First 50,000 Stars – React Blog

That early idea matters here. React began by reducing wiring work. The compiler extends that same instinct into optimization work, which is why the move feels less like a bolt-on tool and more like a continuation of the original design.

The Pipeline That Changes the Game

The compiler is not a search-and-replace plugin. It is a multi-pass pipeline. Source code is lowered into HIR, analyzed, optimized, and then code-generated back into JavaScript. That structure is what lets React reason about lifetimes, captures, and dependencies instead of only looking at syntax.

The compiler turns component code into a control-flow problem, then uses that model to decide what needs to stay reactive.

The key move is the internal language. HIR is where React stops treating your component as plain syntax and starts treating it as a program with paths, scopes, and data flow. That is why this repo feels like a compiler project, not a fancy lint rule.

HIR Is the Real Story

A hedcut-style portrait of Sebastian Markbåge. The image serves as a human anchor for the compiler work in React and helps connect the pipeline to the people shaping it.

HIR is High-level Intermediate Representation, but the interesting part is not the acronym. It is the choice to model code as a control-flow graph rather than a tree. That lets the compiler track where a variable is born, where it is captured, and where its useful life ends.

A close-up editorial illustration of a control-flow graph drawn like a transit map or circuit board. One path is highlighted from variable birth to capture to optimization, making the hidden lifetime analysis visible.
HIR gives React a map of lifetimes and dependencies, which is what makes automatic optimization possible.

That is the compiler’s advantage over an AST transform. A syntax tree can tell you what the code looks like. A CFG can tell you what the code does over time. React needs the second one if it wants to infer when a closure is stable, when a branch invalidates a value, or when a memoized result is actually safe.

What Gets Automated, and What Still Doesn’t

Old modelReact Compiler modelWhat changes for the developerTrade-off
Write `useMemo` and `useCallback` by handInfer memoization from code structureLess performance boilerplateYou have to trust the compiler's analysis
Patch hot spots with ad hoc tweaksRun multi-pass analysis before outputFewer one-off optimizationsThe mental model shifts from runtime to build time
Search and replace AST pluginsLower to HIR, analyze, optimize, codegenMore precise transformationsThe toolchain becomes more complex
Treat reactivity as a developer choreTreat reactivity as a compiler problemCleaner componentsSome edge cases still need manual reasoning

The compiler is not magic. It will not rescue a component that is fundamentally hard to understand. It does not remove the need for good boundaries, simple data flow, or sane state placement. What it can do is remove a lot of the repetitive work that used to sit on top of those choices.

React’s Old Contract vs Its New Contract

The old contract was simple. You wrote components, then you manually decided where the expensive edges were. The new contract is less visible and more powerful. You still write components, but now the compiler can understand enough of your code to infer which parts are stable, which parts are reactive, and which parts should be rewritten.

React before compilerReact with compilerDeveloper expectationPerformance shape
Manual memoization patternsInference-driven optimizationReason about semantics, not just cachingOptimization moves earlier in the toolchain
Runtime-first performance tuningBuild-time analysis and rewritingWrite code the compiler can understandCheaper updates when dependencies stay stable
More boilerplate around rendersLess boilerplate around closuresFocus on component structurePerformance becomes more systematic
Hand-managed reactive boundariesCompiler-managed reactive boundariesTrust analysis, verify edge casesMore consistent optimization across codebases

This is why the repo feels different now. React still renders UI, but it is also becoming a place where code is interpreted, analyzed, and improved before it ever reaches the browser. That is a language runtime growing a compiler brain.

From BoltJS to Fiber to Compiler

React’s history makes the shift easier to understand. BoltJS and early React were about taming change handlers and making UI updates intelligible. Fiber added scheduling, pausing, and priority. The compiler is the next step, moving optimization into the build itself instead of leaving every performance win to runtime discipline.

That arc matters. It shows a project that keeps rewriting the layer where complexity lives. First it simplified UI updates. Then it made rendering interruptible. Now it is simplifying optimization by letting the compiler carry more of the reasoning load.

Why This Matters Beyond React

The bigger implication is not confined to one framework. React is normalizing the idea that UI code can be statically analyzed, partially rewritten, and optimized with compiler-grade tooling. If that model holds, the next generation of frontend work will look less like manual tuning and more like writing code that is intentionally legible to machines.

That changes what good React code means. It is no longer only code that renders correctly. It is code that a compiler can prove things about, and that is a very different standard.