Understanding the Virtual DOM Pattern

The Virtual DOM (VDOM) is a general concept used in web development often associated with front-end JavaScript libraries and frameworks. In particular, React. The VDOM serves the purpose of improving the performance and efficiency of updating web user interfaces within the browser.

As VDOM is virtual by nature, to make sense (and demistify the aura of magic that surrounds it) let’s start from the actual DOM.

The Actual DOM

Internally, the browser creates a tree-like structure called the Document Object Model (DOM) to represent the structure of a web page. Each element in the DOM corresponds to a part of the HTML document, and these elements are organized in a tree-like structure. When there are changes to a web page, such as user interactions or data updates, the DOM needs to be updated to reflect these changes. The DOM exposes an API for the purposes.

As long as the DOM is accessed occasionally, no big deal. For decades, the DOM has been the only and fastest way to dynamically update pages. Then, client-side frontends expanded and the idea of building an entire application within the browser conquered the heart of developers.

The initial approach followed, though, was quite dumb.

The final goal was giving web users the same smooth experience of desktop users. Except that a desktop application builds the UI once and updates it for the rest of the time only for the parts that change. On the web side, instead, it passed the idea that the page could be recreated entirely after each update–not on the server (full page refresh) but on the client using direct access to the DOM.

Unfortunately, directly manipulating the actual DOM can be slow and inefficient because it involves rendering the entire DOM tree every time there’s a change.

Enter a Mediator

      Instead of directly updating the actual DOM, a virtual representation of the DOM is created in memory. This virtual DOM is a lightweight copy of the actual DOM. Any changes to the web page are first made to the virtual DOM rather than the real DOM.
      After the changes are made to the virtual DOM, a process called “reconciliation” is performed. This involves comparing the current virtual DOM with a previous version (before the changes).
      The identified differences are used to determine the minimum number of changes needed to update the actual DOM to reflect the current state. Next, only the specific parts of the actual DOM that need to change are modified, minimizing the amount of work the browser has to do.

      In summary, the Virtual DOM is a pattern for optimizing the updating of web page content by using an in-memory representation of the DOM. It allows for more efficient updates and helps to minimize the performance impact of dynamic changes in web applications. The concept is commonly associated with libraries like React, but similar approaches are used in other front-end frameworks as well.

      VDOM in Angular

      Angular and React have different approaches to the DOM changes and use renderers that follow different philosophies. Driven by the principle of two-way data binding, Angular originally architected the rendering pipeline to make direct changes to the DOM for the entire HTML fragment being touched by changes.

      More recently, Angular introduced Ivy, a new rendering engine that supports incremental DOM updates. Basically, instead of completely re-rendering the entire component tree when data changes occur, Ivy updates only the parts of the DOM that have changed.

      Aside from different implementation details, both Angular and React do use optimized rendering engines based on the general mediator pattern in which dedicated engines work to minimize the number of low-level DOM operations.

      It’s JavaScript; Not Magic

      Note that any web application that uses JavaScript to update the DOM (e.g., via jQuery) dynamically applies its changes to the DOM without intermediation. 

      • Should these applications use some sort of VDOM?
      • Are vanilla-JS applications (provided that still exist) slower because not using a VDOM?

      At its core, there’s just one way to update the content the browser is currently displaying–using the DOM API. More precisely, access to the DOM can take place in two different ways.

      1. You can use the innerHTML property on any given DOM element
      2. You can use the direct API that exposes page elements as nodes of a tree-like structure

      The former approach is quite comfortable for the developer, but slower for the browser to go through. Essentially, it consists is setting the property with a HTML string that the browser has to parse and turn into actual direct API operations. The latter approach is faster as it is directly updating a property on a node but requires more planning and work on the developer’s side.

      Any vanilla-JS application (e.g., a Razor ASP.NET page) performs only the updates the specific action requires. By design, it minimizes the effort and uses JavaScript as a mere scripting language.

      The need for a VDOM arises from treating JavaScript as a full-stack language for building an entire web frontend. Abstracting the web UI to a list of autonomous components–each responsible for its own rendering and updates–has the effect of accumulating a lot of DOM operations losing the perspective of what has really changed after the operation. Hence the need of introducing yet another layer of complexity–the VDOM mediator–to mitigate the impact of arguable frontend architecture.

      The VDOM is, yes, a way to optimize performance. But on top of an arguably required complex frontend framework. Not questioning here the relevance of using React/Angular, but vanilla-JS pages are much more efficient in updating the UI for two reasons:

      • Their changes are by design surgical
      • Do not (need to) use the VDOM

      In vanilla-JS pages, the VDOM is implicit.

      Published by D. Esposito

      Software person since 1992

      Leave a comment