React.JS internals: Virtual DOM

This write up assumes that you are familiar with React.JS. If you’re not, here is a good place to start off. Alright, if you have used React.JS in production or in your little experimental applications, you know that React.JS is so performant in terms of DOM manipulations. Some developers might think that regular applications performing DOM manipulations are really expensive and slow because of JavaScript’s fault. But in reality JavaScript is very fast in execution and in the present JavaScript code can execute in a speed equivalent to optimized C++ code. This might not be the case in each and every instance but there can be use cases where this is possible (for an instance within Node.JS environment). So the real drawback lies behind the DOM (Document Object Model).

Document Object Model

DOM is a programming interface for HTML or XML which provides a structured way to present a document. DOM represents documents in a logical manner. Usually this is mapped with a tree structure. In DOM documents are modeled with objects. It represents not only the structure of the document, but also the behavior. So DOM represents objects. This provides a way to represent object in HTML or XML not a way to persist objects in HTML or XML. DOM provides a API which is language independent. JavaScript is the most common and widely used language to access and manipulate the DOM.

Let’s take a deep look at how a simple web page loads and sort out the reasons for it to be slow. Once a page loads several tasks run.

Above diagram shows several events that take place once a web page loads within a browser. For each and every page load unless the page in empty, there’s a process called painting and this causes reflows. We’ll get into painting and reflows once we go through the render tree. Once a page loads browser constructs the DOM tree, parses CSS and creates the render tree. DOM tree is the HTML representation of a page. On the other hand render tree is more like a visual representation of the DOM tree. Back to painting and reflows. When this process (reflows) takes place, the render tree gets changed. This can be so expensive because a reflow occurs after many calculations to change the visual representation of the DOM.

How does a reflow takes place ? There can be several instances. Adding or updating a DOM node, changing style sheets etc. Because of these actions, once DOM manipulation takes place expensive calculations makes everything looks slow, which will eventually lead to bad user experience (UX). Other than reflows in a DOM manipulations, many other expensive actions will trigger once a change happens to the DOM.

var element = document.getElementById(‘header’); 
element.style.color = ‘#ffff’;
element.innerHTML = ‘some text’;

Select element node, change color, recompute how the DOM is going to look, adding innerHTML will add new node text.

Above events behind the scenes which will compute the new representation of the render tree and eventually the DOM tree can be make DOM manipulation slow.

Chrome devtools recording

This screenshot shows a 2 seconds recording of GitHub homepage load. If you take closer look you’ll get an idea about the events that get executed in a page load. Now that we have a clear understanding about the DOM we’ll take a look at Virtual DOM implementation in React.JS.

Virtual DOM

React’s solution for expensive DOM manipulations is Virtual DOM. V-DOM is a lightweight representation of the real DOM. V-DOM is more like a fake DOM. It’s an in memory representation of real DOM within React.JS. V-DOM clones real DOM and it’s available as a large, single JavaScript object. In React once the application loads, it takes the real DOM and creates the representation of V-DOM.

Let’s take a scenario of DOM manipulation within a React application.

This depicts a few DOM manipulations where new nodes are being added. In this application once we type the username and hit ‘Go’ React will take over the control and it will execute a full re-render within the V-DOM. This won’t be expensive since React is not performing any changes on real DOM. After re-rendering processes finishes with the V-DOM, React compares the V-DOM with real DOM. In order to do this comparison React uses a special algorithm called the diff algorithm. Tree diff is so efficient in comparing two different DOMs. This takes place within few milliseconds. If there are any changes after the comparison, like in this case where few nodes gets added, React immediately patches changes from V-DOM to real DOM. This process doesn’t require expensive traversing since React already knows which nodes got changed. Therefore this solution will be more performant than using regular DOM. With React when mutations occur, they can be batched together. This will increase the performance since a minimal number of traversing is needed to change the state of a user interface.

Concept of Virtual DOM is not specific to React. There can be many implementations of the idea of V-DOM. In fact this library implements the V-DOM concept and the diffing algorithm for efficient change detection and patches.

Conclusion

Process of changing state in user interfaces can lead to expensive DOM manipulations. Maintaining state in modern web applications is an important task which can be tricky and this can affect the performance as well. Even though state can be maintained with JavaScript efficiently, representing state is the hard task. This is where React comes in to play. React solves the drawback of many front-end libraries/frameworks in the community and provides an elegant way to create JavaScript driven web applications.