After I began working with React, I discovered that it is significantly faster than traditional HTML, CSS, and JavaScript-based web pages. I was curious about how React achieves this speed. It's fascinating how Facebook (now Meta) developed such an architecture to address issues like ghost notification updates and slow page loading.
1. Real DOM & The Traditional Approach
When we write HTML code, the browser loads it and constructs a tree-like structure of every element to display on the page, known as the Document Object Model (DOM).
In the traditional approach, if we want to change the value of any element, we update it by calling document methods directly. This line directly touches the Real DOM:
// Traditional DOM update - directly pokes the Real DOM
document.getElementById("h1-text").innerText = "Virtual DOM";2. Why Facebook Was Struggling: Why Real DOM Is Slow
After the DOM creation is complete, the browser calculates styles, layout, and paints them on the page. If we update any element or node, the browser repeats these processes. It becomes even slower when we call document.getElementById, as the browser literally searches each node to find the target.
When we update an element, the browser performs several intensive operations; it's not merely a change to a JavaScript object:
- 1. Search the DOM node or element in the tree
- 2. Update the DOM tree structure
- 3. Recalculate Styles (CSS cascade & computed styles)
- 4. Recalculate Layouts & geometric positions (Reflow)
- 5. Repaint pixels on the screen (Repaint)
- 6. Re-render affected parts of the page
3. Entry of the Virtual DOM (VDOM)
The Facebook team considered taking control of DOM updates rather than relying on the browser. Instead of interacting directly with the slow real DOM, they proposed maintaining a lightweight copy of it in plain JavaScript memory.
This allows them to decide when and how to update the real DOM. This lightweight JavaScript copy is the Virtual DOM (VDOM), a simple JavaScript object that describes what the UI should look like:
// Lightweight JavaScript Object sitting in memory
const vdomNode = {
type: 'div',
props: {
children: [
{
type: 'h1',
props: {
id: 'h1-text',
children: 'Hello World!'
}
},
{
type: 'button',
props: {
children: 'Submit'
}
}
]
}
};4. React's 3-Step Internal Flow (Diffing & Reconciliation)
Now, when state changes, React follows these 3 internal execution steps:
- Step 1: Re-render a new Virtual DOM Tree with the updated state in memory.
- Step 2: Compare (Diff) the new Virtual DOM tree against the previous Virtual DOM tree (Reconciliation).
- Step 3: Compute minimal patches and apply ONLY the changed attributes or nodes to the Real DOM.
5. What Makes Virtual DOM Even Faster: Pointer-Based Referencing
React stores direct node references to skip searching by using a pointer-based approach, eliminating costly DOM lookups:
// Search happens once, at the beginning
const h1Node = document.getElementById("h1-text");
// After every update: direct pointer jump, no tree searching!
h1Node.textContent = "VDOM";
h1Node.textContent = "React";- This is similar to a database indexing strategy: pay the search cost once, never again.
Written by Rana Sarkar
SDE2 at S&P Global, experienced in Java, Spring Boot, Node.js, SQL, NoSQL, React, and AWS development.
Discussion (1)
Markdown supportedThe database indexing analogy ('pay the search cost once, never again') explains React's node pointer referencing better than almost any article out there. Great writeup!