Stop Writing useMemo. Vite Handles It Now.

The React Compiler's Rust rewrite is now built into Vite. Automatic memoization with zero Babel overhead — here's how to turn it on.

Share

The React Compiler — the thing that memoizes your components for you — just got a Rust rewrite, and it now ships natively in Vite. No Babel pass bolted onto your build. One flag in your config, and the compiler starts deleting work you used to do by hand.

If you've spent evenings wrapping components in React.memo and chasing stale dependency arrays, this is the payoff: memoization becomes the compiler's job, not yours.

Why this matters

Manual memoization fails in both directions. Skip it and one keystroke in a search box re-renders a thousand-row table. Apply it everywhere and your components drown in useMemo noise, where every dependency array is a latent stale-data bug. The compiler decides mechanically, per component, which values need caching — something humans do badly at scale.

The Rust rewrite kills the other excuse. The original compiler ran as a Babel plugin that slowed builds enough that teams switched it off. Native Vite support means adoption is a config change, not a build-pipeline project.

How it works

At build time the compiler parses each component and tracks which values could change between renders — derived arrays, filtered lists, object literals passed as props. For each one, it inserts cache calls into the output. Same input, same identity: skip the recompute, and skip the downstream re-renders.

It only compiles components that follow the Rules of React: pure render, no mutating props or state. Non-compliant code is left untouched, so bad components degrade to today's behavior instead of breaking.

Where this helps

  • Context-heavy dashboards: object literals in a provider value currently re-render every consumer; the compiler keeps identity stable for free.
  • Large tables and virtualized lists where one cell update cascades through hundreds of rows.
  • Design systems: leaf components taking complex prop objects no longer need memo wrappers at every boundary.
  • Legacy codebases: enable it per directory and let non-compliant files bail out silently.

Watch out

The compiler enforces the Rules of React strictly. Code that mutates props, state, or shared objects gets skipped — silently, in production builds. Run eslint-plugin-react-hooks with the compiler rules enabled before flipping anything on, and fix the warnings first.

Also, it memoizes — it doesn't optimize. An O(n²) render stays O(n²), just with stable inputs. The auto-inserted cache calls add bundle size too. Profile with React DevTools before and after instead of assuming, and check the compatibility notes for your React major before enabling it fleet-wide.

Try it yourself

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

export default defineConfig({
  plugins: [
    react({
      compiler: true, // Rust compiler, no Babel pass
    }),
  ],
})

// Before:
const visible = useMemo(
  () => items.filter(i => i.status === status),
  [items, status]
)

// After — the compiler caches this for you:
const visible = items.filter(i => i.status === status)

TL;DR

  • What changed: the React Compiler was rewritten in Rust and now ships natively in Vite — automatic memoization without a Babel pass.
  • Why it matters: most of your useMemo, useCallback, and React.memo boilerplate exists to fight re-renders; the compiler does that work mechanically.
  • Try today: flip the compiler flag in vite.config, run the React hooks ESLint rules first, then profile before and after.