Under The Hood
frontend svelte Svelte 5 (runes mode)

Svelte: no virtual DOM — what actually updates

Last updated
Prerequisites:
Basic Svelte syntax
Understanding of what a virtual DOM is and why React/Vue use it
  • svelte
  • virtual-dom
  • compiler
  • dom-updates
  • performance
  • reactivity

Read at your depth

The practical view

React and Vue build a JavaScript description of the UI (the virtual DOM) on every state change, diff it against the previous description, and then apply the minimal set of real DOM changes. Svelte skips that middle layer: the compiler analyzes each component and generates imperative code that updates the exact DOM nodes affected by a state change. So instead of 'create vnode tree → diff → patch', you get 'assign value → set this text node's data'. You write the same declarative templates, but the update path is compiled, direct, and granular.

The same idea in other frameworks

react equivalent
setState → render() builds vnode tree →
reconcile() diffs → commits DOM patches

Legacy vs modern

The same counter: vnode diff vs compiled direct updates

The virtual DOM re-creates and diffs a tree on every update; Svelte's compiler emits direct DOM instructions for exactly the bindings that changed.

before → after
Virtual DOM (React-style)
// render() returns a vnode tree; update path:
// render → createElement → reconcile → commit
Svelte compiled updates
let count = $state(0);
<button onclick={() => count++}>+1</button>

Interview gotchas

Context

The interviewer wants the precise runtime story: what artifacts the compiler produces and how a state change reaches the DOM.

The mechanical answer

Svelte compiles each component into two runtime artifacts: a create block that builds the DOM and attaches event listeners, and per-reactive-fragment update blocks. Each dynamic binding is lowered to a direct instruction such as set_text or set_attribute against a cached node reference. When a $state source changes, the runtime marks the component dirty and, on flush, executes the update blocks whose dependencies changed — the DOM statements reference nodes captured at creation, so the update is a direct property assignment, not a tree traversal. There is no representation of the UI as data between renders; the compiler's static dependency analysis replaces the runtime diff algorithm.

Trap

The trap answer is 'Svelte has no runtime at all' — it ships a runtime, just a much smaller one (signals, scheduling, transitions). Another trap: 'Svelte is always faster than React' — the vdom's diff is only one cost; component re-renders, memoization failures, and reconciliation overhead dominate, and Svelte's advantage shrinks when a tree is genuinely large and mostly static in the same way. The accurate framing is 'less work per update by construction, with compile-time knowledge replacing runtime diffing'.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.