Si parla molto di plugin di cache, di CDN, di immagini in WebP. Si parla raramente della decisione, a monte di tutte, che determina il resto: il tema. Prima di una singola riga di contenuto, il tuo tema stabilisce che cosa un browser dovrà scaricare, interpretare, compilare ed eseguire per disegnare la pagina. E tra tutte le sue scelte tecniche, una pesa più delle altre sulla velocità: il modo in cui spedisce il suo JavaScript.
Ci sono due famiglie. I temi che dividono il loro codice in piccoli pezzi caricati su richiesta, e i temi che ammassano tutto in un unico blocco, il famoso main.js, theme.js o bundle.min.js che governa il menu, lo slider, il lightbox, le tab, i form, le animazioni allo scroll e le chiamate AJAX. Questa seconda famiglia ti blocca su un tetto di prestazioni basso. Ecco perché, e come coglierlo prima di impegnarti.
Ottimizzare con precisione significa poter dividere
Una buona ottimizzazione front-end non è mai un singolo interruttore. È un lavoro chirurgico: tieni ciò che è visibile subito, rimanda il resto, rimuovi ciò che non viene usato affatto. In concreto, su una pagina ben ottimizzata vogliamo poter:
- Caricare lo stretto minimo affinché la parte alta della pagina (l'ATF, above the fold) sia disegnata e interattiva il più rapidamente possibile.
- Ritardare tutto ciò che non serve immediatamente (un carosello nel footer, una chat, un widget di condivisione) fino alla prima interazione o al primo scroll.
- Non caricare affatto ciò che non compare nella pagina corrente (lo script della galleria su una pagina che non ha galleria).
Queste tre leve condividono un prerequisito: il codice deve essere divisibile. Puoi ritardare un pezzo solo se esiste come pezzo. Puoi eliminare uno script condizionale solo se era stato accodato in modo condizionale. Tutta la finezza sta lì. Un tema monolitico elimina il prerequisito. Non ci sono più pezzi, c'è un blocco.
Anatomia di un monolite
Apri la scheda Network di un sito, filtra su JS, e guarda il peso del file più grande che il tema spedisce. Su un tema monolitico vedrai un unico file che concentra l'essenziale:
acme-theme/assets/js/main.min.js 287 KB <- everything
jquery.min.js 89 KB
jquery-migrate.min.js 13 KBQuel file non fa una cosa sola. Ne fa venti. E soprattutto, sono collegate tra loro nello stesso scope, nella stessa closure, nella stessa catena di dipendenze jQuery. Il menu a tendina condivide la sua inizializzazione con lo slider dell'hero, che condivide la propria con il modulo delle testimonianze, che dipende da un plugin di scroll, che dipende da jQuery, che dipende da jQuery Migrate. Rimuovi un mattone e gli altri crollano.
È qui che la strategia di ottimizzazione va a sbattere contro il muro. Riprendiamo le nostre tre leve. Ritardare tutto: puoi rimandare l'intero blocco fino alla prima interazione, ma allora la prima interazione (un semplice clic sul menu burger) paga, in un colpo solo, lo scaricamento, il parsing, la compilazione e l'esecuzione degli interi 287 KB. L'utente clicca, e nulla risponde mentre il main thread digerisce un carosello di cui non ha alcun bisogno. Hai spostato il problema, non l'hai risolto. Non ritardare nulla: il blocco viene eseguito al caricamento, gonfia il TBT (Total Blocking Time), ritarda l'interattività, e se tocca il DOM sopra la piega, degrada l'LCP. Dividere con precisione: impossibile, non c'è nulla da dividere. È tutto o niente.
Il vero costo è il parsing, non lo scaricamento
Un equivoco duro a morire: "300 KB di JS compresso, va benissimo, non è nulla da scaricare." Lo scaricamento non è il problema principale. Il JavaScript ha un costo che le immagini non hanno: deve essere interpretato, compilato ed eseguito sul main thread, proprio quello che deve rispondere alle interazioni dell'utente.
Un byte di immagine viene decodificato su un thread laterale. Un byte di JS potenzialmente blocca l'interattività. Su un mobile di fascia media, interpretare ed eseguire 300 KB di JS applicativo si misura in centinaia di millisecondi, non in peso di rete. E un monolite ti fa pagare quel costo per intero, per codice che, l'80 % delle volte, non ha nulla a che vedere con la pagina a schermo.
"Ma un unico file è meglio per HTTP/2, no?"
Un'obiezione legittima, e merita una risposta onesta piuttosto che una liquidazione. Sì, storicamente, ridurre il numero di richieste era buona pratica, e sì, concatenare aveva senso su HTTP/1.1. Ma due cose sono cambiate. Primo, HTTP/2 e HTTP/3 fanno multiplexing: diversi piccoli file in parallelo non costano più il prezzo delle richieste sequenziali di un tempo. L'argomento delle "meno richieste" ha in gran parte perso la sua forza.
Poi, e questo è il punto decisivo, il vero costo del JS non è la richiesta, è l'esecuzione. Dieci piccoli script di cui ne esegui solo due costano molto meno di uno solo grande che esegui per intero. La granularità non serve a fare più richieste, serve a eseguire meno codice. È un beneficio diverso, e sopravvive perfettamente a HTTP/2.
Tre casi concreti
Caso A: il carosello fantasma
Un tema all-in-one carica il suo bundle completo su ogni pagina, carosello incluso. Ma il carosello esiste solo sulla home page.
Sulle 40 pagine di articoli del blog, quel codice viene scaricato, interpretato, compilato, e mai usato. La scheda Coverage di Chrome lo conferma: dal 60 all'80 % del file è marcato come "unused".
Un tema modulare semplicemente non avrebbe accodato quello script fuori dalla home page.
Caso B: il menu tenuto in ostaggio
Un sito vuole ritardare il suo JavaScript non critico. Problema: il menu burger mobile e il lightbox della galleria vivono nello stesso file.
Ritarda il file e rompi il menu, l'elemento più critico dell'above-the-fold su mobile. Non ritardarlo e il lightbox, inutile al caricamento, sta nel percorso critico.
L'accoppiamento proibisce l'unica decisione che avrebbe senso: menu subito, lightbox dopo.
Su un tema di questo tipo, il sintomo classico è un menu burger che si apre solo al secondo tocco. Il metodo generale per trovare quale script è stato rotto da un ritardo si trova nella nostra guida sul ritardo del JavaScript.
Caso C: il controesempio che funziona
Un tema ben costruito accoda un piccolo script di navigazione (pochi KB, nessuna dipendenza da jQuery) per il menu, e carica lo script della galleria solo sulle pagine che contengono una galleria, con un defer.
Il menu è istantaneo. La galleria si carica separatamente, si ritarda senza rompere nulla, e sparisce del tutto dalle pagine che non ne hanno.
Qui la piattaforma di ottimizzazione ha qualcosa su cui lavorare: può operare nel dettaglio fine perché il tema le ha lasciato delle maniglie.
// Menu: minuscolo, senza jQuery, sempre necessario
wp_enqueue_script( 'acme-nav', $uri.'/nav.js', array(), null, true );
// Galleria: solo dove esiste davvero una galleria, differita
if ( has_block( 'core/gallery' ) ) {
wp_enqueue_script( 'acme-gallery', $uri.'/gallery.js', array(), null, true );
}Come riconoscere un monolite prima di impegnarti
Puoi controllare un tema in pochi minuti, sulla sua demo, senza nemmeno installarlo.
- Scheda Network, filtro JS. Guarda il file più grande che il tema spedisce. Un unico file che pesa 150 KB o più, presente su ogni pagina, è un campanello d'allarme. Diversi file di dimensioni modeste sono un buon segno.
- Scheda Coverage (in DevTools, "Coverage"). Ricarica la pagina e leggi la percentuale "Unused". Se lo script grande mostra il 60 % o più di codice inutilizzato su una pagina interna, il tema carica troppo, ovunque, senza condizioni.
- Il test della pagina spoglia. Confronta il JS caricato sulla home page e su una pagina di contatto minimalista. Se è esattamente lo stesso bundle, il tema non carica nulla in modo condizionale. Scarica tutto, sempre.
- La dipendenza da jQuery. Un tema che impila jQuery, jQuery Migrate e una pila di plugin jQuery in un'unica catena è quasi sempre monolitico nello spirito, anche quando divide i suoi file. Quelle dipendenze si tengono per mano e rifiutano di essere divise.
- Leggere il codice, se accessibile. Guarda come sono registrati gli script. Un unico
wp_enqueue_scriptglobale senza alcuna condizione di pagina o componente dice tutto. Un tema serio accoda i suoi script vicino ai componenti che li usano, e sotto condizioni.
Cosa rende buono un tema, dal punto di vista del JS
- Asset granulari: diversi script mirati invece di un unico blocco.
- Caricamento condizionale: uno script è presente solo sulle pagine che usano il suo componente.
- Bassa dipendenza da jQuery, idealmente JavaScript nativo per i mattoni critici come il menu.
- Rimandabile per natura: il codice può essere rimandato senza rompere l'above-the-fold, perché l'above-the-fold non dipende da esso.
- Nulla di inutile eseguito al caricamento per la parte alta della pagina.
- Hook puliti, che permettono a una piattaforma di ottimizzazione di rimuovere, ritardare o sostituire un pezzo senza effetti collaterali.
Nessuno di questi punti riguarda il "peso" del tema nel senso di marketing. Riguardano tutti la divisibilità. Questa è la vera metrica.
In sintesi
Ottimizzare un sito significa fare scelte fini, pagina per pagina, componente per componente: questo adesso, quello dopo, quest'altro mai. Quelle scelte presuppongono che il tema abbia consegnato il suo codice come pezzi che puoi maneggiare separatamente. Un tema monolitico non consegna pezzi, consegna un unico blocco saldato, e ti condanna al tutto o niente.
Una piattaforma di ottimizzazione può fare molto anche in quel caso: servire una cache, rimandare in blocco ciò che può essere rimandato, alleggerire le immagini, stabilizzare il layout. Ma non può disfare un accoppiamento scritto nel codice del tema. Il tetto è stato fissato a monte, nel momento in cui il tema è stato scelto.
Mantys Core dà il suo meglio sui temi granulari, e aiuta comunque su quelli monolitici:
Su un tema divisibile, mantiene l'above-the-fold al minimo e ritarda il resto fino all'interazione o allo scroll, pagina per pagina.
Rimuove il CSS e il JS che la pagina corrente non usa mai, e rimanda ciò che può essere rimandato.
Su un monolite, mette comunque in cache, stabilizza il layout e rimanda in blocco, ma è il tema a fissare il tetto.
Scegliere un tema divisibile significa scegliere un tetto più alto. Tutto ciò che sta a valle si somma a partire da lì.
Commenti
È bloccato su un problema simile? Descriva la sua configurazione e ciò che osserva. Leggiamo ogni commento e rispondiamo.
Ancora nessun commento. Condivida per primo il suo caso.