javascript domjavascript dom

What is DOM in JavaScript? The difference between Real vs Virtual vs Shadow DOM

What is DOM in JavaScript? Explore real, virtual, and shadow DOM differences, uses, and virtual DOM’s performance perks with code examples

The Document Object Model (DOM) is a programming interface for web documents. It represents the page so that programs can change the document structure, style, and content. The DOM represents the document as nodes and objects, which makes it easy to access and change the page with JavaScript.

With traditional DOM manipulation, updating the DOM is slow because it directly updates the DOM on every change. This causes layout thrashing, resulting in poor performance. Virtual DOM and Shadow DOM were introduced to improve performance and encapsulation when manipulating the DOM.

The DOM is vital for dynamically displaying data and creating interactive web apps. Understanding the differences between the Real DOM, Virtual DOM, and Shadow DOM enables developers to build efficient user interfaces with good performance.

What is the Real DOM?

The Real DOM (Document Object Model) represents the HTML document as a node tree structure called the DOM tree. It consists of objects such as documents, elements, attributes, and text.

When a web page loads, the browser parses the HTML and constructs the DOM tree. It then renders the DOM tree to display the page. Any changes made to the DOM triggers the browser to re-render the updated DOM.

For example:

<div id="container">  <p>Hello World!</p> </div>
HTML

This HTML would be represented as the following DOM tree:

dom tree structure

The browser uses the DOM tree to render the page. Any changes to the DOM tree requires re-rendering of the affected parts. Manipulating the DOM directly to update the UI can be slow for complex apps because the entire subtree has to be re-rendered every time there is an update.

Problems with Real DOM Manipulation

The Real DOM refers to the actual Document Object Model representation of the HTML page loaded in the browser. When we make changes to the DOM, such as adding or updating elements, it triggers the browser to re-render the UI.

This can be quite expensive:

  • Expensive to update: Every small change causes a re-render, which can be taxing on performance. Simple tasks like adding a class or changing text can force the entire UI to re-draw.
  • Can get slow with complex UIs: With large, complex UIs, manipulating the Real DOM can really start to lag, especially on lower-powered devices. All those re-renders add up.
  • Difficult to optimize: Because the browser handles DOM updates, it can be challenging to optimize Real DOM performance. We have to rely on general best practices around reducing DOM access and manipulation.

So while working with the Real DOM is natural, it can get costly. This led to the creation of solutions like Virtual DOM to improve performance.

Introducing Virtual DOM

The Virtual DOM is an in-memory representation of the Real DOM. It is completely detached from any browser-specific implementation details.

Since the Virtual DOM is just a JavaScript object, it becomes very easy to manipulate. You can update it in any way you want without worrying about browser repaints and reflows. This makes it much faster than directly manipulating the Real DOM.

When you modify the Virtual DOM, it calculates the minimal set of changes necessary to update the Real DOM. This process is called diffing. It figures out which virtual nodes have changed and then only applies those changes to the Real DOM. So in most cases, only a small part of the Real DOM will get updated instead of re-rendering the entire tree.

The Virtual DOM brings the benefits of speed and performance. You can freely manipulate JavaScript objects to describe your UI state, and let the Virtual DOM figure out how to efficiently update the Real DOM. This allows you to write simple and clean code without worrying about performance implications.

How Virtual DOM Works

The virtual DOM works by using a virtual representation of the real DOM. When the state of an application changes, the virtual DOM will re-render the entire UI in memory and compare the result with the previous render.

This process is called “diffing”. The diffing algorithm compares the new virtual DOM with the previous one to find out what has changed. It does this by traversing the virtual DOM tree recursively and comparing all nodes.

When it finds a difference, such as a text node whose value has changed, it will mark that node as “dirty”. Once the diffing is complete, there is a list of the minimal set of changes needed to update the real DOM.

This allows the virtual DOM to batch multiple DOM changes together before applying them. So rather than manually manipulating the real DOM on every state change, we let the virtual DOM handle updating the real DOM most optimally.

This process of diffing and batched DOM updates is extremely performant compared to manual DOM manipulation. By minimizing operations on the real DOM, the number of expensive reflows and repaints is reduced.

Benefits of Virtual DOM

The Virtual DOM provides several benefits over direct manipulation of the Real DOM:

Faster updates

Updating the Virtual DOM is much faster than updating the Real DOM directly. When state changes in a component, the Virtual DOM can update efficiently behind the scenes without touching the Real DOM. This avoids costly Real DOM operations like removing/adding DOM nodes.

