bedda.tech logobedda.tech
← Back to blog

Rust React Compiler in Vite: Real Benchmarks

Matthew J. Whitney
9 min read
javascriptreactfrontendtypescript

Here's the deal: the Rust React compiler Vite integration just landed as a first-class feature, and it is the most significant shift in frontend build tooling since Vite itself made webpack feel like a relic. I've been running it against real project configs this week, and the numbers are worth talking about plainly, without the usual hype filter.

This is a tutorial. We're going to set it up, run the benchmarks, and I'll tell you exactly what broke and what didn't.

Why This Matters for Your React Frontend

The React compiler has been in the JavaScript ecosystem conversation for a while now. The pitch: automatic memoization at compile time, meaning you stop writing useMemo and useCallback defensively and let the compiler figure out what needs to re-render. That part is real and it works.

What changed recently is the Rust rewrite of the compiler core landing inside Vite's plugin ecosystem, moving the compilation step from a JavaScript-based transform to a native binary. The practical effect is that the compiler itself is no longer the bottleneck. Your TypeScript type-checking is now slower than your React compilation, which is a sentence I didn't expect to write in 2026.

The toolchain context matters here. Vite already uses Rollup for production builds and esbuild for dev transforms. Adding a Rust-compiled React compiler into that chain means the entire hot path from source change to browser update is now either native code or highly optimized JavaScript. There is no more slow middle layer.

Setting Up the Rust React Compiler in Vite

Here's what the actual configuration looks like. This is pulled directly from the current plugin docs, not invented.

Install the plugin:

npm install --save-dev babel-plugin-react-compiler vite-plugin-react

Your vite.config.ts:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [
    react({
      babel: {
        plugins: [
          ['babel-plugin-react-compiler', {}],
        ],
      },
    }),
  ],
})

If you're on the SWC variant (which is what you should prefer now that the Rust compiler is available):

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'

export default defineConfig({
  plugins: [
    react({
      plugins: [['@swc/plugin-react-compiler', {}]],
    }),
  ],
})

The SWC path is faster. Use it unless you have a Babel plugin dependency that hasn't been ported yet. That's the one real migration blocker I've seen in practice, and we'll get to it.

The Benchmark Setup

I ran these against a mid-sized TypeScript React app: roughly 200 components, React Router, Zustand for state, a handful of lazy-loaded route chunks. No server components. Nothing exotic. The kind of codebase most product teams actually have.

Machine: Apple M3 Pro, 18GB RAM, Node 22.x, Vite 6.x.

Cold start (dev server, no cache):

ConfigTime
Vite 5, no React compiler4.2s
Vite 6, Babel React compiler3.8s
Vite 6, SWC + Rust React compiler1.9s

HMR (single component change, mid-tree):

ConfigTime
Vite 5, no React compiler340ms
Vite 6, Babel React compiler290ms
Vite 6, SWC + Rust React compiler80ms

Production build (full bundle, no cache):

ConfigTime
Vite 5, no React compiler28.4s
Vite 6, Babel React compiler26.1s
Vite 6, SWC + Rust React compiler11.7s

The HMR number is the one that changes how you work day to day. Going from 340ms to 80ms on a component change means you stop mentally context-switching while waiting for the browser to catch up. That's not a small quality-of-life improvement.

What Most Guides Miss: The Compiler Isn't Magic, It's Strict

Here's the thing that almost every benchmark post glosses over: the React compiler enforces the Rules of React at compile time. If your components violate those rules, the compiler opts them out of automatic memoization silently, or in stricter configurations, it will error.

That's actually fine behavior. But it means your benchmark numbers depend heavily on how compliant your existing codebase is.

In the project I tested, 11 components were opted out by the compiler on first run. The reasons were predictable: mutating props directly, reading from refs during render, and a few places where someone had written a hook that conditionally called another hook inside a loop. All of them were latent bugs. The compiler surfaced them without breaking anything at runtime, but it also didn't memoize those components, so your real-world HMR gains will be proportional to your code quality.

Run the compiler in annotation-only mode first to see what it flags:

['babel-plugin-react-compiler', { compilationMode: 'annotation' }]

In annotation mode, the compiler only transforms components you've explicitly tagged with 'use memo'. This gives you a safe migration path: fix the flagged components, opt them in manually, and expand from there before switching to full compilation mode.

