Virtual DOM vs No Virtual DOM — Complete Guide
In this tutorial, you will learn about Virtual Dom vs No Virtual DOM. We cover key concepts, practical examples, and best practices to help you master this topic.
Virtual DOM vs No Virtual DOM compares frameworks that use compile-time compilation to direct DOM operations against runtime Virtual DOM reconciliation for UI updates.
What You'll Learn
- How frameworks like Svelte and Solid achieve reactivity without Virtual DOM
- The performance tradeoffs between the two approaches
- When the Virtual DOM adds unnecessary overhead
- How compile-time compilation changes the performance equation
Why It Matters
The Virtual DOM is not the only way to build reactive UIs. Frameworks that skip the Virtual DOM achieve better performance in many scenarios. Understanding the alternatives helps you choose the right tool.
flowchart LR A[UI Framework Approaches] --> B[Virtual DOM] A --> C[Compile-time DOM] B --> D[Runtime diffing] B --> E[Generic patches] C --> F[Direct DOM operations] C --> G[Fine-grained updates] C --> H[No runtime overhead]
How Svelte Works Without Virtual DOM
Svelte is a compiler that converts your components into imperative JavaScript that directly manipulates the DOM.
// Svelte component:
// <script>
// let count = 0;
// function increment() {
// count += 1;
// }
// </script>
// <button on:click={increment}>
// Clicked {count} times
// </button>
// Compiled output (simplified):
function createCounterComponent(target) {
let count = 0;
const button = document.createElement('button');
const text = document.createTextNode('Clicked times');
button.appendChild(text);
target.appendChild(button);
function updateCount(newValue) {
count = newValue;
// Direct DOM update — no diffing
text.textContent = 'Clicked ' + count + ' times';
}
button.addEventListener('click', () => {
updateCount(count + 1);
});
return {
destroy() {
button.remove();
}
};
}
// When count changes:
// 1. The compiler-generated code directly updates textContent
// 2. No Virtual DOM tree is created
// 3. No diffing happens
// 4. No patch objects are generated
// 5. The DOM is updated in one operation
How Solid Works Without Virtual DOM
Solid uses fine-grained reactivity with a compiled template approach.
// Solid component:
// function Counter() {
// const [count, setCount] = createSignal(0);
// return <button onClick={() => setCount(c => c + 1)}>
// Clicked {count()} times
// </button>;
// }
// Compiled output (simplified):
function Counter() {
const [count, setCount] = createSignal(0);
const button = document.createElement('button');
const text = document.createTextNode('Clicked times');
// Fine-grained subscription
createEffect(() => {
// This effect re-runs when count changes
text.textContent = 'Clicked ' + count() + ' times';
});
button.appendChild(text);
button.addEventListener('click', () => setCount(c => c + 1));
return button;
}
// Each reactive value has its own subscribers
// Only the specific DOM nodes that depend on the changed value are updated
// No component-level re-rendering
// No Virtual DOM diffing
Performance Comparison
Compare the three approaches across different scenarios.
// Scenario 1: Simple update (single text change)
// Virtual DOM (React):
// - Create new VNode tree
// - Diff against old tree
// - Determine text changed
// - Update textContent
// No Virtual DOM (Svelte):
// - Directly update textContent
// Winner: No Virtual DOM (no overhead)
// Scenario 2: Complex update (50% of tree changes)
// Virtual DOM (React):
// - Create full new VNode tree
// - Diff entire tree
// - Generate patches for changed parts
// - Apply patches
// No Virtual DOM (Svelte):
// - The compiler generates updates for each binding
// - Multiple individual DOM operations
// - Each operation is targeted
// Winner: Depends on the specific case
// Scenario 3: Large list reordering
// Virtual DOM with keys (React):
// - Efficient keyed reconciliation
// - Only move DOM nodes, don't recreate
// No Virtual DOM (Svelte):
// - Must move each DOM node individually
// - Each move is explicit in compiled code
// Winner: Virtual DOM (better at complex structural changes)
Memory Usage Comparison
Virtual DOM uses more memory due to the virtual tree.
// Memory for a component with 50 elements:
// Virtual DOM (React):
// - Two VNode trees: 50 VNodes each = 100 objects
// - Fiber nodes: 50 persistent objects
// - Patch objects during diffing: ~10-50 temporary objects
// - Total: ~200 objects
// No Virtual DOM (Svelte):
// - Generated code variables: minimal
// - Reactive subscriptions: ~10-30 objects
// - No virtual tree
// - Total: ~30 objects
// For 1000 components on a page:
// Virtual DOM: ~200,000 objects
// No Virtual DOM: ~30,000 objects
// The Virtual DOM uses 6-7x more memory
Bundle Size Comparison
No-Virtual-DOM frameworks often produce smaller bundles.
// Bundle size comparison (approximate):
// React + ReactDOM: ~40 KB gzipped
// Vue 3: ~30 KB gzipped
// Preact: ~10 KB gzipped
// Svelte (runtime): ~2 KB gzipped + compiled component code
// Solid (runtime): ~7 KB gzipped (less than 1 KB for signals)
// However, Svelte's compiled output adds code per component.
// For very small apps (1-2 components), Svelte wins.
// For very large apps (100+ components), the compiled output may be larger.
// Example: 100 components
// React: 40 KB runtime + 100 * 1 KB component code = 140 KB
// Svelte: 2 KB runtime + 100 * 3 KB compiled component = 302 KB
// At this scale, React's generic runtime is more efficient.
When to Use Each Approach
Choose based on your specific needs.
// Use Virtual DOM when:
// - You need React's ecosystem (React Native, Next.js, etc.)
// - Your app has many large, complex lists
// - You need concurrent features (transitions, Suspense)
// - Your team is experienced with React/Vue
// Use No Virtual DOM when:
// - You need maximum runtime performance
// - You're building interactive dashboards with frequent updates
// - Mobile-first where memory is constrained
// - You want smaller bundle sizes
// - You're building a new project with no framework constraints
// The gap is narrowing:
// - React 18's concurrent features add value beyond performance
// - Svelte 5 introduces runes for better reactivity
// - Solid combines fine-grained reactivity with JSX
// - The best choice depends on your specific requirements
Common Mistakes
- Assuming no-Virtual-DOM frameworks are always faster (they have tradeoffs for complex lists).
- Choosing a framework solely based on benchmark numbers without considering ecosystem and team experience.
- Thinking Virtual DOM is obsolete because Svelte and Solid exist (React and Vue are still excellent choices).
- Ignoring that compile-time optimization works best for known templates, while Virtual DOM handles fully dynamic content better.
- Micro-optimizing framework choice when application architecture matters more for performance.
Practice Questions
- How does Svelte update the DOM without Virtual DOM? It compiles components to imperative code that directly manipulates DOM nodes when reactive values change.
- What is the main advantage of no-Virtual-DOM frameworks? No runtime diffing overhead and less memory usage.
- What is the main advantage of Virtual DOM frameworks? Better handling of structural changes (list reordering) and richer ecosystem.
- When does Virtual DOM use less bundle size than Svelte? For large applications (100+ components) where the generic runtime amortizes.
Challenge
Build the same simple and complex component in React, Svelte, and Solid. Measure: initial render time, update time (single and batch), memory usage, and bundle size. Display the results in a comparison table. Draw conclusions about which approach suits which scenario.
FAQ
Mini Project
Build the same interactive data table (sortable, filterable, 1000 rows) in React (Virtual DOM) and Svelte (no Virtual DOM). Measure load time, sort time, filter time, memory usage, and frames per second during rapid updates. Display a side-by-side comparison.
What's Next
Lesson 13: Memoization and Optimization
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro