Vue 3 Performance 2026: Vapor Mode, Alien Signals und das Ende des Virtual DOM

Tiefer Einblick in die Performance von Vue 3.6 Vapor Mode: wie es das Virtual DOM eliminiert, das Reaktivitätssystem Alien Signals, Benchmarks gegen Solid.js und praktische Optimierungstechniken für Produktions-Apps.

Diagramm zur Performance-Optimierung von Vue 3 Vapor Mode mit direkten DOM-Updates ohne Virtual DOM

Vue 3.6 Vapor Mode ist die bedeutendste Änderung der Rendering-Architektur, seit Vue in Version 2 das Virtual DOM übernommen hat. Indem Single File Components direkt in imperative DOM-Operationen kompiliert werden, eliminiert Vapor Mode den Diffing-Overhead, der die Rendering-Pipeline von Vue über Jahre geprägt hat. Zusammen mit der Neufassung der Reaktivität durch Alien Signals erreicht Vue 3.6 in Benchmarks Gleichstand mit Solid.js und Svelte 5 — ohne dass Entwickler eine neue API lernen müssen.

Vapor Mode auf einen Blick

Vapor Mode ist eine optionale Kompilierungsstrategie in Vue 3.6, die das Virtual DOM vollständig umgeht. In Vapor Mode kompilierte Komponenten verdrahten jede reaktive Abhängigkeit direkt mit dem exakten DOM-Knoten, den sie betrifft, und erzeugen so chirurgisch präzise Updates ohne jede Baumdurchquerung. Aktiviert wird das Ganze mit einem einzigen Attribut: <script setup vapor>.

So funktioniert das Virtual DOM von Vue — und warum es zum Engpass wurde

Das Virtual-DOM-Muster (VDOM), von React populär gemacht und von Vue 2 übernommen, erstellt eine leichtgewichtige JavaScript-Repräsentation des tatsächlichen DOM-Baums. Bei jeder Zustandsänderung erzeugt Vue einen neuen VDOM-Baum, vergleicht ihn mit dem vorherigen und patcht nur die geänderten Knoten in das reale DOM.

Dieser Ansatz funktioniert für die meisten Anwendungen gut. Der Diffing-Algorithmus läuft in O(n)-Zeit, und der Compiler von Vue optimiert statische Teilbäume bereits aus dem Diff-Pfad heraus. Doch der Overhead summiert sich in bestimmten Szenarien:

  • Große Listen mit Hunderten von Zeilen lösen bei jedem Update vollständige Teilbaum-Vergleiche aus
  • Häufige Zustandsänderungen (Animationen, Echtzeitdaten) erzeugen VDOM-Churn, den der Garbage Collector aufräumen muss
  • Tiefe Komponentenbäume vervielfachen die Kosten für Baumdurchquerung und Patch-Erzeugung

Der Template-Compiler von Vue 3 führte mehrere VDOM-Optimierungen ein — statisches Hoisting, Patch-Flags, Block-Trees — die unnötige Arbeit reduzierten. Diese brachten messbare Verbesserungen, doch die grundlegende Architektur erforderte weiterhin das Erzeugen, Vergleichen und Verwerfen von JavaScript-Objekten bei jedem Render-Zyklus.

Vue 3.6 Vapor Mode: Das Virtual DOM wegkompilieren

Vapor Mode verfolgt einen völlig anderen Ansatz. Statt Templates in Render-Funktionen zu kompilieren, die VDOM-Knoten zurückgeben, erzeugt der Vapor-Compiler Code, der DOM-Elemente direkt erstellt und aktualisiert. Jede reaktive Bindung bildet eine konkrete DOM-Mutation ab — keine Zwischenrepräsentation nötig.

So kompiliert eine Standard-Vue-Komponente unter den beiden Modi unterschiedlich:

vue
<!-- Counter.vue -->
<script setup vapor>
import { ref } from 'vue'

const count = ref(0)
const increment = () => count.value++
</script>

<template>
  <button @click="increment">
    Count: {{ count }}
  </button>
</template>

