DEV Community

Alex Spinov
Alex Spinov

Posted on

Million.js Has a Free React Compiler That Makes Components 70% Faster

React's virtual DOM is smart but slow. Million.js replaces it with a block virtual DOM that skips diffing entirely for static parts of your components.

How It Works

React's VDOM diffs the entire tree on every render. Million.js analyzes your component at compile time and creates a "block" that only updates the dynamic parts.

React VDOM:    Diff entire tree → Find changes → Patch DOM
Million block: Skip static parts → Update only dynamic nodes → Done
Enter fullscreen mode Exit fullscreen mode

Setup (30 Seconds)

npm install million
Enter fullscreen mode Exit fullscreen mode
// vite.config.ts
import million from "million/compiler";
import react from "@vitejs/plugin-react";

export default {
  plugins: [million.vite({ auto: true }), react()],
};
Enter fullscreen mode Exit fullscreen mode

That is it. Million.js automatically optimizes your components.

Auto Mode

With auto: true, Million.js automatically wraps compatible components:

// This is automatically optimized — no changes needed
function UserCard({ name, email, role }) {
  return (
    <div className="card">
      <h2>{name}</h2>          {/* Dynamic — tracked */}
      <p>{email}</p>           {/* Dynamic — tracked */}
      <span>{role}</span>      {/* Dynamic — tracked */}
      <div className="footer"> {/* Static — skipped during diff */}
        <button>Edit</button>  {/* Static — skipped during diff */}
      </div>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

The static HTML (div.footer, button) is never diffed.

Manual Mode (block())

import { block } from "million/react";

const UserCard = block(function UserCard({ name, email }) {
  return (
    <div className="card">
      <h2>{name}</h2>
      <p>{email}</p>
    </div>
  );
});
Enter fullscreen mode Exit fullscreen mode

For Lists (The Biggest Win)

import { For } from "million/react";

function UserList({ users }) {
  return (
    <For each={users}>
      {(user) => (
        <div key={user.id}>
          <h3>{user.name}</h3>
          <p>{user.email}</p>
        </div>
      )}
    </For>
  );
}
Enter fullscreen mode Exit fullscreen mode

<For> is optimized for list rendering — items are updated in place without recreating DOM nodes. Lists with 1000+ items see 70% faster updates.

Benchmarks

Scenario React React + Million.js
1000 item list update 45ms 12ms
Complex form re-render 22ms 8ms
Dashboard with charts 38ms 15ms
Table sorting (5000 rows) 120ms 35ms

Compatibility

Works with:

  • Vite
  • Next.js
  • Remix/React Router
  • Astro
  • Webpack (via plugin)

When NOT to Use Million.js

  • Components with complex conditional rendering
  • Components that use refs extensively
  • Very small apps (overhead not worth it)
  • React Server Components (already skip client JS)

React Compiler vs Million.js

React 19 introduced the React Compiler (formerly React Forget). Key differences:

  • React Compiler: auto-memoizes to prevent re-renders
  • Million.js: replaces VDOM with block DOM for faster updates
  • They are complementary — use both for maximum performance

Need high-performance web applications? I build developer tools and data solutions. Email spinov001@gmail.com or explore my Apify tools.

Top comments (0)