liveBook · Manning

Patching

As explained in Build a Frontend Web Framework (From Scratch)

Patching is the process of updating existing browser DOM nodes to reflect differences between virtual DOM trees.

Patching updates existing browser DOM nodes after application state changes. Rather than destroy and rebuild the whole view, `patchDOM(oldVdom, newVdom, parentEl)` compares the previously rendered virtual tree with the new one and applies the necessary changes. This is the second part of reconciliation: diffing finds differences; patching applies them to the real DOM. section 7.3 section 7.7

Mounting creates the initial DOM once. Later state changes call `renderApp()`, which obtains a new virtual tree from `view()` and passes both trees to `patchDOM()`. That separation lets unchanged DOM nodes stay in place. section 7.3 section 8.0

Build the patcher one case at a time:

  • Compare corresponding virtual nodes, starting at the top and continuing recursively through their children. Nodes of different types cannot share a DOM node; element nodes can share one when their tag names match. section 8.5
  • When nodes cannot be reused, find the old node’s position, destroy its DOM subtree, and mount the new subtree at that position. Replacing a changed parent’s subtree keeps the algorithm simple, even when some descendants might have matched. section 8.2.3
  • When nodes can be reused, copy the old virtual node’s DOM reference to the new virtual node. For text, change the DOM node’s `nodeValue` only if its value changed. section 8.2.4
  • For elements, patch attributes, CSS classes, styles, and event listeners separately. For element or fragment children, use `arraysDiffSequence()` to determine which child operations to apply. section 8.5

Insert an error without replacing the form

Suppose validation adds an error paragraph between a form’s input and button. Mounting only at the end would put it in the wrong place, so `mountDOM()` needs an index. The new paragraph can then be inserted at child position 1. section 8.1

Listing 8.7 Patching the DOM when the top nodes are different (patch-dom.js)
import { destroyDOM } from './destroy-dom'
import { mountDOM } from './mount-dom'
import { areNodesEqual } from './nodes-equal'

export function patchDOM(oldVdom, newVdom, parentEl) {
  if (!areNodesEqual(oldVdom, newVdom)) {
    const index = findIndexInParent(parentEl, oldVdom.el)      #1
    destroyDOM(oldVdom)                              #2
    mountDOM(newVdom, parentEl, index)            #3

    return newVdom
  }
}

function findIndexInParent(parentEl, el) {
  const index = Array.from(parentEl.childNodes).indexOf(el)
  if (index < 0) {
    return null
  }

  return index
}

The initial `patchDOM()` case shows the replacement path: find the old node’s index, destroy its subtree, and mount the new subtree there. section 8.2.3

The result is an update assembled from small DOM operations rather than a whole-tree replacement. In the TODOs application, input fields no longer lose focus on every keystroke because they are updated without being replaced. section 8.0 section 8.5

How Build a Frontend Web Framework (From Scratch) covers it

How deep it goes
Builds a recursive patcher through node replacement, text updates, element properties, and child operations, favoring simple subtree replacement over exhaustive reuse.
Examples
Uses a validation error inserted between an input and button, plus JavaScript cases for subtree replacement and text updates.
What it assumes
Assumes JavaScript virtual trees, mounting, and object-and-array diff helpers; introduces the DOM patching cases incrementally.
What you can do after
Build it from scratch as `patchDOM()` to update reusable nodes and replace changed subtrees at the correct position.
How it connects
Connects virtual DOM reconciliation with diffing, DOM mounting, text nodes, element attributes, event listeners, and array differences.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Build a Frontend Web Framework (From Scratch). The section links point to the parts of the book it draws on.