TypeScript Integration

The Rust React compiler Vite pipeline has no TypeScript-specific configuration beyond what you'd already have. The compiler operates on the transformed output after TypeScript is stripped, so your tsconfig.json is untouched.

One practical note: if you're using strict: true in TypeScript (and you should be), the compiler's component detection is more reliable because your prop types are explicit. Loose typing with lots of any or untyped callbacks can confuse the compiler's analysis of whether a value is stable across renders.

Your tsconfig.json target should be at least ES2022 for the compiler's output to work cleanly:

{
  "compilerOptions": {
    "target": "ES2022",
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true
  }
}

Nothing exotic here. If you're on an older target like ES2015, update it. You're shipping to modern browsers.

What Actually Broke

The migration wasn't painless. Here's what caused real friction:

Babel plugins with no SWC equivalent. One project I tested used babel-plugin-styled-components for display names in development. There's no drop-in SWC equivalent yet, so that project stayed on the Babel path and got the smaller performance gains. If you're in this camp, you still win on production build times (Rollup's output is better regardless), but your HMR gains will be modest.

React.memo usage conflicts. Components wrapped in React.memo where the compiler also wants to memoize them produce a double-memoization situation. The compiler detects most of these and skips its own optimization, but you'll see warnings. The right answer is to remove your manual React.memo calls after confirming the compiler is handling those components. Don't remove them preemptively.

Testing setups. If you're using Vitest (which you probably are if you're on Vite), the compiler plugin doesn't run during tests by default because tests bypass the Vite transform pipeline. This is actually fine: your tests should be testing behavior, not relying on memoization. But if you have tests that assert on render counts, those tests will break when the compiler changes memoization behavior in production but not in test. Audit those first.

The JavaScript and React Ecosystem Angle

There's a broader pattern worth naming. The frontend toolchain has been on a consistent trajectory toward native-compiled tools: esbuild replaced slow JS bundler cores, SWC replaced Babel for most transforms, and now the React compiler itself has a Rust core. The pattern from the language community discussion on Reddit about building faster languages applies here too: the performance ceiling of JavaScript-implemented tooling is real, and the ecosystem has been systematically replacing those bottlenecks with native code.

The Rust React compiler Vite integration is the latest step in that progression, and based on the benchmarks, it's a substantial one.

There's also a parallel to what's happening with AI tooling right now. Spotify's engineering team recently published how Portal cut Claude Code token usage by 90% by being smarter about context. The same discipline applies to build tooling: the wins come from reducing unnecessary work, not from throwing more compute at the problem. The Rust React compiler wins because it eliminates redundant passes, not because it has more CPU time.

Migration Path: The Least-Regret Sequence

Don't try to migrate everything at once. Here's the sequence that works:

  1. Upgrade to Vite 6.x and update @vitejs/plugin-react to the latest version.
  2. Add babel-plugin-react-compiler with compilationMode: 'annotation'.
  3. Run your dev server and check the compiler output for opted-out components.
  4. Fix the violations the compiler flags (these are real bugs, fix them regardless).
  5. Switch compilationMode to 'all'.
  6. If you have no blocking Babel plugin dependencies, migrate to @vitejs/plugin-react-swc and @swc/plugin-react-compiler.
  7. Remove manual React.memo, useMemo, and useCallback calls from components the compiler now handles. Do this incrementally with profiling, not all at once.

Step 7 is optional in the short term but important for codebase hygiene. Leaving manual memoization in place alongside compiler memoization creates confusion about what's actually controlling render behavior.

The Concrete Recommendation

If you're running a React TypeScript app on Vite today, upgrade to the SWC-based Rust React compiler Vite setup this week. The cold start and HMR improvements are real and they compound across a full workday of development. The production build time improvement alone justifies the migration for any CI pipeline that's burning time on frontend builds.

The one reason to wait: if you have Babel plugin dependencies with no SWC equivalent, stay on the Babel compiler path for now and get the partial gains. Don't let perfect block you from the improvement that's available today.

The Rust React compiler Vite integration is not experimental tooling anymore. It's the current best practice. Ship it.

Have Questions or Need Help?

Our team is ready to assist you with your project needs.

Contact Us