Im klassischen VDOM-Modus kompiliert dieses Template zu einer Render-Funktion, die einen virtuellen Knotenbaum zurückgibt. Bei jedem Klick erzeugt Vue einen neuen VDOM-Baum, vergleicht ihn mit dem vorherigen, erkennt die geänderte Textmenge und patcht das reale DOM.

Im Vapor Mode erzeugt der Compiler etwas, das eher so aussieht:

javascript
// Simplified Vapor compilation output
const button = document.createElement('button')
const text = document.createTextNode('Count: 0')
button.appendChild(text)

// Direct binding: reactive source -> DOM mutation
effect(() => {
  text.nodeValue = `Count: ${count.value}`
})

button.addEventListener('click', increment)

Der reaktive Effekt verdrahtet count direkt mit text.nodeValue. Keine VDOM-Erzeugung, kein Diffing, kein Patching. Die Zustandsänderung löst genau eine DOM-Mutation aus.

Vapor Mode in einem Projekt aktivieren

Vapor Mode arbeitet auf Komponentenebene. Es existieren zwei Integrationsstrategien:

vaporApp.js — Full Vapor application (no VDOM runtime)javascript
import { createVaporApp } from 'vue'
import App from './App.vue'

createVaporApp(App).mount('#app')
hybridApp.js — Mixed VDOM + Vapor componentsjavascript
import { createApp, vaporInteropPlugin } from 'vue'
import App from './App.vue'

createApp(App)
  .use(vaporInteropPlugin)
  .mount('#app')

Der hybride Ansatz ermöglicht eine schrittweise Migration. Performancekritische Komponenten — Datentabellen, Echtzeit-Dashboards, animationslastige Ansichten — können auf Vapor umgestellt werden, während der Rest der Anwendung weiterhin die Standard-VDOM-Laufzeit nutzt. Beide Komponententypen koexistieren im selben Komponentenbaum.

Einschränkungen von Vapor Mode in Vue 3.6

Vapor Mode setzt die Composition API mit <script setup> voraus. Die Options API, app.config.globalProperties, getCurrentInstance() und elementbezogene Lifecycle-Events (@vue:mounted usw.) werden nicht unterstützt. Custom Directives nutzen eine andere Schnittstelle, die reaktive Getter statt Binding-Objekte erwartet. Suspense funktioniert, wenn Vapor-Komponenten in einem VDOM-Eltern eingebettet sind, aber nicht in reinen Vapor-Anwendungen.

Alien Signals: Die neue Reaktivitäts-Engine von Vue

Vue 3.6 bringt neben Vapor Mode eine zweite große Änderung: eine vollständige Neufassung von @vue/reactivity auf Basis der Bibliothek Alien Signals. Alien Signals, entwickelt von Johnson Chu, implementiert einen Push-Pull-Reaktivitätsalgorithmus, der sowohl die Speicherzuweisung als auch den Rechenaufwand reduziert.

Das Push-Pull-Modell arbeitet in zwei Phasen:

  1. Push-Phase — Wenn sich ein Signal (eine reaktive Quelle) ändert, propagiert es ein „Dirty"-Flag an alle abhängigen Computed Properties. Diese Durchquerung ist günstig: Sie setzt lediglich boolesche Flags um, ohne Berechnungen auszuführen.
  2. Pull-Phase — Wenn eine Computed Property gelesen wird, prüft sie ihr Dirty-Flag. Ist sie dirty, berechnet sie neu. Ist sie clean, gibt sie sofort den zwischengespeicherten Wert zurück.

Dieses Design eliminiert unnötige Neuberechnungen. Im Reaktivitätssystem von Vue 3.5 hätte eine von drei Signalen abhängige Computed Property bei jeder Signaländerung neu gerechnet, selbst wenn das Ergebnis gleich blieb. Alien Signals rechnet nur dann neu, wenn der Wert tatsächlich gelesen wird und sich mindestens eine Abhängigkeit geändert hat.

reactivityComparison.tstypescript
import { ref, computed, watch } from 'vue'

const firstName = ref('Jane')
const lastName = ref('Doe')
const isActive = ref(true)

