Vue 3.6 è entrato in release candidate a luglio, e con lui Vapor Mode è finalmente feature-complete: componenti single-file che compilano direttamente in operazioni DOM, saltando del tutto il virtual DOM. Ho un motivo strano per cui la cosa mi interessa — il lavoro di Vapor l'ho fatto a mano.
Uso Vue tutti i giorni nei progetti per i clienti, quindi la 3.6 mi interessa per i motivi soliti: bundle più piccoli, aggiornamenti più rapidi. Ma da un po' di tempo scrivo a mano anche i giochi di logica di questo sito — un nonogram, una variante di campo minato, numberlink, mastermind, un cubo di Rubik 3D con risolutori integrati, un timer da speedcubing. Ogni gioco è una pagina, niente framework, niente librerie pesanti. Solo stato e manipolazione diretta del DOM. Quell'esperienza è in pratica un'anteprima di quello che fa Vapor Mode — solo che il compilatore ero io.
Cosa impari quando non c'è un virtual DOM dietro cui nasconderti
Prendiamo il nonogram. La board è una griglia di celle; un click cambia lo stato di una cella e magari aggiorna un paio di indicatori sugli indizi di riga e colonna. Nel modello mentale ingenuo dei framework, la vista è una funzione dell'intero stato della board, e qualcosa si occupa di calcolare per differenza la modifica minima. Scrivendo tutto a mano, quel modello mentale non te lo puoi permettere. Ragioni in delta: questo click cambia la classe di questa cella e questi due elementi degli indizi, nient'altro. Scrivi esattamente quelle tre operazioni DOM e hai finito.
Il campo minato è stata la stessa lezione con la posta più alta. Il mio è una variante senza indovinelli — ogni griglia generata è verificata da un risolutore, così non sei mai costretto a un 50/50. Quando un flood-fill rivela decine di celle in un colpo solo, senti ogni tocco al DOM non necessario. Quindi raggruppi: calcoli in JS puro l'insieme completo delle celle da rivelare, poi applichi i cambi di classe in un passaggio unico. Prima lo stato, poi il DOM, e solo il DOM che è cambiato davvero.
Il cubo di Rubik 3D ha spinto tutto questo al limite. Animare le rotazioni degli strati e far girare i risolutori (metodo a strati, CFOP, ottimale) significa che il lavoro interessante vive interamente nel modello di stato — il livello di rendering è una sua proiezione sottile. Una volta strutturate le cose così, il "rendering" smette di essere la parte difficile dell'applicazione.
Cosa dice tutto questo su Vapor Mode
Tre conclusioni dall'aver fatto a mano quello che ora Vapor fa in fase di compilazione.
Primo: il virtual DOM non è mai stato prima di tutto una feature di performance. È una feature di developer experience: ti permette di scrivere vista = f(stato) senza pensare ai delta. Il diffing è il prezzo che paghi per quel modello mentale, non un trucco di velocità. La scommessa di Vapor è che un compilatore possa tenere il modello dichiarativo di scrittura ed emettere il codice a delta che io scrivevo a mano — il meglio di entrambi.
Secondo: la disciplina che il codice senza framework ti impone — stato puro, DOM come proiezione — è esattamente la disciplina che rende veloci i componenti in qualunque framework. Se lo stato del tuo componente è aggrovigliato col suo DOM, nessuna strategia di rendering ti salva.
Terzo: c'è un tetto reale a quanto tutto questo conti. I miei giochi sono il caso favorevole per gli aggiornamenti diretti del DOM: mutazioni frequenti e localizzate su griglie grandi. Un form CRUD tipico si ri-renderizza così di rado che l'overhead del VDOM è rumore. Se la tua app Vue è fatta soprattutto di form e tabelle, Vapor ti ridurrà il bundle più di quanto velocizzi le interazioni — ne vale comunque la pena, ma è bene sapere quale beneficio stai comprando.
Continuerei a scrivere i giochi a mano anche dopo Vapor?
Sì — ma per una ragione diversa dalla performance. Tenere ogni gioco privo di dipendenze significa che queste pagine funzioneranno intatte anche tra dieci anni, e scrivere da solo la logica di aggiornamento è metà del divertimento. Per il lavoro di prodotto, però, Vapor è la direzione giusta: prende la strategia di rendering che il codice a basso livello ti insegna e la rende l'output di default del codice dichiarativo che scriveresti comunque.
Un avvertimento: mentre scrivo, la 3.6 è ancora in release candidate. Feature-complete non vuol dire stabile — nei progetti dei clienti non la porto finché non esce la stable, attesa in autunno.
I giochi sono tutti giocabili nella sezione giochi, se vuoi vedere in azione la versione fatta a mano del "vapor mode".