virtual DOM
{{Short description|Lightweight representation of Document Object Model}}
A virtual DOM is a lightweight JavaScript representation of the Document Object Model (DOM) used in declarative web frameworks such as React, Vue.js, and Elm.{{Cite web|title=Beginning Elm|url=http://elmprogramming.com/|access-date=2020-12-11|website=Elm Programming}} Since generating a virtual DOM is relatively fast, any given framework is free to rerender the virtual DOM as many times as needed relatively cheaply. The framework can then find the differences between the previous virtual DOM and the current one (diffing), and only makes the necessary changes to the actual DOM (reconciliation).{{Cite web|title=Virtual DOM and Internals – React|url=https://reactjs.org/docs/faq-internals.html|access-date=2020-12-11|website=reactjs.org|language=en}}{{Cite web|title=React: The Virtual DOM|url=https://www.codecademy.com/articles/react-virtual-dom|access-date=2020-12-11|website=Codecademy|language=en}} While technically slower than using just vanilla JavaScript, the pattern makes it much easier to write websites with a lot of dynamic content, since markup is directly coupled with state.
Similar techniques include Ember.js' Glimmer and Angular's incremental DOM.{{Citation|title=google/incremental-dom|date=2020-12-08|url=https://github.com/google/incremental-dom|access-date=2020-12-11}}{{Cite web|title=React Virtual DOM vs Incremental DOM vs Ember's Glimmer: Fight|url=https://auth0.com/blog/face-off-virtual-dom-vs-incremental-dom-vs-glimmer/|access-date=2020-12-11|website=Auth0 - Blog|language=en}}
History
The JavaScript DOM API has historically been inconsistent across browsers, clunky to use, and difficult to scale for large projects. While libraries like jQuery aimed to improve the overall consistency and ergonomics of interacting with HTML,{{Cite web |last=openjsf.org |first=OpenJS Foundation- |title=The jQuery Object {{!}} jQuery Learning Center |url=https://learn.jquery.com/using-jquery-core/jquery-object/ |access-date=2024-11-11 |language=en-US}} it too was prone to repetitive code that didn't describe the nature of the changes being made well and decoupled logic from markup.
The release of AngularJS in 2010 provided a major paradigm shift in the interaction between JavaScript and HTML with the idea of dirty checking.{{Cite web |date=2014-01-30 |title=Make Your Own AngularJS, Part 1: Scopes And Digest |url=http://teropa.info/blog/2013/11/03/make-your-own-angular-part-1-scopes-and-digest.html |access-date=2024-11-11 |archive-date=2014-01-30 |archive-url=https://web.archive.org/web/20140130084907/http://teropa.info/blog/2013/11/03/make-your-own-angular-part-1-scopes-and-digest.html |url-status=bot: unknown }} Instead of imperatively declaring and destroying event listeners and modifying individual DOM nodes, changes in variables were tracked and sections of the DOM were invalidated and rerendered when a variable in their scope changed. This digest cycle provided a framework to write more declarative code that coupled logic and markup in a more logical way.
While AngularJS aimed to provide a more declarative experience, it still required data to be explicitly bound to and watched by the DOM, and performance concerns were cited over the expensive process of dirty checking hundreds of variables.{{Cite web |last=Utley |first=Tatum |title=The death of AngularJS and why you should care |url=https://blog.core10.io/2019/04/10/the-death-of-angularjs |access-date=2024-11-11 |website=blog.core10.io |language=en}} To alleviate these issues, React was the first major library to adopt a virtual DOM in 2013, which removed both the performance bottlenecks (since diffing and reconciling the DOM was relatively cheap) and the difficulty of binding data (since components were effectively just objects).{{Cite AV media |url=https://www.youtube.com/watch?v=x7cQ3mrcKaY |title=Pete Hunt: React: Rethinking best practices -- JSConf EU |date=2013-10-30 |last=JSConf |access-date=2024-11-11 |via=YouTube}} Other benefits of a virtual DOM included improved security since XSS was effectively impossible and better extensibility since a component's state was entirely encapsulated.{{Cite web |title=Why did we build React? – React Blog |url=https://legacy.reactjs.org/blog/2013/06/05/why-react.html |access-date=2024-11-11 |website=legacy.reactjs.org |language=en}} Its release also came with the advent of JSX, which further coupled HTML and JavaScript with an XML-like syntax extension.
Following React's success, many other web frameworks copied the general idea of an ideal DOM representation in memory, such as Vue.js in 2014, which used a template compiler instead of JSX and had fine-grained reactivity built as part of the framework.{{Cite web |title=Reactivity in Depth — Vue.js |url=https://v2.vuejs.org/v2/guide/reactivity.html#How-Changes-Are-Tracked |access-date=2024-11-11 |website=v2.vuejs.org |language=en}}
In recent times, the virtual DOM has been criticized for being slow due to the additional time required for diffing and reconciling DOM nodes.{{Cite web |last=Harris |first=Rich |date=2018-12-27 |title=Virtual DOM is pure overhead |url=https://svelte.dev/blog/virtual-dom-is-pure-overhead |access-date=2024-11-11 |website=svelte.dev |language=en}} This has led to the development of frameworks without a virtual DOM, such as Svelte, and frameworks that edit the DOM in-place such as Angular 2.
Implementations
= React =
React pioneered the use of a virtual DOM to make components declaratively. Virtual DOM nodes are constructed using the createElement()
function, but are often transpiled from JSX to make writing components more ergonomic.{{Cite web |title=Writing Markup with JSX – React |url=https://react.dev/learn/writing-markup-with-jsx |access-date=2024-11-11 |website=react.dev |language=en}} In class-based React, virtual DOM nodes are returned from the render()
function, while in functional hook-based components, the return value of the function itself serves as the page markup.
= Vue.js =
Vue.js uses a virtual DOM to handle state changes, but is usually not directly interacted with; instead, a compiler is used to transform HTML templates into virtual DOM nodes as an implementation detail.{{Cite web |title=Rendering Mechanism |url=https://vuejs.org/guide/extras/rendering-mechanism.html |website=Vue.js}} While Vue supports writing JSX and custom render functions,{{Cite web |title=Render Functions & JSX |url=https://vuejs.org/guide/extras/render-function.html |website=Vue.js}} it's more typical to use the template compiler since a build step isn't required that way.
= Svelte =
Svelte does not have a virtual DOM, with its creator Rich Harris calling the virtual DOM "pure overhead".{{Cite web |last=Dec 27 2018 |first=Rich Harris Thu |date=27 December 2018 |title=Virtual DOM is pure overhead |url=https://svelte.dev/blog/virtual-dom-is-pure-overhead |access-date=2020-12-11 |website=svelte.dev |language=en}} Instead of diffing and reconciling DOM nodes at runtime, Svelte uses compile-time reactivity to analyze markup and generate JavaScript code that directly manipulates the DOM, drastically increasing performance.{{Cite web |last=Harris |first=Rich |date=2019-04-22 |title=Svelte 3: Rethinking reactivity |url=https://svelte.dev/blog/svelte-3-rethinking-reactivity |access-date=2024-11-11 |website=svelte.dev |language=en}}