Questo articolo riassume le tecniche utilizzate e i risultati ottenuti grazie ad una serie di ottimizzazioni effettuate recentemente su un sito dinamico di dimensioni medio-grandi con l’obiettivo di migliorare la velocità globale del sito agendo su tempi medi di risposta e di caricamento delle pagine.
Il sito in questione presentava da tempo un problema di velocità, in parte dovuto a cause strutturali, acuitosi col crescere delle dimensioni del sito stesso e del numero dei suoi visitatori: alcune pagine si aprivano molto lentamente, principalmente a causa degli elevati tempi di risposta dell’applicazione lato server che interrogava in modo inefficiente una tabella di database contenente alcune decine di migliaia di record. Questo rallentava notevolmente sia la normale navigazione da parte degli utenti, sia la scansione del sito da parte dei crawler dei motori di ricerca.
Inoltre, da un’analisi del sito effettuata con l’ottimo tool GTmetrix era emerso che anche i tempi di caricamento delle pagine presentavano un discreto margine di miglioramento.
Per velocizzare il sito in maniera significativa e impattante sia sull’esperienza utente sia sulla performance SEO si è perciò deciso di intervenire su più fronti: a livello di interfaccia utente, con alcune ottimizzazioni volte ad alleggerire -per quanto possibile- il peso complessivo e comprimere i tempi di trasferimento delle pagine e degli elementi comuni (immagini, CSS e codice JavaScript); a livello di backend, riprogettando la struttura del database e ottimizzando le query utilizzate dalle pagine principali.
Tuttavia, la singola ottimizzazione che ha permesso di ottenere l’incremento di velocità di gran lunga più importante è stata l’implementazione di un sistema di caching lato server. Questo sistema crea e gestisce copie statiche dei sorgenti HTML generati dinamicamente dall’applicazione (tramite l’esecuzione di codice lato server e l’interrogazione del database) in una cache ottimizzata per l’accesso veloce in lettura servendole direttamente ai client che ne fanno richiesta, velocizzando in questo modo i tempi di risposta del sito fino a tre ordini di grandezza (da alcune decine di secondi ad alcuni centesimi).
Inoltre, sia le pagine generate dinamicamente sia quelle servite a partire da una copia statica in cache vengono erogate con intestazioni di risposta HTTP tali da permetterne il caching da parte dei client. Nello specifico, sono stati ottimizzati gli header Expires, Cache-Control, Pragma e Last-Modified.
Queste ottimizzazioni hanno comportato sia un notevole incremento soggettivo della velocità di risposta durante il browsing del sito, sia un grande risparmio della banda utilizzata dagli utenti e dai crawler dei motori di ricerca, permettendo ai primi di visualizzare più pagine per visita (a parità di tempo), e ai secondi di effettuare una scansione più efficiente (e perciò più approfondita) del sito.
Il sistema prevede infine il supporto dell’intestazione di richiesta HTTP If-Modified-Since. Si tratta di un header, contemplato dal protocollo HTTP, che permette a un client di inviare una richiesta GET condizionale, chiedendo cioè a un server di servire una copia aggiornata di una determinata risorsa solo nel caso in cui questa sia stata modificata successivamente a una certa data, passata come valore dell’intestazione nel formato HTTP-date. Il client può utilizzare come timestamp quello contenuto nell’intestazione di risposta Last-Modified della risorsa l’ultima volta che gli è stata servita.
In simili condizioni, l’applicazione che gestisce la cache lato server verificherà la data di ultima modifica della copia della risorsa nella cache (se una copia esiste) e, se tale data è uguale o antecedente a quella nel timestamp specificato dal client, risponderà così:
HTTP/1.1 304 Not Modified
In caso contrario (pagina esistente in cache, ma con data di ultima modifica più recente rispetto al timestamp specificato dal client), verrà inviata al client l’ultima copia della pagina presente nella cache, con un codice di stato HTTP 200 e un header Last-Modified opportunamente compilato.
Su un sito dinamico con un numero elevato di pagine a bassa frequenza di aggiornamento, come nel caso del sito in questione, erogare un semplice codice di stato HTTP “304 Not Modified” ai client che richiedono una risorsa di cui detengono già una copia aggiornata all’ultima versione disponibile permette:
- un ulteriore risparmio di banda;
- un consistente alleggerimento del carico sul backend.
Ovviamente tali benefici saranno tanto più significativi quanto più grandi sono le dimensioni del sito e il volume di traffico che riceve da utenti e motori di ricerca.
Un altro ottimo motivo per prevedere in un CMS il supporto per l’intestazione di richiesta If-Modified-Since è appunto il fatto che, come da tempo noto e ufficialmente confermato, anche Googlebot invia richieste siffatte, promettendo -ai siti che le supportano- crawl più veloci, efficienti e profonde.
Sul sito oggetto di questo piccolo caso di studio, i primi risultati non hanno tardato a farsi vedere nelle statistiche di scansione di Google Webmaster Tools, che hanno mostrato fin dai primi giorni:
- un incremento del numero di pagine sottoposte a scansione;
- un drastico calo del consumo di banda da parte di Googlebot: da una media di circa 1 Gigabyte/giorno (con picchi di quasi 2 GB) utilizzando la compressione gzip a circa un centinaio di MB/giorno;
- un calo dei tempi medi di scaricamento delle pagine da parte del crawler.
Anche lato web analytics sono stati riscontrati effetti positivi immediatamente dopo le ottimizzazioni effettuate. Questi gli indicatori più significativi della prima settimana, confrontati con quelli della settimana precedente:
- Visite: +8%;
- Visualizzazioni di pagina: +19%;
- Pagine/Visita: +10%;
- Tempo medio sul sito: invariato;
- Frequenza di rimbalzo: -3%.
Per chiudere in bellezza questo lungo (e probabilmente noioso) post e premiare l’eroico lettore per la sua capacità di resistenza, ecco un bel…
Consiglio per gli acquisti
Se ti interessa l’argomento SEO su siti di grandi dimensioni, portali e siti e-commerce, ti consiglio caldamente questo imperdibile videocorso realizzato dall’amico e collega Piersante Paneghel.





{ 7 comments… read them below or add one }
Gran bella presentazione! Viene naturale chiedere se ed in che modo questa tecnica è implementabile su un CMS come Joomla! e cosa bisognerebbe chiedere al proprio amministratore di spazio hosting sul lavoro da fare, se eventualmente possibile, lato server.
Ciao Simone, grazie per il commento.
Riguardo alla domanda, onestamente non ho esperienza recente su Joomla, perciò non so in quale misura tale CMS sia già ottimizzato, o ottimizzabile con le tecniche usate per il sito oggetto di questo post (basato su un CMS custom), per abbassare i tempi di generazione o di caricamento delle pagine.
anche io lavoro con Joomla, e quando hai twittato “prova anche tu a implementare un sistema di caching con if-modified-since” me lo sono appuntato come sfida personale sulla lavagna dei todo
Ciao Tambu, da una ricerca al volo pare che il supporto per l’header If-Modified-Since sia già presente nel sistema di caching integrato in Joomla 1.5, almeno stando a questo articolo: t’è andata grassa!
non trovo dove parla di quell’header, e sinceramente non avevo nemmeno controllato, dato che sta nei todo
da una veloce prova non mi risulta, almeno nella mia implementazione, ma controllerò meglio quando arriverò a quel punto della lavagna
L’articolo non menziona esplicitamente l’header
If-Modified-Since, ma dice testualmente:Grazie Giacomo per aver condiviso questa informazione.
Ci mettiamo all’opera subito. Stavamo appunto cercando una soluzione per un sito in Joomla