Virtual DOM
what is virtual DOM and how it helps
The Problem
DOM manipulation is the heart of the modern, interactive web. Unfortunately, it is also a lot slower than most JavaScript operations.
This slowness is made worse by the fact that most JavaScript frameworks update the DOM much more than they have to.
As an example, let’s say that you have a list that contains ten items. You check off the first item. Most JavaScript frameworks would rebuild the entire list. That’s ten times more work than necessary! Only one item changed, but the remaining nine get rebuilt exactly how they were before.
Rebuilding a list is no big deal to a web browser, but modern websites can use huge amounts of DOM manipulation. Inefficient updating has become a serious problem.
To address this problem, the people at React popularized something called the virtual DOM.
The Virtual DOM
In React, for every DOM object, there is a corresponding “virtual DOM object.” A virtual DOM object is a representation of a DOM object, like a lightweight copy.
A virtual DOM object has the same properties as a real DOM object, but it lacks the real thing’s power to directly change what’s on the screen.
Manipulating the DOM is slow. Manipulating the virtual DOM is much faster, because nothing gets drawn onscreen. Think of manipulating the virtual DOM as editing a blueprint, as opposed to moving rooms in an actual house.
How it helps
When you render a JSX element, every single virtual DOM object gets updated.
This sounds incredibly inefficient, but the cost is insignificant because the virtual DOM can update so quickly.
Once the virtual DOM has updated, then React compares the virtual DOM with a virtual DOM snapshot that was taken right before the update.
By comparing the new virtual DOM with a pre-update version, React figures out exactly which virtual DOM objects have changed. This process is called “diffing.”
Once React knows which virtual DOM objects have changed, then React updates those objects, and only those objects, on the real DOM. In our example from earlier, React would be smart enough to rebuild your one checked-off list-item, and leave the rest of your list alone.
This makes a big difference! React can update only the necessary parts of the DOM. React’s reputation for performance comes largely from this innovation.
In summary, here’s what happens when you try to update the DOM in React:
The entire virtual DOM gets updated.
The virtual DOM gets compared to what it looked like before you updated it. React figures out which objects have changed.
The changed objects, and the changed objects only, get updated on the real DOM.
Changes on the real DOM cause the screen to change.
Reference - https://www.codecademy.com/articles/react-virtual-dom
ReactJS does not update the real DOM directly but it updates the Virtual DOM. DOM stands for Document Object Model. As per w3.org DOM defines the logical structure of documents and the way a document is accessed and manipulated.
This causes a great performance benefit for ReactJS. Here, we will try to understand why updating the real DOM is slow and how updating Virtual DOM increase the performance?
Why updating Real DOM is slow:
Updating a DOM is not slow, it is just like updating any JavaScript object; then what exactly makes updating real DOM slow?
Let’s look at the below image from html5Rocks to see how exactly browser renders a web page
Rendering engines which are responsible for displaying or rendering the webpage on the browser screen parses the HTML page to create DOM. It also parses the CSS and applies the CSS to the HTML, thus creating a render tree, this process is called as attachment.
Layout process gives exact coordinates to each node of the render tree, where the node gets painted and displayed.
So when we do,
Following thing happens:
The browser has to parse the HTML
It removes the child element of elementId
Updates the DOM with the “New Value”
Re-calculate the CSS for the parent and child
Update the layout i.e. each elements exact coordinates on the screen
Traverse the render tree and paint it on the browser display
Recalculating the CSS and changing layouts uses complex algorithms and they affect the performance.
Thus updating a real DOM does not involve just updating the DOM but, it involves a lot of other processes.
Also, each of the above steps runs for each update of the real DOM i.e. if we update the real DOM 10 times each of the above step will repeat 10 times. This is why updating Real DOM is slow.
How Virtual DOM solves this problem?
Virtual DOM is an in-memory representation of real DOM. It is a lightweight JavaScript object which is a copy of Real DOM.
Updating virtual DOM in ReactJS is faster because ReactJS uses
Efficient diff algorithm
Batched update operations
Efficient update of subtree only
Uses observable instead of dirty checking to detect the change
AngularJS uses dirty checking to find the models which have changed. This dirty checking process runs in cycle after a specified time. As the application grows, checking the whole model reduces the performance and thus makes the application slow.
ReactJS uses observable’s to find the modified components. Whenever setState() method is called on any component, ReactJS makes that component dirty and re-renders it.
Whenever setState() method is called, ReactJS creates the whole Virtual DOM from scratch. Creating a whole tree is very fast so it does not affect the performance. At any given time, ReactJS maintains two virtual DOM, one with the updated state Virtual DOM and other with the previous state Virtual DOM.
ReactJS using diff algorithm compares both the Virtual DOM to find the minimum number of steps to update the Real DOM.
Finding the minimum number of modifications between two trees have complexity in the order of O(n^3). But react uses a heuristic approach with some assumptions which makes the problems to have complexity in the order of O(n).
ReactJS uses the following steps to find the difference in both the Virtual DOM’s
Re-render all the children if parent state has changed. If the state of a component has changed, then ReactJS re-renders all the child components even if child components are not modified. To prevent the unwanted re-render of the child components we can use shouldComponentUpdate() component life cycle method. This will further help in boosting performance.
Breadth First Search. ReactJS traverse the tree using BFS. Consider the below tree. States of element B and H have changed. So when using BFS ReactJS reached element B it will by default re-render the element H. This is the reason to use BFS for tree traversal
3. Reconciliation. It is the process to determine which parts of the Real DOM need to be updated. It follows the below steps:
Two elements of different types will produce different trees.
The developer can hint at which child elements may be stable across different renders with a
key
prop.
Reconciliation in detail can be read from React’s official doc
Batch Update
ReactJS using the diff algorithm to find the minimum number of steps to update the Real DOM. Once it has these steps, it executes all the steps in one event loop without involving the steps to repaint the Real DOM. Thus, if there are more element which gets updated ReactJS will wait for the event loop to finish then, in bulk will update the real DOM with all the updated elements.
Once all the steps are executed, React will repaint the Real DOM. This means during the event loop, there is exactly one time when the Real DOM is being painted. Thus all the layout process will run only on time for updating the real DOM.
Last updated