Performance di Vue 3 nel 2026: Vapor Mode, Alien Signals e la fine del Virtual DOM
Analisi approfondita delle prestazioni di Vue 3.6 Vapor Mode: come elimina il Virtual DOM, il sistema di reattività Alien Signals, benchmark contro Solid.js e tecniche di ottimizzazione pratiche per app in produzione.

Vue 3.6 Vapor Mode rappresenta il cambiamento più significativo nell'architettura di rendering da quando Vue ha adottato il Virtual DOM nella versione 2. Compilando i Single File Component direttamente in operazioni DOM imperative, Vapor Mode elimina l'overhead del diffing che ha definito per anni la pipeline di rendering di Vue. Unito alla riscrittura della reattività basata su Alien Signals, Vue 3.6 raggiunge la parità nei benchmark con Solid.js e Svelte 5 — senza che gli sviluppatori debbano imparare una nuova API.
Vapor Mode è una strategia di compilazione opzionale di Vue 3.6 che aggira completamente il Virtual DOM. I componenti compilati in Vapor Mode collegano ogni dipendenza reattiva direttamente al nodo DOM esatto su cui agisce, producendo aggiornamenti chirurgici senza alcun attraversamento dell'albero. Si attiva con un singolo attributo: <script setup vapor>.
Come funziona il Virtual DOM di Vue — e perché è diventato un collo di bottiglia
Il pattern Virtual DOM (VDOM), reso popolare da React e adottato da Vue 2, crea una rappresentazione JavaScript leggera dell'albero DOM reale. A ogni cambiamento di stato, Vue genera un nuovo albero VDOM, lo confronta con il precedente e applica le patch solo ai nodi modificati nel DOM reale.
Questo approccio funziona bene per la maggior parte delle applicazioni. L'algoritmo di diffing opera in tempo O(n) e il compilatore di Vue ottimizza già i sottoalberi statici escludendoli dal percorso di diff. Ma l'overhead si accumula in scenari specifici:
- Liste estese con centinaia di righe innescano confronti completi dei sottoalberi a ogni aggiornamento
- Cambiamenti di stato frequenti (animazioni, dati in tempo reale) generano un churn del VDOM che il garbage collector deve ripulire
- Alberi di componenti profondi moltiplicano il costo dell'attraversamento dell'albero e della generazione delle patch
Il compilatore di template di Vue 3 ha introdotto diverse ottimizzazioni del VDOM — static hoisting, patch flag, block tree — che hanno ridotto il lavoro superfluo. Hanno portato miglioramenti misurabili, ma l'architettura di fondo richiedeva comunque di generare, confrontare e scartare oggetti JavaScript a ogni ciclo di rendering.
Vue 3.6 Vapor Mode: eliminare il Virtual DOM in fase di compilazione
Vapor Mode adotta un approccio del tutto diverso. Invece di compilare i template in funzioni di render che restituiscono nodi VDOM, il compilatore Vapor genera codice che crea e aggiorna direttamente gli elementi DOM. Ogni binding reattivo corrisponde a una specifica mutazione del DOM — nessuna rappresentazione intermedia necessaria.
Ecco come un componente Vue standard viene compilato in modo diverso nei due modi:
<!-- 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>Nel modo VDOM classico, questo template compila in una funzione di render che restituisce un albero di nodi virtuali. A ogni clic, Vue crea un nuovo albero VDOM, lo confronta con il precedente, rileva che il contenuto testuale è cambiato e applica la patch al DOM reale.
In Vapor Mode, il compilatore genera qualcosa di più simile a questo:
// 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)L'effetto reattivo collega count direttamente a text.nodeValue. Nessuna creazione di VDOM, nessun diffing, nessuna patch. Il cambiamento di stato innesca esattamente una mutazione del DOM.
Abilitare Vapor Mode in un progetto
Vapor Mode opera a livello di componente. Esistono due strategie di integrazione:
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')L'approccio ibrido consente una migrazione graduale. I componenti critici per le prestazioni — tabelle dati, dashboard in tempo reale, viste ricche di animazioni — possono passare a Vapor mentre il resto dell'applicazione continua a usare il runtime VDOM standard. Entrambi i tipi di componente coesistono nello stesso albero dei componenti.
Vapor Mode richiede la Composition API con <script setup>. La Options API, app.config.globalProperties, getCurrentInstance() e gli eventi di lifecycle per singolo elemento (@vue:mounted, ecc.) non sono supportati. Le direttive personalizzate usano un'interfaccia diversa che accetta getter reattivi anziché oggetti di binding. Suspense funziona quando i componenti Vapor sono incapsulati in un genitore VDOM, ma non nelle applicazioni puramente Vapor.
Alien Signals: il nuovo motore di reattività di Vue
Vue 3.6 porta con sé, accanto a Vapor Mode, una seconda grande novità: una riscrittura completa di @vue/reactivity basata sulla libreria Alien Signals. Creata da Johnson Chu, Alien Signals implementa un algoritmo di reattività push-pull che riduce sia l'allocazione di memoria sia l'overhead di calcolo.
Il modello push-pull lavora in due fasi:
- Fase push — Quando un signal (una sorgente reattiva) cambia, propaga un flag "dirty" a tutte le computed property dipendenti. Questo attraversamento è economico: si limita a invertire flag booleani senza eseguire alcun calcolo.
- Fase pull — Quando una computed property viene letta, controlla il proprio flag dirty. Se è dirty, ricalcola. Se è clean, restituisce immediatamente il valore memorizzato in cache.
Questo design elimina i ricalcoli superflui. Nel sistema di reattività di Vue 3.5, una computed property che dipende da tre signal veniva ricalcolata ogni volta che un signal cambiava, anche se il risultato restava invariato. Alien Signals ricalcola solo quando il valore viene effettivamente letto e almeno una dipendenza è cambiata.
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'Anche la struttura dati interna è cambiata. Alien Signals sostituisce il tracciamento delle dipendenze basato su Set con liste doppiamente collegate, riducendo la memoria per ogni dipendenza reattiva e migliorando la velocità di attraversamento durante la pulizia.
Risultati dei benchmark: Alien Signals nella pratica
I numeri dei benchmark della beta di Vue 3.6 mostrano miglioramenti costanti rispetto a Vue 3.5:
| Metrica | Vue 3.5 | Vue 3.6 (Alien Signals) | Miglioramento | |---|---|---|---| | Memoria per ref reattivo | Riferimento | -14% | Allocazione ridotta | | Ricalcolo computed | Riferimento | -20% medio | Meno esecuzioni superflue | | Mount dei componenti (100k) | ~300ms | ~100ms | 3x più veloce | | First Contentful Paint | Riferimento | 0,7s tipico | Overhead del framework ridotto | | Dimensione bundle base | ~16KB | <10KB | -37% |
Questi guadagni si applicano automaticamente a tutte le applicazioni Vue 3.6. A differenza di Vapor Mode, che richiede l'attivazione per ogni componente, il sistema di reattività Alien Signals è l'impostazione predefinita in Vue 3.6.
Pronto a superare i tuoi colloqui su Vue.js / Nuxt.js?
Pratica con i nostri simulatori interattivi, flashcards e test tecnici.
Tecniche pratiche di ottimizzazione delle prestazioni in Vue 3
Vapor Mode e Alien Signals affrontano l'overhead a livello di framework, ma le prestazioni a livello di applicazione dipendono ancora da come sono strutturati i componenti. Queste tecniche valgono sia per i componenti VDOM sia per quelli Vapor.
Reattività superficiale per strutture dati estese
La reattività profonda avvolge ogni proprietà annidata in un Proxy. Per dataset estesi — risposte API, oggetti di configurazione, stato in cache — questo crea migliaia di wrapper Proxy superflui. shallowRef e shallowReactive limitano la reattività al riferimento di primo livello.
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
}
}La direttiva v-memo per il rendering di liste costose
Per i componenti VDOM che renderizzano liste lunghe, v-memo memorizza in cache i risultati di rendering dei sottoalberi in base ai valori delle dipendenze. Il VDOM salta del tutto il diffing per i sottoalberi memoizzati le cui dipendenze non sono cambiate.
<!-- 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>L'array di v-memo [product.id === selectedId, product.price] dice a Vue: non rieseguire il rendering di questo elemento a meno che non cambino lo stato di selezione o il prezzo. Per una lista di 500 prodotti in cui ne viene selezionato uno solo, questo riduce il lavoro del VDOM da 500 diff di sottoalberi a 2 (l'elemento precedentemente selezionato e quello appena selezionato).
Componenti asincroni con Suspense per il code splitting
Il lazy loading dei componenti pesanti mantiene leggero il bundle iniziale. La defineAsyncComponent di Vue, abbinata a Suspense, gestisce lo stato di caricamento in modo dichiarativo.
<!-- 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: quando usare ciascun approccio
Vapor Mode non è un sostituto universale del Virtual DOM. Ogni modo di compilazione ha punti di forza adatti a profili di componenti diversi.
| Scenario | Modo consigliato | Motivo | |---|---|---| | Tabelle dati (1000+ righe) | Vapor | Elimina l'overhead VDOM per riga | | Dashboard in tempo reale | Vapor | Gli aggiornamenti frequenti beneficiano del binding DOM diretto | | Componenti ricchi di animazioni | Vapor | Nessuna pressione sul GC dovuta al churn del VDOM | | Librerie di componenti VDOM di terze parti | VDOM | Il livello di interoperabilità aggiunge complessità | | Componenti che usano la Options API | VDOM | Vapor richiede la Composition API | | Form con validazione complessa | Indifferente | Overhead di rendering minimo in entrambi i modi | | Pagine di contenuti statici | Indifferente | SSG/SSR si occupa del grosso del lavoro |
Il percorso di migrazione consigliato: profilare prima l'applicazione usando la scheda Performance dei Vue DevTools. Individuare i componenti con il tempo di rendering e la frequenza di re-render più alti. Convertirli a Vapor Mode, misurare l'impatto ed estendere da lì.
Domande da colloquio: prestazioni di Vue 3 e Vapor Mode
Queste domande riflettono ciò che i team di ingegneria chiedono nel 2026 quando valutano la competenza su Vue. Ogni risposta riassume il ragionamento tecnico che un intervistatore si aspetta.
D: Quale problema risolve Vapor Mode e in cosa si differenzia dalle ottimizzazioni del VDOM che Vue già aveva?
Il compilatore VDOM di Vue 3 ottimizzava già i sottoalberi statici, aggiungeva patch flag e implementava i block tree per saltare i diff superflui. Ciò riduceva l'overhead del VDOM ma non lo eliminava — ogni cambiamento di stato richiedeva comunque di creare nodi VDOM, attraversare l'albero e generare patch. Vapor Mode rimuove l'intera pipeline. Il compilatore mappa lo stato reattivo direttamente sulle mutazioni del DOM, così un cambiamento di stato innesca esattamente le operazioni DOM necessarie — nessuna struttura dati intermedia, nessun algoritmo di diffing, nessuna garbage collection di nodi VDOM scartati.
D: I componenti Vapor e VDOM possono coesistere nella stessa applicazione?
Sì. Il vaporInteropPlugin consente entrambi i tipi di componente in un unico albero dei componenti. Un genitore VDOM può renderizzare figli Vapor e viceversa, con alcune avvertenze: gli slot Vapor non possono usare slots.default() all'interno di un componente VDOM (usare invece renderSlot), e l'interoperabilità con le librerie di componenti basate su VDOM (Vuetify, PrimeVue) può presentare spigolosità durante la fase sperimentale.
D: Spiega il modello di reattività push-pull degli Alien Signals in Vue 3.6.
Il modello push-pull divide gli aggiornamenti reattivi in due fasi. Nella fase push, quando un signal cambia valore, il sistema propaga un flag dirty verso il basso attraverso tutte le computed property dipendenti — operazione economica, poiché si limita a invertire flag booleani. Nella fase pull, quando un valore computed viene effettivamente letto, controlla se è dirty. Se è dirty, ricalcola dalle sue dipendenze. Se è clean, restituisce il valore in cache. Questo evita di ricalcolare con anticipo computed property che potrebbero non essere mai lette in un particolare ciclo di aggiornamento.
D: Quando si dovrebbe usare shallowRef invece di ref in un'applicazione Vue 3?
shallowRef è appropriato quando la struttura dati è estesa e solo la riassegnazione di primo livello deve innescare la reattività — cache di risposte API, oggetti di configurazione e array estesi in cui le mutazioni dei singoli elementi sono controllate manualmente con triggerRef(). La reattività profonda avvolge ogni proprietà annidata in un Proxy, un overhead inutile per dati che verranno sostituiti integralmente anziché mutati sul posto.
Esercitati con altre domande da colloquio su Vue.js su composable e pattern di reattività su SharpSkill.
La guida ufficiale alle prestazioni di Vue.js tratta ulteriori tecniche di ottimizzazione, tra cui la stabilità delle prop, lo scrolling virtuale e lo streaming SSR. Le note di rilascio della beta di Vue 3.6 documentano ogni API di Vapor Mode e le limitazioni note.
Inizia a praticare!
Metti alla prova le tue conoscenze con i nostri simulatori di colloquio e test tecnici.
Conclusione
- Vapor Mode compila gli SFC di Vue in operazioni DOM dirette, eliminando del tutto creazione, diffing e patching del Virtual DOM
- Si abilita per ogni componente con
<script setup vapor>— nessuna migrazione a livello di intera applicazione - Alien Signals, il nuovo motore di reattività predefinito, riduce l'uso di memoria del 14% e migliora le prestazioni delle computed property tramite la valutazione lazy push-pull
- Usare
shallowRefper strutture dati estese,v-memoper il rendering di liste costose edefineAsyncComponentper il code splitting — questi pattern valgono in entrambi i modi - Vapor Mode richiede la Composition API con
<script setup>. Options API,getCurrentInstance()eglobalPropertiesnon sono supportati - Profilare prima con i Vue DevTools, convertire a Vapor i componenti ad alto impatto, misurare e iterare
- Vue 3.6 è in beta all'inizio del 2026 — trattare Vapor Mode come sperimentale per le applicazioni in produzione, ma iniziare fin da ora a costruire familiarità nel team
Tag
Condividi
Articoli correlati

Composable Avanzati in Vue 3: Pattern Riutilizzabili e Domande da Colloquio 2026
Guida completa ai composable avanzati di Vue 3 con pattern riutilizzabili, gestione asincrona degli errori, dependency injection con provide/inject e validazione dei form. Include domande da colloquio tecnico aggiornate al 2026.

Nuxt 4 nel 2026: nuova struttura di directory e migrazione da Nuxt 3
Analisi approfondita delle novità di Nuxt 4 nel 2026: struttura app/, data fetching con cache evoluto, reattività shallow, TypeScript rigoroso e guida alla migrazione graduale da Nuxt 3.

Vue 3 Pinia vs Vuex: Gestione dello Stato Moderna e Domande da Colloquio 2026
Pinia vs Vuex a confronto: design delle API, supporto TypeScript, performance, strategie di migrazione e domande frequenti sulla gestione dello stato Vue nei colloqui 2026.