Non si può pretendere di ottimizzare il sito altrui e lasciare il proprio lento e decrepito. Ne valerebbe anche della reputazione, motivo per cui il primo caso studio che decido di presentare su questo sito è proprio quello di SpeedyWordpress.it.
UPDATE 2019: il sito web SpeedyWordpress.it ad Aprile 2019 ha cambiato nome ed è diventato SpeedyWP.it
Questo è un sito WordPress veloce avente come base il tema best seller BeTheme e con all’attivo 11 plugin tra cui anche il famoso Yoast SEO. Tra questi nessuno fa parte della categoria performance ad eccezione di quello che mi consente di comprimere automaticamente immagini con TinyPNG.
Allora, direte voi, com’è possibile che un sito WordPress, con un tema commerciale e 11 plugin all’attivo abbia un tempo di caricamento inferiore al secondo senza utilizzare W3 Total Cache, WP-Rocket o altri plugin del genere?
La risposta la troverete continuando a leggere questo articolo. Prima però desidero farvi toccare con mano il risultato con una comparazione prima-dopo.
PRIMA
DOPO
Indice dei contenuti
L’audit è la parte più importante di qualsiasi tipologia di consulenza. Consiste nell’individuare i problemi ed iniziare a ragionare sulle soluzioni. È grazie all’audit che ogni forma di strategia diventa possibile.
Come un medico prescrive una cura solo dopo aver individuato la causa del malessere, un bravo consulente in performance agisce solo dopo aver misurato le metriche e compreso il modello di business del sito web.
Principalmente utilizzo la DevTools di Google Chrome per effettuare le mie analisi. In prima battuta verifico se la metrica DOMContentLoaded è superiore al secondo e mezzo. Se è così sono certo del fatto che il browser è in sovraccarico per una mancata ottimizzazione del percorso di rendering critico.
Per effettuare analisi che non dipendono dalle caratteristiche hardware del mio PC e dalla velocità di connessione, utilizzo in particolare il tool WebPageTest. È uno strumento indispensabile poiché se saputo usare fornisce tutti gli elementi necessari per effettuare un auditing di qualità:
E tante altre configurazioni. Insomma un tool online completo come pochi al punto che è disponibile anche un libro dal nome Using WebPageTest.
Clicca qui per visualizzare lo stato di SpeedyWordpress.it prima del processo di ottimizzazione. Mi soffermo intanto sulla prima parte del test:
Come potete constatare, tutti gli accorgimenti in termini di compressione immagini, politica di caching per il browser, HTTP/2 e persino la CDN sono stati presi. Ciononostante il DOMContentLoaded si appresta ad essere superiore ai 2 secondi e la prima percezione di visualizzazione avviene sopra i 1.200 secondi.
Non è che il sito sia lento, ve ne sono sicuramente di peggiori. Ma nelle performance vige una regola: ogni millisecondo guadagnato è importante. Questo perché oggi il sito ha un determinato quantitativo di visite, domani, quando ne avrà (si spera) molte di più, questi millisecondi guadagnati faranno la differenza nel tasso di conversione.
Il mio personale obiettivo è ottenere un tempo di caricamento inferiore al secondo con un sito WordPress tradizionale, senza risparmiare in temi, plugin, immagini e testi. “Semplicemente” ottimizzando le risorse.
Individuate le metriche da ottimizzare, procedo ad osservare il waterfall e noto che la favicon pesa 25 MB!!! Un dato inverosimile che si tramuta in uno strano bug che prontamente correggo. Ritornata alla normalità inizio a valutare quelle che sono le risorse esterne che vengono scaricate ed elaborate prima del processo di rendering.
Per motivi di spazio ho ridotto la dimensione dello screenshot ma le risorse sono ben 46. Decisamente troppe per un layout come quello di SpeedyWordpress.
Sono un sostenitore dell’ottimizzazione del percorso di rendering critico. Seppur questa è un’operazione che può essere svolta solo da un personale esperto, è l’unica in grado di fare una netta differenza tra un’applicazione web veloce per tutti i dispositivi ed una che non lo è.
L’obiettivo è snellire il carico di lavoro del browser fornendogli inizialmente le sole risorse veramente necessarie per visualizzare il contenuto della pagina e rimandare a posteriori il caricamento di quelle che non lo sono.
È tutt’altro che semplice. Vi sono risorse non critiche per il browser ma critiche per il modello di business del sito. Altre che per loro natura devono obbligatoriamente essere elaborate prima del processo di rendering.
Per speedywordpress.it ho dovuto creare una politica di ottimizzazione differente per home page, categoria di articoli, articoli singoli, pagine semplici, pagina contatti. Vi risparmio i particolari altrimenti non basterebbe un libro.
Per applicare le politiche ho utilizzato una libreria PHP che ho scritto appositamente per questi tipi di interventi. Tale libreria mi permette di modificare il codice HTML della pagina prima di restituirlo al browser, apportando i cambiamenti prefissati.
Per la home page ho prima di tutto estratto le sole regole CSS utilizzate dalla pagina ed eliminato tutti i rimanenti CSS: non servono più. Quindi ho ottenuto una pagina con un solo CSS.
Fatto questo ho applicato una politica generale per il caricamento degli script, dopo naturalmente l’opportuna analisi. Ad eccezione di jQuery, tutti gli altri script vanno rimandati all’evento onLoad.
Gli script che servono solo in determinate pagine, come quelli di Disqus per i commenti o Facebook Widget, vanno eliminati.
I fonts li scarico sul server e quelli necessari per la visualizzazione del contenuto above the fold li prioritizzo con preload, così come tutte le risorse hero, ovvero le risorse necessarie per visualizzare il contenuto primario della pagina.
Per immagini non critiche, video e iframe attivo un lazy loading. La compressione di CSS e Javascript è già impostata su Cloudflare, che utilizzo come CDN.
Il blog presenta una sidebar con tanto di Facebook Like Box. Questo script comporta tempi di caricamento eccessivi perché:
Il widget di Facebook non è fondamentale per visualizzare la pagina né tanto meno viene visualizzato in above the fold. Non è essenziale neanche per il mio modello di business. Per questo script cambio la politica e lo carico solo quando ci si trova nei suoi pressi, una sorta di lazy loading di script.
La stessa cosa faccio per gli script dei commenti nelle pagine degli articoli. La pagina contatti, invece, necessita di uno script da caricare prima del processo di rendering. Si tratta dello script di configurazione che regolamenta il form di contatti. Poco conta, richiede pochissima CPU.
Per applicare le politiche descritte sommariamente nei paragrafi precedenti, vi sono voluti 2 giorni interi di lavoro. Siti più complessi richiedono molti più studi e molto più tempo ma il risultato ne vale davvero la pena. A questo punto ho già risparmiato più di 1 secondo e mezzo.
Durante il testing mi sono accorto di un comportamento anomalo: lo header del sito nei dispositivi desktop veniva caricato dopo circa 2 secondi e solo dopo il resto del contenuto del sito, impattando negativamente sulla percezione umana della velocità:
Dopo qualche ora di autiding sono giunto al nocciolo dei problema. Durante il caricamento della pagina da dispositivi desktop, lo header in BeTheme possiede una classe dal nome loading che da CSS nativo è impostata in display: none.
Questo perché uno script del tema, js/scripts.js, si occupa di calcolare dinamicamente la sua dimensione. Siccome la politica generale forza che tutti gli script, ad eccezione di pochi eletti, vengano caricati all’evento onLoad, anche l’elaborazione di questo veniva ritardata.
Di conseguenza lo header veniva caricato circa 2 secondi dopo, in concomitanza di tale evento. La prima soluzione che viene in mente è quella di forzare il caricamento dello script prima dell’evento onLoad.
Il problema di questa soluzione è che quello script dipende a sua volta da altri script che a loro volta dipendono da altri script, ritardando di circa mezzo secondo il tempo di visualizzazione.
Per risolvere il problema ho forzato da CSS la dimensione dello header, che lo script calcolava intorno all’80%. Risultato? Risparmiato 1 secondo di tempo sul tempo di visualizzazione dello header che adesso viene visualizzato in 0.8 secondi.
Osservate voi stessi la differenza di percezione tra il prima e il dopo.
PRIMA
DOPO
SpeedyWordpress.it è ospitato su un VPS geolocalizzato in Germania, che a sua volta ospita altri siti web. Il traffico web di questo sito è per la maggior parte effettuato da utenti che si connettono dall’Italia, motivo per cui ho deciso di utilizzare Cloudflare.
Quest’ultimo mi consente di servire file statici più velocemente grazie ai suoi numerosi server presenti direttamente in Italia, velocizzando il tempo di risposta.
Il problema rimane per il codice HTML della pagina principale, che ad ogni nuova richiesta viene elaborato dal PHP e dalle numerose query SQL che WordPress, temi e plugin sistematicamente fanno. In più l’overhead della mia libreria che in runtime applica le politiche di ottimizzazione.
Per risolvere il problema avrei potuto optare per installare una cache HTML come WP Super Cache, a mio parere uno dei plugin più efficaci quanto semplici. Alternativamente avrei potuto installare memcached e connetterlo a WordPress con il plugin Batcache.
Siccome ho accesso pieno al VPS ho deciso di utilizzare FastCGI Cache di Nginx, velocizzando il tempo di risposta del 150%. Dopo la prima elaborazione, infatti, una copia della pagina viene salvata dal web server nel path di cache.
Quando viene richiesta nuovamente, anziché essere elaborata da zero viene direttamente pescata dalla cache e inviata al client, senza avviare processi ulteriori o installare servizi come Varnish Cache. Essendo un VPS meno efficiente di un server dedicato, meno processi attivi abbiamo e meglio è.
In ogni caso il server presenta uno stack con Nginx + PHP-FPM 7.2 + MariaDB, tutti configurati ad-hoc per sfruttare a pieno il numero di Virtual Core e RAM. Di seguito lo screenshot del test finale di WebPageTest al completamento dei processi di ottimizzazione.
L’ottimizzazione per dispositivi mobile è oggi fondamentale più che mai. Google ha inoltre ufficializzato la notizia che a partire da Luglio 2018 la velocità sarà fattore di ranking anche per le ricerche effettuate a mobile.
Ad essere sinceri, l’ottimizzazione cui sopra unita ad una corretta politica di preloading delle risorse hero, ha già dato vita ad un sito tranquillamente navigabile da mobile. Di seguito lo screenshot di un test effettuato con Lighthouse, il software di autid presente nella DevTools di Google Chrome:
Altro test è stato condotto utilizzando Test My Site di Google, un tool in grado di calcolare anche la stima del numero di visitatori persi calcolando un punteggio di velocità e confrontandolo con quelli di siti dello stesso settore. Il grado di affidabilità è del 90%.
Anche in questo caso i risultati sono più che soddisfacenti.
Come ultima chicca ho implementato una progressive web application appositamente realizzata per questo sito web. Grazie al service worker adesso i visitatori ritornanti scaricheranno dal server solo le risorse HTML mentre utilizzeranno la cache per tutto il resto.
In caso di connessione assente, anche le risorse HTML verranno scaricate dalla cache rendendo di fatto il sito web veloce come un’APP nativa.
SpeedyWordpress.it è un sito WordPress dalle caratteristiche semplici la cui però consulenza in performance non è stata semplice come installare un plugin.
A seguire casi studio di siti web molto più complessi e con un uso massivo di pubblicità ed alto traffico, la cui ottimizzazione si tramuta in un vero e proprio aumento dei fatturati.
Per gli amanti di GTMetrix, cliccando qui potrete trovare il test con il relativo punteggio di PageSpeed Insight e YSlow.