// This computed only recalculates when read AND dirty
const displayName = computed(() => {
  return isActive.value
    ? `${firstName.value} ${lastName.value}`
    : 'Inactive User'
})

// Changing isActive marks displayName as dirty
// But no computation runs until something reads displayName.value
isActive.value = false

// NOW the recalculation happens
console.log(displayName.value) // 'Inactive User'

Auch die interne Datenstruktur hat sich geändert. Alien Signals ersetzt die Set-basierte Abhängigkeitsverfolgung durch doppelt verkettete Listen, was den Speicherbedarf pro reaktiver Abhängigkeit senkt und die Durchquerungsgeschwindigkeit beim Aufräumen verbessert.

Benchmark-Ergebnisse: Alien Signals in der Praxis

Die Zahlen aus den Vue-3.6-Beta-Benchmarks zeigen durchgängige Verbesserungen gegenüber Vue 3.5:

| Metrik | Vue 3.5 | Vue 3.6 (Alien Signals) | Verbesserung | |---|---|---|---| | Speicher pro reaktivem Ref | Basiswert | -14% | Geringere Allokation | | Computed-Neuberechnung | Basiswert | -20% Ø | Weniger unnötige Durchläufe | | Komponenten-Mount (100k) | ~300ms | ~100ms | 3x schneller | | First Contentful Paint | Basiswert | typ. 0,7s | Geringerer Framework-Overhead | | Basis-Bundle-Größe | ~16KB | <10KB | -37% |

Diese Verbesserungen gelten automatisch für alle Vue-3.6-Anwendungen. Anders als Vapor Mode, das pro Komponente aktiviert werden muss, ist das Alien-Signals-Reaktivitätssystem in Vue 3.6 der Standard.

Bereit für deine Vue.js / Nuxt.js-Interviews?

Übe mit unseren interaktiven Simulatoren, Flashcards und technischen Tests.

Praktische Techniken zur Performance-Optimierung in Vue 3

Vapor Mode und Alien Signals adressieren den Overhead auf Framework-Ebene, doch die Performance auf Anwendungsebene hängt weiterhin davon ab, wie Komponenten strukturiert sind. Diese Techniken gelten sowohl für VDOM- als auch für Vapor-Komponenten.

Flache Reaktivität für große Datenstrukturen

Tiefe Reaktivität umhüllt jede verschachtelte Eigenschaft mit einem Proxy. Bei großen Datensätzen — API-Antworten, Konfigurationsobjekten, zwischengespeichertem State — erzeugt das Tausende unnötiger Proxy-Wrapper. shallowRef und shallowReactive beschränken die Reaktivität auf die oberste Referenzebene.

shallowReactivity.tstypescript
import { shallowRef, triggerRef } from 'vue'

interface Product {
  id: number
  name: string
  variants: { sku: string; price: number }[]
}

// Only the ref itself is reactive, not the nested properties
const products = shallowRef<Product[]>([])

// Fetching data — assign the new array to trigger reactivity
async function fetchProducts() {
  const response = await fetch('/api/products')
  products.value = await response.json() // triggers update
}

// Mutating nested data — must manually trigger
function updatePrice(productId: number, sku: string, newPrice: number) {
  const product = products.value.find(p => p.id === productId)
  const variant = product?.variants.find(v => v.sku === sku)
  if (variant) {
    variant.price = newPrice
    triggerRef(products) // explicit trigger required
  }
}

Die v-memo-Direktive für aufwändiges Listen-Rendering

Bei VDOM-Komponenten, die lange Listen rendern, speichert v-memo die Render-Ergebnisse von Teilbäumen anhand von Abhängigkeitswerten zwischen. Das VDOM überspringt das Diffing vollständig für memoisierte Teilbäume, deren Abhängigkeiten sich nicht geändert haben.

vue
<!-- ProductGrid.vue -->
<script setup>
import { ref } from 'vue'

const products = ref([])
const selectedId = ref(null)
</script>

