Logo
JavaScript DOM Rendering - The Three Techniques

Browser 2025-05-22

JavaScript DOM Rendering - The Three Techniques

The following is a summary of the 3 ways JavaScript frameworks render the DOM.

Key Concepts

Rendering to the DOM: The process by which a JavaScript framework translates application state and template structure into actual visible elements in a web browser.

Declarative Rendering: A programming paradigm where you describe what the UI should look like based on the current state, rather than how to update it step-by-step. Frameworks handle the details of updating the DOM.

Templating: The structure (often using syntax like JSX or tag template literals) that defines the relationship between state and UI. Templates have static parts (fixed HTML elements) and dynamic parts (“holes” where state values are inserted).

State: The data that drives the UI. Changes in state trigger updates to the rendered UI.

DOM (Document Object Model): A programming interface for HTML and XML documents. It represents the page so that programs can change the document structure, style, and content. Directly manipulating the DOM can be slow or lead to deoptimization if not done carefully.

Deoptimization: Actions that can cause the browser’s JavaScript engine to slow down or perform less efficiently, such as forcing layout calculations by reading certain DOM properties repeatedly.

Rendering Approaches

String Inner HTML (Legacy Method)

How it works: The template is processed into a single HTML string, and this string is inserted into the DOM using innerHTML. Update mechanism: When state changes, the entire template string is regenerated and innerHTML is called again, replacing the previous content. Drawbacks: Unperformant because it recreates the entire DOM subtree, unmounting and remounting elements, leading to flickering and inefficiency, especially for large templates. (Not a modern approach).

Dirty Checking / Template-Based Diffing

How it works: The framework processes the template on initial render to identify “holes” (dynamic parts) and creates bindings associated with specific DOM nodes (often using placeholder comments). On subsequent updates, the framework only compares the new values for these holes against the previous values. Update mechanism: If a value for a hole has changed, the framework directly updates the corresponding DOM node (e.g., updating a text node’s value, setting an attribute). The static parts of the template are ignored during updates. Advantages: More performant than innerHTML because it avoids recreating the entire DOM. Examples: Angular, Ember, Svelte, Lit. Lit uses tag template literals to cache static parts and focus on diffing the dynamic parts. Underlying Process: Involves processing the template (often compiled) to create or find bindings and then performing a diffing process on these bindings to apply updates directly to the DOM.

Virtual DOM Diffing

How it works: The template (often written with hyperscript functions like createElement) is used to create a JavaScript data structure representing the desired DOM tree (the Virtual DOM). On initial render, this Virtual DOM is used to construct the actual DOM. Update mechanism: When state changes, a new Virtual DOM tree is generated. The framework then compares the new Virtual DOM tree with the previous Virtual DOM tree (a process called “diffing”). Based on the differences, the framework performs the minimal necessary updates to the actual DOM. Advantages: Abstracted from the direct DOM manipulation, allowing for more dynamic updates and easier portability to non-browser environments (like mobile or server-side rendering). While it recreates the Virtual DOM tree on every render, it only updates the necessary parts of the actual DOM. Examples: React, Vue, Inferno. Underlying Process: Two passes: 1) Create the Virtual DOM data structure, 2) Diff the new Virtual DOM against the old one and apply changes to the real DOM. Considered by the source material to be similar to dirty checking but operating on a full tree structure rather than just holes.

Fine-Grained Rendering

How it works: This approach leverages a reactive system (often based on signals and effects) to track dependencies between state and specific parts of the DOM. Templates are often compiled into highly optimized imperative code. Update mechanism: State changes (signals) automatically notify only the specific code (effects) that depends on that state. These effects then directly update the minimal necessary part of the DOM. Advantages: Highly performant as updates are very precise and avoid general diffing processes. Examples: SolidJS (popularized), Svelte 5, Vue Vapor (upcoming). Underlying Process: Compiled templates create DOM nodes and set up reactive relationships (signals and effects). When a signal updates, only the associated effects that directly modify the DOM are triggered. No diffing process is generally required.

Relationship between approaches: The source suggests Virtual DOM is similar to Dirty Checking (“2.5 ways”) as both involve diffing to minimize DOM updates, but Virtual DOM diffs a full tree while Dirty Checking often focuses on diffing specific bindings/holes identified in the template. Fine-grained rendering is presented as a distinct, more efficient approach.

Glossary of Key Terms

Bindings: Data structures or mechanisms used in rendering (particularly Dirty Checking) to associate dynamic parts (“holes”) in a template with specific locations or elements in the actual DOM, facilitating targeted updates.

Compiler: A tool used by modern JavaScript frameworks to process template syntax (like JSX or tag template literals) into optimized JavaScript code, often generating the logic for initial rendering and updates.

Declarative: A programming paradigm where you describe what the UI should be, and the framework figures out how to make it happen.

Diffing: The process of comparing two structures (e.g., a new Virtual DOM tree and a previous one, or new hole values and previous bindings) to identify the differences and determine what needs to be updated in the actual DOM.

DOM (Document Object Model): A tree-like representation of the structure of an HTML or XML document, providing an interface for JavaScript to interact with and modify the content, structure, and style of web pages.

Dirty Checking: A rendering approach where the framework tracks changes to specific dynamic parts (“holes”) in the template and directly updates the corresponding DOM elements based on those changes, avoiding full re-renders of the static parts.

Effects: In Fine-Grained Rendering, functions that run when the state they depend on (signals) changes. They are often used to perform side effects, such as directly updating the DOM.

Fine-Grained Rendering: A highly optimized rendering approach that uses a reactive system (like signals) to track dependencies and trigger updates only for the minimal necessary parts of the DOM, often compiled from a template.

Holes: Dynamic parts within a template where state values are inserted or where dynamic logic occurs. These are the parts of the template that can change over time.

Hyperscript Function (e.g., createElement): A function used in some frameworks (like React for Virtual DOM) to programmatically describe DOM elements and their structure, often used as the compilation target for template syntax like JSX.

Inner HTML: A property of DOM elements that allows you to get or set the HTML content inside that element as a string. Setting innerHTML with a new string causes the browser to parse and rebuild the DOM subtree within that element.

Rendering: The process by which a framework takes application state and template instructions and translates them into visible UI elements in the browser’s DOM.

Signals: In Fine-Grained Rendering, a type of reactive primitive that holds a value and can notify code that depends on it (observers/effects) when its value changes.

Static Parts: The fixed HTML structure and content within a template that does not change based on application state.

Tag Template Literal: A JavaScript feature used in frameworks like Lit, allowing a function to parse a template string with embedded expressions, which can be leveraged to cache the static parts of the template.

Template: The structure or syntax used to define the relationship between application state and the user interface, containing both static HTML and dynamic “holes.”

Virtual DOM: A lightweight JavaScript object or data structure that represents the desired structure of the real DOM. Frameworks use this representation to perform diffing and calculate the minimal changes needed for the actual DOM.