Better performance

By minimizing Real DOM updates, the Virtual DOM improves overall rendering performance. Batching DOM updates and minimizing reflows/repaints boosts performance significantly. The Virtual DOM enables smooth UIs even when the state changes frequently.

Simpler coding

The Virtual DOM abstracts away direct DOM manipulation in favor of a simpler programming model. Developers can write code as if the entire UI is re-rendered on each update, and allow the Virtual DOM to handle optimizations behind the scenes. This reduces complexity and makes code easier to understand.

Introducing Shadow DOM

The Shadow DOM allows for the encapsulation of DOM elements and CSS styles. It creates a scoped subtree of DOM elements that are not accessible from the main document DOM tree. This enables better componentization and isolation.

Some key aspects of Shadow DOM:

  • Encapsulated DOM tree – The Shadow DOM creates an encapsulated DOM tree scoped to the component. It is separate from the main document DOM tree. This allows the component to have its own isolated DOM without worrying about collisions with other DOM trees.
  • Scoped CSS – CSS styles defined inside Shadow DOM are scoped to it. They won’t leak out and affect styles on the main page. This allows shadow DOM components to have self-contained styles without worrying about naming collisions.
  • Improved componentization – Since Shadow DOM components have their own DOM tree and CSS scope, they become truly isolated custom elements. This makes them more reusable, portable, and modular.

The shadow DOM improves componentization by enabling DOM and CSS encapsulation. Components can use unique IDs and class names without worrying about conflicts. Styles are also scoped, allowing self-contained customizable components.

Using Shadow DOM

The Shadow DOM allows web developers to attach a hidden DOM to an element. This shadow DOM is not accessible from the main document DOM. To attach a shadow DOM to an element, we use the attachShadow() method:

const header = document.querySelector('header');   const shadow = header.attachShadow({mode: 'open'});
JavaScript

This attaches a shadow DOM to the <header> element. We can then add elements to the shadow DOM:

const header = shadow.appendChild(document.createElement('h1')); header.textContent = 'Hello World'; 
JavaScript

The <h1> we created is only visible within the shadow DOM, not in the main document DOM.

To allow elements from the main DOM to show up inside the shadow DOM, we use the <slot> element:

<header>  <slot></slot> </header>
HTML

Any elements inside <header> in the main DOM will get projected into the <slot>.

Events handled in the shadow DOM will not bubble up to the main DOM. If we want events to reach the main DOM, we need to re-target the events. We can do this by calling event.composedPath() and dispatching the event on those elements.

Shadow DOM allows for encapsulation of DOM logic and protects the main document DOM from becoming cluttered. It’s a key aspect of web components. The ability to project nodes via <slot> keeps the component flexible and connected to the main document.

Benefits of Shadow DOM

The Shadow DOM provides several key benefits:

Scoped CSS

The Shadow DOM allows for CSS scoping so that styles don’t bleed out and affect parts of the DOM they shouldn’t. Styles defined inside a shadow root stay inside that shadow root. This prevents issues with global style collisions.

Improved encapsulation

Shadow DOM enables better encapsulation and isolation of component implementation details. The internal structure of a component isn’t exposed to the main document. This improves modularity and reusability.

Component-based architecture

Shadow DOM promotes component-based architecture. Components become individual self-contained units that can be reused across applications. Developers can build complex UIs out of reusable, encapsulated components with their own scoped CSS. This aligns with modern front-end frameworks.

The scoping, encapsulation, and modularity provided by Shadow DOM facilitates improved structure and organization of complex web applications built from reusable components.

Conclusion

Virtual DOM and Shadow DOM are both technologies that improve upon directly manipulating the real DOM in different ways. Here’s a summary of the key differences:

  • The Virtual DOM is an in-memory representation of the real DOM. It allows diffing and batching of changes for better performance. The Shadow DOM encapsulates a component’s DOM to avoid conflicts.
  • Use the Virtual DOM when you need to update the UI efficiently in frameworks like React and Vue. Use the Shadow DOM when you need scoped styling and markup for web components.
  • The future of web development is component-driven thanks to these innovations. Frameworks leveraging the Virtual DOM like React and Vue have exploded in popularity. Web components using the Shadow DOM allow for reusable widgets.
  • Together, the Virtual DOM and Shadow DOM enable faster UIs through minimal DOM manipulation. They encourage modular and encapsulated front-end code. As web apps become more complex, these technologies will be crucial for managing complexity. Expect to see wider adoption of both as web development continues to evolve.