<template>
  <div class="grid">
    <div
      v-for="product in products"
      :key="product.id"
      v-memo="[product.id === selectedId, product.price]"
      :class="{ selected: product.id === selectedId }"
    >
      <h3>{{ product.name }}</h3>
      <span>{{ product.price }}</span>
    </div>
  </div>
</template>

Das v-memo-Array [product.id === selectedId, product.price] weist Vue an: dieses Element nicht neu rendern, solange sich Auswahlstatus oder Preis nicht ändern. Bei einer Liste von 500 Produkten, von denen nur eines ausgewählt wird, reduziert das die VDOM-Arbeit von 500 Teilbaum-Diffs auf 2 (das zuvor und das neu ausgewählte Element).

Asynchrone Komponenten mit Suspense für Code-Splitting

Das Lazy-Loading schwergewichtiger Komponenten hält das initiale Bundle schlank. Vues defineAsyncComponent in Kombination mit Suspense behandelt den Ladezustand deklarativ.

vue
<!-- Dashboard.vue -->
<script setup>
import { defineAsyncComponent } from 'vue'

// Heavy charting library loaded only when needed
const AnalyticsChart = defineAsyncComponent(() =>
  import('./components/AnalyticsChart.vue')
)

const DataExport = defineAsyncComponent({
  loader: () => import('./components/DataExport.vue'),
  delay: 200,       // show loading after 200ms
  timeout: 10000,   // fail after 10s
})
</script>

<template>
  <Suspense>
    <template #default>
      <AnalyticsChart />
      <DataExport />
    </template>
    <template #fallback>
      <div class="skeleton-loader" />
    </template>
  </Suspense>
</template>

Vapor Mode vs. VDOM: Wann welcher Ansatz passt

Vapor Mode ist kein universeller Ersatz für das Virtual DOM. Jeder Kompilierungsmodus hat Stärken, die zu unterschiedlichen Komponentenprofilen passen.

| Szenario | Empfohlener Modus | Grund | |---|---|---| | Datentabellen (1000+ Zeilen) | Vapor | Eliminiert VDOM-Overhead pro Zeile | | Echtzeit-Dashboards | Vapor | Häufige Updates profitieren von direkter DOM-Bindung | | Animationslastige Komponenten | Vapor | Kein GC-Druck durch VDOM-Churn | | Drittanbieter-VDOM-Komponentenbibliotheken | VDOM | Interop-Schicht erhöht die Komplexität | | Komponenten mit Options API | VDOM | Vapor erfordert die Composition API | | Formulare mit komplexer Validierung | Beliebig | In beiden Modi minimaler Render-Overhead | | Statische Inhaltsseiten | Beliebig | SSG/SSR übernimmt die Hauptarbeit |

Der empfohlene Migrationspfad: zuerst die Anwendung mit dem Performance-Tab der Vue DevTools profilieren. Die Komponenten mit der höchsten Render-Zeit und Re-Render-Häufigkeit identifizieren. Diese auf Vapor Mode umstellen, die Wirkung messen und von dort ausweiten.

Interview-Fragen: Vue 3 Performance und Vapor Mode

Diese Fragen spiegeln wider, was Engineering-Teams 2026 bei der Bewertung von Vue-Expertise stellen. Jede Antwort fasst die technische Argumentation zusammen, die ein Interviewer erwartet.

F: Welches Problem löst Vapor Mode, und wie unterscheidet es sich von den VDOM-Optimierungen, die Vue bereits hatte?

Der VDOM-Compiler von Vue 3 optimierte bereits statische Teilbäume, fügte Patch-Flags hinzu und implementierte Block-Trees, um unnötige Diffs zu überspringen. Das reduzierte den VDOM-Overhead, eliminierte ihn aber nicht — jede Zustandsänderung erforderte weiterhin das Erzeugen von VDOM-Knoten, das Durchqueren des Baums und das Generieren von Patches. Vapor Mode entfernt diese gesamte Pipeline. Der Compiler bildet reaktiven State direkt auf DOM-Mutationen ab, sodass eine Zustandsänderung exakt die benötigten DOM-Operationen auslöst — keine Zwischendatenstrukturen, kein Diffing-Algorithmus, keine Garbage Collection verworfener VDOM-Knoten.

