Back Story
Wondering why this pic ?
Because if you have asked me about DOM few months back , I would have said you about him. As he is the only "Dom" i knew, till i started learning web dev at neoG Camp.
In our third week at neoG Camp, I got introduced to another DOM formally by our mentor .Although it was just enough intro to work upon the assignment , I got more confused when virtual DOM is introduced in our fourth week . And when I heard that there is something called shadow DOM too , I could not stop myself to dive deeper.
Here is what I am able to understand about DOM(s) .
What is this DOM ?
DOM or Document Object Model is an web api that models the entire html document in an object oriented way , so that programming languages like Javascript can access and manipulate it's properties .
Why ?
Because without representing the elements of html document as objects, Javascript won't be able to recognise them,let alone accessing it's properties .
How ?
By taking all the elements of the doument as objects and then representing them in a hierarchical tree . In that tree each branch starts and ends with nodes and by using this nodes javascript control the whole document .
so only elements are represented as nodes ?
Not Necessarily . A node is just the generic name for any type of object in DOM tree . It could be one of the built-in DOM element like document or document.body or it could be an element node or text node or even attribute node too .
so if it's all objects underneath , why updating it slow ?
Actually updating the DOM is not slow , It's like updating any javascript object . It's what comes after the manipulation that's where the problem lies . So in order to answer what is making the whole process slow we need to understand browser workflow first .
Broswer Workflow
From the above image Although you can see it's happening in four stages mainly . You must be thinking who is responsible for all of it . The answer is Rendering Engine .
The Rendering Engine
Like the name suggests, all it does is Render, that is displaying requested contents on the browser screen. Below we are going to see the work flow of webkit engine that powers browsers like safari ,chrome and edge .
As you can see from the above image before painting each modification it has to go through all those time consuming stages like layout and paint .
So for example if you have modified 40 nodes, one by one. That would mean 40 potential re-calculations of the layout, 40 potential tree modifications and 40 potential re-renderings too .
And that's what makes direct DOM Manipulation slow .
It's like creating your bike from scratch for every little fix or color change or even stickering . Then imagine if you have to do the same thing for a BUS .
Yes it's insane , If you are even thinking about creating something like facebook and twitter in this way .
then solution ?
Virtual DOM a.k.a VDOM.
Virtual DOM
Virtual DOM is nothing but a light-weight copy of actual DOM that exist only in memory . Like actual DOM it is a object too . You can think of it as a blueprint to the actual thing .
then how does it different from actual DOM?
It lacks the ability to directly change what is displayed on the screen until the real DOM is updated . Which is why, it does not have to go through all the heavy weight stages like re-layout or re-paint etc . It just observes the changes then draws out in blueprint and passes it down to the real DOM .
sounds fascinating , right ? even if it's not for you..can you please just pretend and ask the next question that resembles the below question..
how does it do it ?
As you can see from above pictures , the whole process can be divided broadly into three parts .
State Change - Due to changing state of red color node , virtual DOM is generated in memory with the updated tree .
Compute diff - Comparison is carried out to detect the changes and it's effects.
Re-render - Finally , the change in real DOM is consolidated and updated at once.
Now let's get to the million dollar question..
How does react use it to solve our problem ?
In short , by using following things :
- Observable instead of dirty checking to detect the change
- Efficient diff algorithm
- Batched update operations
- Efficient update of subtree only
Using observable's instead of dirty checking
In React, each piece of the UI is a component and each component has an internal state. This state is observed by the library in order to detect changes in it. So whenever state changes , React mark that component dirty and re-renders it.
So unlike angular that uses dirty checking to find modified models in regular intervals , React uses observables to find the exact modified components . If there are no state changes then it won't have to do anything .
The Diffing Algorithm
Before rendering a new component , React must figure out the specific parts need to be updated . And to figure out this React must compare between two Virtual DOMs it maintains at any given time , one with the updated state and the other with previous state .
And To achieve it efficiently , React uses a heuristic approach known as the Diffing Algorithm of the order O(n) instead of using state of the art algorithm of order [O(n³)] .
HOW ? by relying on below assumptions ..
Assumption 1 : Two elements of different types will produce two different trees.
Assumption 2 : The developer can hint at which child elements may be stable across different renders with a key prop.
Batch Update operations
React uses the diffing process to find minimum no. of steps to update the Real DOM and once it has those , it executes all of it in one event loop . So if there are more elements that needs to get updated in meantime , React will wait for the event loop to finish first and then in bulk will update the DOM with updated elements .
After all these steps are done, React will repaint the Real DOM .
As you can see DOM is getting repainted only once during the whole process, thus all the layout , re-calculation process will run only once .
Updating the subtree only
ReactJS traverses the tree using BST. So if the state of a component has changed, then ReactJS re-renders all the child components even if they are not modified .
Consider the tree below.
States of element B and H have changed. So when using BST ReactJS reached element B it will by default re-render the element H. This is the reason to use BST for tree traversal.
Is shadow DOM is same as Virtual DOM ?
NO..they are completely different things..
Shadow DOM
Shadow DOM refers to the ability of the browser to include a subtree of DOM elements into the rendering of a document, but not into the main document DOM tree.
you can say it simply as “ DOM within a DOM” .
As it remains hidden and separate from the scope of the other codes , we use it as a meanning of creating web component .
Can you give a example that we know ?
think of <video>
element with all it's default controls . For us it maybe
just <video>
element that we can put anywhere in our document without any hassle.
But if you look closely in it's shadow DOM , you are gonna find out a series of buttons , controls and other settings hidden and separated from the outer code .