Sviluppo web Blog Tutorial vari sul mondo dello sviluppo web ed internet

29Apr/10

Voi siete qui: Home » Web performance » Google Best Practices » Fare leva sulla cache del browser

Fare leva sulla cache del browser

Impostando una data di scadenza negli Header HTTP per le risorse statiche si istruisce il browser al caricamento delle risorse, scaricate precedentemente, dal disco locale anzichè dalla rete.

Dettagli

I protocolli HTTP e HTTPS supportano il caching in locale delle risorse statiche del browser. Alcuni dei browser di ultima generazione (IE 7, Chrome) usano un algoritmo euristico per decidere per quanto tempo mantenere in cache tutte le risorse che non hanno una dichiarazione esplicita negli header delle risorse. Altri vecchi browser possono richiedere che la dichiarazione degli header della cache sia effettuata prima di caricare una risorsa dalla cache stessa; e alcuni potrebbero non utilizzare mai la cache per tutte le risorse via SSL.

Per poter usufruire di tutti i benefici della cache in maniera consistente per tutti i browser, raccomandiamo di configurare i propri server web di settare correttamente tutti gli header di cache ed applicarli su tutte le risorse che vi possono essere riposte, non solo una piccola parte come ad esempio le immagini. L'insieme delle risorse che possono essere riposte in cache include i file JS, CSS, immagini ed altri oggetti inclusi in file binari (file media, PDF, Flash, ecc.). Generalmente l'HTML non è statico e non si dovrebbe considerarlo come un contenuto da riporre in cache.

Il protocollo HTTP/1.1 dispone dei seguenti parametri che possono essere impostati negli header HTTP per un caching corretto:

  • ExpiresCache-Control: max-age. Questi indicano il tempo di validità di una risorsa, il periodo in cui il browser potrà usare una risorsa riposta in cache senza controllare se ve n'è una più aggiornata disponibile nel web server. Hanno un effetto "forte" in quanto vengono applicati incondizionatamente; quando vengono settati, ed una risorsa riposta in cache, il browser non eseguira più nessuna richiesta GET per quella risorsa finchè non sarà raggiunta l'expiry date oppure la maximun age.
  • Last-ModifiedETag. Questi indicano alcune caratteristiche della risorsa che il browser controlla per determinare se i file sono gli stessi. Il Last-Modified header è sempre una data.Mentre l' ETag header può essere qualsiasi valore che identifica univocamente una risorsa (la versione del file o l'hash del contenuto sono valori tipici). Last-Modified è un parametro "debole" in quanto i browser applicano un controllo euristico per determinare se caricare la risorsa dalla cache o meno. (Gli algoritmi sono differenti da browser a browser.) Tuttavia questo parametro permette al browser di aggiornare correttamente le proprie risorse in cache effettuando richieste GET al server web in maniera condizionale quando l'utente ricarica la pagina. Questo tipo di richieste GET non danno come risposta l'intera risorsa fino a che la risorsa non è cambiata nel server e avranno un tempo di attesa minore di una GET normale.

E' importante specificare uno dei parametri tra ExpiresCache-Control e un altro tra Last-ModifiedETag per tutte le risorse cachabili. E' rindondante specificarli entrambi in tutti e due i casi.

Raccomandazioni

Impostare i valori di cache negli header HTTP per tutte le risosrse statiche.

Per tutte le risorse cachabili raccomandiamo le seguenti impostazioni:

  • Impostare Expires ad un valore minimo di un mese e successivamente ad un anno in futuro. (Preferiamo "Expires" rispetto a "Cache-Control: max-age" perchè è maggiormente supportato.) Non settarlo a più di un anno in futuro, questo viola le linee guida dettate dalle RFC. Se si conosce esattamente quando una risorsa scaderà impostare il valore di "Expires" a meno di un anno è corretto. Ma se si pensa che una risorsa cambierà spesso ma non si conosce quando bisogna impostare un lungo periodo di Expires ed utilizzare la tecnica di URL Fingerprinting (descritta sotto). Impostare un caching "aggressivo" come da noi suggerito non avvelena la cache del browser: da quanto ne sappiamo tutti i browser puliscono la loro cache utilizzando un algoritmo che mantiene la versione utilizzata più recentemente. Non siamo a conoscenza di browser che mantengono le risorse di cache memorizzate fino a che non scadano.
  • Impostare la data in "Last-Modified" con il valore reale dell'ultima  modifca. Se il valore di "Last-Modified" è sufficentemente "lontano" nel passato è probabile che il browser esegua la memorizzazione in cache della risorsa.

