Wydajność Vue 3 w 2026: Vapor Mode, Alien Signals i koniec Virtual DOM
Szczegółowa analiza wydajności trybu Vapor w Vue 3.6: jak eliminuje Virtual DOM, system reaktywności Alien Signals, benchmarki w porównaniu z Solid.js oraz praktyczne techniki optymalizacji aplikacji produkcyjnych.

Vue 3.6 Vapor Mode to najważniejsza zmiana w architekturze renderowania od czasu, gdy Vue przyjęło Virtual DOM w wersji 2. Kompilując komponenty Single File Component bezpośrednio do imperatywnych operacji na DOM, Vapor Mode eliminuje narzut diffingu, który przez lata definiował potok renderowania Vue. W połączeniu z przepisaniem systemu reaktywności opartym na Alien Signals, Vue 3.6 osiąga w benchmarkach poziom Solid.js i Svelte 5 — bez konieczności uczenia się przez programistów nowego API.
Vapor Mode to opcjonalna strategia kompilacji w Vue 3.6, która całkowicie omija Virtual DOM. Komponenty skompilowane w Vapor Mode łączą każdą zależność reaktywną bezpośrednio z dokładnym węzłem DOM, na który wpływają, generując precyzyjne aktualizacje bez przechodzenia po drzewie. Włącza się to jednym atrybutem: <script setup vapor>.
Jak działa Virtual DOM w Vue — i dlaczego stał się wąskim gardłem
Wzorzec Virtual DOM (VDOM), spopularyzowany przez React i przyjęty przez Vue 2, tworzy lekką reprezentację rzeczywistego drzewa DOM w JavaScript. Przy każdej zmianie stanu Vue generuje nowe drzewo VDOM, porównuje je z poprzednim i nakłada zmiany tylko na zmodyfikowane węzły rzeczywistego DOM.
To podejście sprawdza się w większości aplikacji. Algorytm diffingu działa w czasie O(n), a kompilator Vue już optymalizuje statyczne poddrzewa, usuwając je ze ścieżki diffowania. Narzut kumuluje się jednak w określonych scenariuszach:
- Duże listy z setkami wierszy wyzwalają pełne porównania poddrzew przy każdej aktualizacji
- Częste zmiany stanu (animacje, dane w czasie rzeczywistym) generują churn VDOM, który musi sprzątać garbage collector
- Głębokie drzewa komponentów zwielokrotniają koszt przechodzenia po drzewie i generowania zmian
Kompilator szablonów Vue 3 wprowadził kilka optymalizacji VDOM — static hoisting, patch flags, block trees — które ograniczyły zbędną pracę. Przyniosły one mierzalne usprawnienia, ale podstawowa architektura wciąż wymagała generowania, porównywania i odrzucania obiektów JavaScript w każdym cyklu renderowania.
Vue 3.6 Vapor Mode: skompilowanie Virtual DOM-u na wylot
Vapor Mode przyjmuje zupełnie inne podejście. Zamiast kompilować szablony do funkcji renderujących zwracających węzły VDOM, kompilator Vapor generuje kod, który bezpośrednio tworzy i aktualizuje elementy DOM. Każde powiązanie reaktywne odpowiada konkretnej mutacji DOM — bez potrzeby reprezentacji pośredniej.
Oto jak standardowy komponent Vue kompiluje się odmiennie w każdym z trybów:
<!-- 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>W klasycznym trybie VDOM ten szablon kompiluje się do funkcji renderującej zwracającej drzewo wirtualnych węzłów. Przy każdym kliknięciu Vue tworzy nowe drzewo VDOM, porównuje je z poprzednim, wykrywa zmianę zawartości tekstowej i nakłada zmianę na rzeczywisty DOM.
W Vapor Mode kompilator generuje coś bliższego temu:
// 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)Efekt reaktywny łączy count bezpośrednio z text.nodeValue. Bez tworzenia VDOM, bez diffingu, bez nakładania zmian. Zmiana stanu wyzwala dokładnie jedną mutację DOM.
Włączanie Vapor Mode w projekcie
Vapor Mode działa na poziomie komponentu. Istnieją dwie strategie integracji:
import { createVaporApp } from 'vue'
import App from './App.vue'
createVaporApp(App).mount('#app')import { createApp, vaporInteropPlugin } from 'vue'
import App from './App.vue'
createApp(App)
.use(vaporInteropPlugin)
.mount('#app')Podejście hybrydowe umożliwia stopniową migrację. Komponenty krytyczne dla wydajności — tabele danych, dashboardy czasu rzeczywistego, widoki bogate w animacje — mogą przejść na Vapor, podczas gdy reszta aplikacji nadal korzysta ze standardowego środowiska uruchomieniowego VDOM. Oba typy komponentów współistnieją w tym samym drzewie komponentów.
Vapor Mode wymaga Composition API z <script setup>. Options API, app.config.globalProperties, getCurrentInstance() oraz zdarzenia cyklu życia na poziomie elementu (@vue:mounted itp.) nie są obsługiwane. Dyrektywy niestandardowe korzystają z innego interfejsu, który przyjmuje reaktywne gettery zamiast obiektów bindowania. Suspense działa, gdy komponenty Vapor są zagnieżdżone w rodzicu VDOM, ale nie w czysto Vaporowych aplikacjach.
Alien Signals: nowy silnik reaktywności Vue
Vue 3.6 wprowadza obok Vapor Mode drugą dużą zmianę: pełne przepisanie @vue/reactivity w oparciu o bibliotekę Alien Signals. Stworzona przez Johnsona Chu, Alien Signals implementuje algorytm reaktywności push-pull, który redukuje zarówno alokację pamięci, jak i narzut obliczeniowy.
Model push-pull działa w dwóch fazach:
- Faza push — Gdy sygnał (źródło reaktywne) się zmienia, propaguje flagę „dirty" do wszystkich zależnych właściwości computed. To przejście jest tanie: jedynie przełącza flagi logiczne, nie uruchamiając żadnych obliczeń.
- Faza pull — Gdy właściwość computed zostaje odczytana, sprawdza swoją flagę dirty. Jeśli jest dirty, przelicza się. Jeśli jest clean, natychmiast zwraca wartość z pamięci podręcznej.
Ten projekt eliminuje zbędne przeliczenia. W systemie reaktywności Vue 3.5 właściwość computed zależna od trzech sygnałów przeliczała się przy każdej zmianie dowolnego sygnału, nawet jeśli wynik pozostawał ten sam. Alien Signals przelicza tylko wtedy, gdy wartość jest faktycznie odczytywana, a przynajmniej jedna zależność się zmieniła.
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'Zmieniła się również wewnętrzna struktura danych. Alien Signals zastępuje śledzenie zależności oparte na Set listami dwukierunkowymi, co zmniejsza zużycie pamięci na każdą zależność reaktywną i poprawia szybkość przechodzenia podczas sprzątania.
Wyniki benchmarków: Alien Signals w praktyce
Liczby z benchmarków wersji beta Vue 3.6 pokazują spójne usprawnienia względem Vue 3.5:
| Metryka | Vue 3.5 | Vue 3.6 (Alien Signals) | Poprawa | |---|---|---|---| | Pamięć na reaktywny ref | Punkt odniesienia | -14% | Mniejsza alokacja | | Przeliczanie computed | Punkt odniesienia | -20% śr. | Mniej zbędnych przebiegów | | Montowanie komponentów (100k) | ~300ms | ~100ms | 3x szybciej | | First Contentful Paint | Punkt odniesienia | typowo 0,7s | Mniejszy narzut frameworka | | Bazowy rozmiar bundla | ~16KB | <10KB | -37% |
Te zyski obowiązują automatycznie we wszystkich aplikacjach Vue 3.6. W przeciwieństwie do Vapor Mode, który wymaga włączania per komponent, system reaktywności Alien Signals jest domyślny w Vue 3.6.
Gotowy na rozmowy o Vue.js / Nuxt.js?
Ćwicz z naszymi interaktywnymi symulatorami, flashcards i testami technicznymi.
Praktyczne techniki optymalizacji wydajności w Vue 3
Vapor Mode i Alien Signals adresują narzut na poziomie frameworka, ale wydajność na poziomie aplikacji wciąż zależy od tego, jak skonstruowane są komponenty. Te techniki dotyczą zarówno komponentów VDOM, jak i Vapor.
Płytka reaktywność dla dużych struktur danych
Głęboka reaktywność opakowuje każdą zagnieżdżoną właściwość w Proxy. W przypadku dużych zestawów danych — odpowiedzi API, obiektów konfiguracyjnych, stanu w pamięci podręcznej — tworzy to tysiące zbędnych opakowań Proxy. shallowRef i shallowReactive ograniczają reaktywność do referencji najwyższego poziomu.
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
}
}Dyrektywa v-memo dla kosztownego renderowania list
W komponentach VDOM renderujących długie listy v-memo buforuje wyniki renderowania poddrzew na podstawie wartości zależności. VDOM całkowicie pomija diffing dla zapamiętanych poddrzew, których zależności się nie zmieniły.
<!-- 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>Tablica v-memo [product.id === selectedId, product.price] mówi Vue: nie renderuj ponownie tego elementu, dopóki nie zmieni się stan zaznaczenia lub cena. Dla listy 500 produktów, z których tylko jeden zostaje zaznaczony, redukuje to pracę VDOM z 500 diffów poddrzew do 2 (poprzednio i nowo zaznaczonego elementu).
Komponenty asynchroniczne z Suspense do dzielenia kodu
Leniwe ładowanie ciężkich komponentów utrzymuje początkowy bundle szczupłym. defineAsyncComponent z Vue w połączeniu z Suspense deklaratywnie obsługuje stan ładowania.
<!-- 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 kontra VDOM: kiedy stosować które podejście
Vapor Mode nie jest uniwersalnym zamiennikiem Virtual DOM. Każdy tryb kompilacji ma mocne strony pasujące do różnych profili komponentów.
| Scenariusz | Zalecany tryb | Powód | |---|---|---| | Tabele danych (1000+ wierszy) | Vapor | Eliminuje narzut VDOM na wiersz | | Dashboardy czasu rzeczywistego | Vapor | Częste aktualizacje zyskują na bezpośrednim bindowaniu DOM | | Komponenty bogate w animacje | Vapor | Brak obciążenia GC przez churn VDOM | | Zewnętrzne biblioteki komponentów VDOM | VDOM | Warstwa interop zwiększa złożoność | | Komponenty używające Options API | VDOM | Vapor wymaga Composition API | | Formularze ze złożoną walidacją | Dowolny | Minimalny narzut renderowania w obu trybach | | Strony ze statyczną treścią | Dowolny | SSG/SSR wykonuje główną pracę |
Zalecana ścieżka migracji: najpierw sprofiluj aplikację za pomocą zakładki Performance w Vue DevTools. Zidentyfikuj komponenty o najwyższym czasie renderowania i częstotliwości ponownego renderowania. Przekształć je na Vapor Mode, zmierz wpływ i rozszerzaj od tego punktu.
Pytania rekrutacyjne: wydajność Vue 3 i Vapor Mode
Te pytania odzwierciedlają to, o co zespoły inżynierskie pytają w 2026 roku, oceniając kompetencje w Vue. Każda odpowiedź podsumowuje rozumowanie techniczne, którego oczekuje rekruter.
P: Jaki problem rozwiązuje Vapor Mode i czym różni się od optymalizacji VDOM, które Vue już miało?
Kompilator VDOM w Vue 3 już optymalizował statyczne poddrzewa, dodawał patch flags i implementował block trees, by pomijać zbędne diffy. Zmniejszało to narzut VDOM, ale go nie eliminowało — każda zmiana stanu nadal wymagała tworzenia węzłów VDOM, przechodzenia po drzewie i generowania zmian. Vapor Mode usuwa cały ten potok. Kompilator mapuje stan reaktywny bezpośrednio na mutacje DOM, więc zmiana stanu wyzwala dokładnie potrzebne operacje DOM — bez pośrednich struktur danych, bez algorytmu diffingu, bez garbage collection odrzuconych węzłów VDOM.
P: Czy komponenty Vapor i VDOM mogą współistnieć w tej samej aplikacji?
Tak. vaporInteropPlugin pozwala na oba typy komponentów w jednym drzewie komponentów. Rodzic VDOM może renderować dzieci Vapor i odwrotnie, z pewnymi zastrzeżeniami: sloty Vapor nie mogą używać slots.default() wewnątrz komponentu VDOM (zamiast tego należy użyć renderSlot), a interoperacyjność z bibliotekami komponentów opartymi na VDOM (Vuetify, PrimeVue) może mieć niedociągnięcia w fazie eksperymentalnej.
P: Wyjaśnij model reaktywności push-pull w Alien Signals w Vue 3.6.
Model push-pull dzieli aktualizacje reaktywne na dwie fazy. W fazie push, gdy sygnał zmienia wartość, system propaguje flagę dirty w dół przez wszystkie zależne właściwości computed — jest to tanie, bo przełącza jedynie flagi logiczne. W fazie pull, gdy wartość computed zostaje faktycznie odczytana, sprawdza, czy jest dirty. Jeśli jest dirty, przelicza się z zależności. Jeśli jest clean, zwraca wartość z pamięci podręcznej. Pozwala to uniknąć gorliwego przeliczania właściwości computed, które w danym cyklu aktualizacji mogą nigdy nie zostać odczytane.
P: Kiedy należy użyć shallowRef zamiast ref w aplikacji Vue 3?
shallowRef jest właściwy, gdy struktura danych jest duża i tylko ponowne przypisanie na najwyższym poziomie powinno wyzwalać reaktywność — pamięci podręczne odpowiedzi API, obiekty konfiguracyjne i duże tablice, w których mutacje poszczególnych elementów są kontrolowane ręcznie za pomocą triggerRef(). Głęboka reaktywność opakowuje każdą zagnieżdżoną właściwość w Proxy, co stanowi zbędny narzut dla danych, które będą zastępowane w całości, a nie mutowane w miejscu.
Ćwicz więcej pytań rekrutacyjnych z Vue.js dotyczących composables i wzorców reaktywności na SharpSkill.
Oficjalny przewodnik po wydajności Vue.js omawia dodatkowe techniki optymalizacji, w tym stabilność propsów, wirtualne przewijanie i streaming SSR. Informacje o wydaniu wersji beta Vue 3.6 dokumentują każde API Vapor Mode i znane ograniczenia.
Zacznij ćwiczyć!
Sprawdź swoją wiedzę z naszymi symulatorami rozmów i testami technicznymi.
Podsumowanie
- Vapor Mode kompiluje SFC Vue do bezpośrednich operacji na DOM, całkowicie eliminując tworzenie, diffing i nakładanie zmian Virtual DOM
- Włącza się go per komponent za pomocą
<script setup vapor>— bez migracji w skali całej aplikacji - Alien Signals, nowy domyślny silnik reaktywności, zmniejsza zużycie pamięci o 14% i poprawia wydajność właściwości computed dzięki leniwemu przetwarzaniu push-pull
- Używaj
shallowRefdla dużych struktur danych,v-memodla kosztownego renderowania list idefineAsyncComponentdo dzielenia kodu — te wzorce obowiązują w obu trybach - Vapor Mode wymaga Composition API z
<script setup>. Options API,getCurrentInstance()iglobalPropertiesnie są obsługiwane - Najpierw profiluj za pomocą Vue DevTools, przekształcaj na Vapor komponenty o największym wpływie, mierz i iteruj
- Vue 3.6 jest w fazie beta na początku 2026 roku — traktuj Vapor Mode jako eksperymentalny w aplikacjach produkcyjnych, ale już teraz zacznij budować znajomość w zespole
Tagi
Udostępnij
Powiązane artykuły

Zaawansowane Vue 3 Composables: Wzorce wielokrotnego uzytku i pytania rekrutacyjne 2026
Kompleksowy przewodnik po zaawansowanych Vue 3 Composables z wzorcami wielokrotnego uzytku, asynchroniczna obsluga bledow, Dependency Injection, walidacja formularzy i aktualne pytania rekrutacyjne na 2026 rok.

Nuxt 4 w 2026: Nowa Struktura Katalogow i Migracja z Nuxt 3
Kompletny przewodnik po Nuxt 4: nowa struktura katalogu app/, migracja krok po kroku z Nuxt 3, singleton data fetching, shallow reactivity, TypeScript context splitting, Vue Router v5, zarzadzanie meta tagami i lista kontrolna migracji.

Vue 3 Pinia vs Vuex: Nowoczesne zarządzanie stanem i pytania rekrutacyjne 2026
Porównanie Pinia i Vuex: architektura, TypeScript, Composition API, migracja, hydratacja SSR oraz najczęstsze pytania rekrutacyjne o zarządzanie stanem Vue na rok 2026.