F: Können Vapor- und VDOM-Komponenten in derselben Anwendung koexistieren?

Ja. Das vaporInteropPlugin erlaubt beide Komponententypen in einem einzigen Komponentenbaum. Ein VDOM-Eltern kann Vapor-Kinder rendern und umgekehrt, mit einigen Einschränkungen: Vapor-Slots können slots.default() nicht innerhalb einer VDOM-Komponente verwenden (stattdessen renderSlot nutzen), und die Interoperabilität mit VDOM-basierten Komponentenbibliotheken (Vuetify, PrimeVue) kann in der experimentellen Phase Ecken und Kanten haben.

F: Erläutern Sie das Push-Pull-Reaktivitätsmodell der Alien Signals in Vue 3.6.

Das Push-Pull-Modell teilt reaktive Updates in zwei Phasen. In der Push-Phase propagiert das System bei einer Wertänderung eines Signals ein Dirty-Flag abwärts durch alle abhängigen Computed Properties — das ist günstig, da nur boolesche Flags umgesetzt werden. In der Pull-Phase prüft eine Computed Property beim tatsächlichen Lesen, ob sie dirty ist. Ist sie dirty, rechnet sie aus ihren Abhängigkeiten neu. Ist sie clean, gibt sie den zwischengespeicherten Wert zurück. Das vermeidet das eifrige Neuberechnen von Computed Properties, die in einem bestimmten Update-Zyklus womöglich nie gelesen werden.

F: Wann sollte shallowRef statt ref in einer Vue-3-Anwendung verwendet werden?

shallowRef ist angebracht, wenn die Datenstruktur groß ist und nur eine Neuzuweisung auf oberster Ebene Reaktivität auslösen soll — API-Antwort-Caches, Konfigurationsobjekte und große Arrays, bei denen einzelne Element-Mutationen manuell mit triggerRef() gesteuert werden. Tiefe Reaktivität umhüllt jede verschachtelte Eigenschaft mit einem Proxy, was unnötiger Overhead für Daten ist, die als Ganzes ersetzt statt an Ort und Stelle mutiert werden.

Weitere Vue.js-Interviewfragen zu Composables und Reaktivitätsmustern auf SharpSkill üben.

Weiterführende Lektüre

Der offizielle Performance-Leitfaden von Vue.js behandelt weitere Optimierungstechniken, darunter Prop-Stabilität, virtuelles Scrolling und SSR-Streaming. Die Release-Notes zur Vue-3.6-Beta dokumentieren jede Vapor-Mode-API und bekannte Einschränkung.

Fang an zu üben!

Teste dein Wissen mit unseren Interview-Simulatoren und technischen Tests.

Fazit

  • Vapor Mode kompiliert Vue-SFCs in direkte DOM-Operationen und eliminiert Erzeugung, Diffing und Patching des Virtual DOM vollständig
  • Aktivierung pro Komponente mit <script setup vapor> — keine anwendungsweite Migration erforderlich
  • Alien Signals, die neue Standard-Reaktivitäts-Engine, senkt den Speicherverbrauch um 14% und verbessert die Performance von Computed Properties durch faule Push-Pull-Auswertung
  • shallowRef für große Datenstrukturen, v-memo für aufwändiges Listen-Rendering und defineAsyncComponent für Code-Splitting nutzen — diese Muster gelten in beiden Modi
  • Vapor Mode erfordert die Composition API mit <script setup>. Options API, getCurrentInstance() und globalProperties werden nicht unterstützt
  • Zuerst mit den Vue DevTools profilieren, wirkungsstarke Komponenten auf Vapor umstellen, messen und iterieren
  • Vue 3.6 befindet sich Anfang 2026 in der Beta — Vapor Mode für Produktionsanwendungen als experimentell behandeln, aber jetzt mit dem Aufbau von Team-Know-how beginnen

Tags

#vue
#vue-3
#vapor-mode
#performance
#virtual-dom
#alien-signals
#reactivity

Teilen

Verwandte Artikel