Utilizzare la tecnica di fingerprinting per abilitare dinamicamente la cache.

Per le risorse che cambiano occasionalmente, si puo' avere la risorsa in cache finchè non cambia nel server, a questo punto il server dice al browser che la risorsa è cambiata e che è pronta una nuova versione. Si può ottenere questo includendo una piccola "impronta digitale" (fingerprint) della risorsa nel suo URL (ad esempio nel path del file). Quando la risorsa cambia, anche la sua impronta digitale cambia e di conseguenza ancora il suo URL. Appena l'URL cambia il browser è obbligato a ricaricare la risorsa. Grazie al fingerprinting si può impostare una data di scadenza della cache lontana nel tempo anche per le risorse che potrebbero cambiare spesso nel tempo. Naturalmente questa tecnica richiede che tutte le pagine che puntano alla risorsa conoscano il suo "fingerprint URL" cosa che può essere fattibile o meno a seconda di come le pagine sono codificate.

Impostare correttamente il "Vary header" per Internet Explorer.

Internet Explorer non salva in cache nessuna risorsa che che ha impostato il parametro "Vary" nel header http e un qualsiasi campo impostato. Per essere sicuri che queste risorse vengano poste in cache da IE bisogna eliminare qualsiasi campo dal "Vary header" oppure rimuovere, se possibile, il "Vary header" stesso.

Evitare gli URL che causano collisioni nella cache di Firefox.

La funzione di Firefox di "disk cache hash" può generare delle collisioni per gli URL che variano di poco, sui quali è stato inserito un nome file con solo 8 caratteri di boundary. Quando il codice hash di più risorse punta alla stessa chiave solo una di queste risorse può essere mantenuta nella cache, le altre risorse devono nuovamente essere richieste al server. Quindi se si sta utilizzando la tecnica di fingerprinting oppure se si stanno generando gli url da programma per massimizzare gli hit cache, bisogna evitare che avvenga una collisione degli hash nella cache di Firefox assicurandosi che la vostra applicazione generi URL che differiscano di più di 8 caratteri di boundary.

Utilizzare la direttiva "Cache control: public" per abilitare il caching con HTTPS in Firefox.

Alcune versioni di Firefox richiedono che la direttiva "Cache control: public" nel header HTTP sia impostata perchè le risorse inviate via SSL siano poste in cache, anche se le altre direttive sono esplicitamente impostate. Sebbene questa direttiva sia normalmente utilizzata per abilitare il caching dei proxy, i proxy non possono salvare in cache alcun contenuto inviato via HTTPS, quindi non c'è alcun problema ad utilizzare questa direttiva per le risorse HTTPS.

Esempio

Per il foglio di stile usato per visualizzare il calendario dell'utente dopo il login, Google Calendar include un fingerprint nel suo nome del file: calendar/static/fingerprint_keydoozercompiled.css, dove la fingerprint key è un numero esadecimale a 128-bit. Nello screenshot sotto (preso dal pannello di Page Speed Show Resources), il fingerprint era impostato a 82b6bc440914c01297b99b4bca641a5d:

Il meccanismo di fingerprinting permette al server di impostare il valore di Expires nel header HTTP esattamente un anno dopo la data della richiesta; Last-Modified al valore della data di modifica; e il Cache-Control: max-age a 3153600. Per consentire al client il download del file aggiornato in caso di cambiamenti prima dell'expiry date o maximun-age, il fingerprint (e di conseguenza l'url) cambiano quando il contenuto del file cambia.

Risorse Aggiuntive

Articolo originale in lingua inglese

Potrebbe interessarti anche:

About Alessandro

Mi interesso di web editing, seo e rich internet application