Million.js: The O(1) Heist of the Virtual DOM
How a build-time compiler turns React's biggest weakness into a static-speed advantage without a single rewrite.

Million.js takes a different approach. Instead of replacing React, it augments it with performance optimizations when you need it. Million.js works out of the box, alongside your favorite metaframeworks (Next.js, Remix, etc.) and React libraries.
- Million.js replaces React's recursive tree-diffing with a block architecture that achieves O(1) rendering complexity.
- A custom build-time compiler separates static HTML from dynamic data to create optimized update templates.
- The library maintains full compatibility with the React ecosystem and major metaframeworks like Next.js.
- Automatic heuristics determine whether to optimize a component based on the ratio of static elements to nested components.
The O(n) Tax
The Virtual DOM was a brilliant abstraction. It allowed developers to write declarative UI code without worrying about manual browser updates. But this abstraction comes with a hidden cost. Every state change triggers a recursive diffing process. React must compare the new component tree against the old one to find what changed. As applications scale, this O(n) algorithmic complexity becomes a tangible performance bottleneck.
Frameworks like SolidJS and Svelte solved this by abandoning the Virtual DOM entirely. They adopted fine-grained reactivity or compiled imperative updates. But migrating to a new framework is a monumental task. Developers were stuck choosing between the rich React ecosystem and raw performance. Million.js offers a third path.
Anatomy of a Block
Instead of diffing trees, Million.js uses a block architecture. A block is a pre-calculated template with specific holes for dynamic data. When state changes, Million does not search the tree. It maps the new data directly to the holes in an O(1) operation.
The Compiler is the Architect
Million.js is fundamentally a compiler. The heavy lifting happens during the build step using a custom Babel plugin. The compiler analyzes your React components, separates the static HTML structure from the dynamic variables, and generates optimized update instructions before the code ever reaches the browser.
import { block } from 'million/react';
const HeavyList = block(({ items }) => (
<div>
{items.map(item => (
<span key={item.id}>{item.value}</span>
))}
</div>
));
The Speed Spectrum
Million sits in a unique position. It provides the ecosystem compatibility of React with the rendering speed of compiled frameworks.
| Feature | React | Million.js | SolidJS |
|---|---|---|---|
| Reconciliation | O(n) Tree Diffing | O(1) Block Updates | Fine-grained Signals |
| Ecosystem | Massive | Full React Compatibility | Growing Custom Ecosystem |
| Build Step Required | No (JSX only) | Yes (Babel Plugin) | Yes (Custom Compiler) |
When the Magic Fails
Not every component benefits from the block architecture. If a component consists entirely of other React components rather than raw HTML elements, the compiler cannot extract a meaningful static template. The automatic mode uses a heuristic to calculate an improvement score, ensuring it only optimizes code that will actually run faster.