Da 284 richieste a 34: cosa c'era dentro un e-commerce lento
Quasi tutti gli articoli sulla velocità dicono le stesse quattro cose generiche. Questo racconta un caso solo, il mio, con i numeri misurati da Google prima e dopo. Perché il problema quasi mai è quello che ti aspetti.
Il punto di partenza
Un e-commerce funzionante, che vendeva, con le foto giuste e i prodotti giusti. E questi numeri, misurati da Google su rete mobile: 8,7 secondi perché comparisse il contenuto principale, 4,8 MB di peso per una singola pagina, 284 richieste di rete per aprire la home, 592 millisecondi di thread bloccato. Punteggio prestazioni: 47 su 100.
Il numero che conta non è quello che pensi
Non è il peso. È 284. Duecentottantaquattro volte il browser ha dovuto chiedere qualcosa a un server e aspettare la risposta. Il peso lo risolvi comprimendo; il numero di richieste lo risolvi solo togliendo roba. E togliere roba significa decidere che qualcosa non serve, che è una decisione, non un'ottimizzazione.
Cosa c'era dentro, davvero
Il grosso non erano le immagini. Erano componenti aggiuntivi, ognuno con il suo foglio di stile e i suoi script, caricati su ogni pagina anche dove quella funzione non veniva mai usata. Un modulo di contatto che carica il proprio codice anche sulla scheda prodotto. Un costruttore di pagine che carica gli stili di tutti i blocchi possibili invece che di quelli usati. Uno strumento di recensioni che interroga un server esterno per mostrare tre stelline.
La seconda causa: le catene
Non conta solo quante richieste fai, ma in che ordine. Se il foglio di stile dichiara un font, il browser scopre quel font solo dopo aver scaricato e letto il foglio di stile. Se quel foglio è a sua volta chiamato da un altro foglio, aggiungi un anello. Le catene non si vedono nel peso totale: si vedono solo nel tempo, ed è per questo che un sito «leggero» può restare lento.
Cosa ho fatto, in ordine di resa
Prima ho tolto: ogni componente aggiuntivo che faceva una cosa sola, sostituito con il codice che serviva, dove serviva. Poi ho spezzato le catene, dichiarando in anticipo le risorse critiche invece di lasciarle scoprire per ultime. Poi le immagini, in formato moderno e nella misura giusta per lo schermo. L'ordine conta: ottimizzare le immagini di un sito che fa 284 richieste è come lucidare i cerchioni di un'auto senza motore.
Il risultato, misurato
Da 8,7 a 2,7 secondi. Da 4,8 MB a 0,4. Da 284 richieste a 34. Da 592 millisecondi di thread bloccato a 0. Punteggio prestazioni da 47 a 94, e accessibilità, best practices e SEO tecnica tutte e tre a 100.
Perché 94 e non 100
Perché non ho ancora finito, e lo scrivo invece di nasconderlo. Resta il foglio di stile: circa 15 KB di regole che nessuna pagina usa e altrettante di codice non minificato, cioè scritto con spazi e commenti che al browser non servono. Il referto di Google le quantifica in 300 e 390 millisecondi. Sono lavori di rifinitura, non di struttura — e vanno fatti guardando il risultato, perché i minificatori automatici sbagliano proprio sulle regole CSS più recenti e quando sbagliano non danno errore: sparisce un'immagine e te ne accorgi tre giorni dopo. Un sito non si finisce alla consegna: si finisce quando i numeri dicono che è finito, e questi non lo dicono ancora.
Il dettaglio tecnico: dove si nasconde il tempo
Il referto di Lighthouse ha due sezioni che quasi nessuno apre e che valgono più dei punteggi. La prima è l'albero delle dipendenze di rete: mostra la catena più lunga di richieste in serie e la sua durata complessiva. È lì che si vede se una risorsa critica viene scoperta tardi — tipicamente un font dichiarato dentro il CSS, che il browser non può nemmeno iniziare a scaricare prima di aver letto il foglio di stile. Si spezza con rel="preload" sulle sole risorse davvero critiche.
La seconda è l'adattamento dinamico forzato del contenuto: compare quando del JavaScript legge una proprietà geometrica — offsetWidth, getBoundingClientRect() — subito dopo aver modificato lo stile o il DOM. Il browser è costretto a ricalcolare il layout dell'intera pagina prima di poter rispondere, e se succede dentro un ciclo il costo si moltiplica per il numero di giri. Il rimedio è sempre lo stesso: prima tutte le letture, poi tutte le scritture.
Sul lato peso, l'unità di misura utile non è il totale ma il numero di richieste bloccanti prima del primo disegno. Un foglio di stile esterno nel <head> blocca il rendering finché non è arrivato: su una connessione mobile con 150 ms di latenza, tre fogli di stile in serie sono mezzo secondo di schermo bianco prima ancora di parlare di contenuti.