Skip to content

Cos’è la cache

Cos’è la cache

La cache è un sistema per riutilizzare risorse già scaricate dal browser, riducendo quindi il consumo di CPU e banda del web server e velocizzando il caricamento delle pagine.

Recuperare file dalla rete richiede tempo e comporta dei costi energetici (banda utilizzata, utilizzo della CPU, utilizzo del disco e così via). Spesso per generare anche una semplice pagina web sono necessarie numerose chiamate HTTP tra client e server, queste chiamate incidono sull’esperienza utente, sui tempi di caricamento e sui tempi di calcolo del browser per processare la pagina. Di conseguenza, la possibilità di mettere in cache e riutilizzare risorse recuperate in precedenza costituisce un aspetto fondamentale nell’ottimizzazione delle prestazioni di un sito web.

Ogni browser possiede un sistema integrato di cache HTTP, devi assicurarti solamente che ogni risposta del web server fornisca l’intestazione HTTP corretta per comunicare al browser in che modo, quando e per quanto tempo la risposta può essere archiviata in cache.

Esistono più tipi di cache

Una copia cache di una pagina web, o di un file CSS ad esempio, può esistere in diversi livelli del percorso web server > network > client.

  • Una copia cache infatti può esistere a livello del web server, ad esempio usando fastCGI, Varnish o altre soluzioni comparabili.
  • Una copia cache può esistere su una CDN, quindi nel network che connette il client al server, ad esempio usando Cloudflare.
  • Infine, una copia cache può esistere nel browser, che salva file e pagine per velocizzare le pageview successive alla prima.

In questa guida parliamo dell’intestazione HTTP Cache-Control che consiglia al browser cosa tenere in memoria, quindi parliamo di una cache lato client.

Intestazione HTTP Cache-Control

Le intestazioni HTTP consentono al client e al server di passare informazioni aggiuntive con la richiesta o la risposta. Un’intestazione HTTP è costituita dal suo nome, non case sensitive, seguito dai due punti ‘:’, quindi dal suo valore senza interruzioni di riga. Spazio bianco iniziale prima che il valore venga ignorato.

Ti è mai capitato di vedere qualcosa del genere? Ecco, questo che segue è un esempio di intestazione HTTP:

HTTP/1.1 200 OK
Date: Fri, 27 Apr 2018 07:59:06 GMT
Content-Type: text/html; charset=UTF-8
Connection: close
Set-Cookie: __cfduid=d047683e2225426554c96d71a9e7d21521524815946; expires=Sat, 27-Apr-19 07:59:06 GMT; path=/; domain=.evemilano.com; HttpOnly
Vary: Accept-Encoding
Link: <https://www.evemilano.com/wp-json/>; rel="https://api.w.org/"
X-Cache: HIT
Strict-Transport-Security: max-age=15552000; preload
X-Content-Type-Options: nosniff
Expect-CT: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Server: cloudflare
CF-RAY: 411fbf703d4d9c6b-AMS

In cache è possibile inserire qualsiasi tipo di estensione file: pagine HTML, file CSS, Fonts, JavaScript e Immagini. La modalità di caching di ogni risorsa può essere definita tramite l’intestazione HTTP Cache-Control. Le direttive Cache-Control determinano chi può mettere in cache la risposta, a quali condizioni e per quanto tempo.

Cache-Control header
Fonte: developers.google.com

Dal un punto di vista dell’ottimizzazione delle performance e della velocità di caricamento delle pagine, la richiesta migliore è una richiesta che non ha bisogno di comunicare con il web server: una copia locale della risposta consente al browser di eliminare qualsiasi latenza di rete e riduce i dati trasferiti dal web server. Per ottenere ciò, la specifica HTTP consente al server di restituire direttive Cache-Control che controllano come e per quanto tempo ogni singola risposta può essere tenuta in cache dal browser e altre cache intermedie.

L’intestazione Cache-Control è stata definita all’interno delle specifiche HTTP/1.1 e sostituisce ogni intestazione precedente (ad es. Expires) utilizzate per definire le policy di caching delle risposte. Cache-Control è supportato da tutti gli attuali browser; non abbiamo quindi bisogno di altro.

Il campo di intestazione generale Cache-Control viene quindi utilizzato per specificare le direttive per i meccanismi di memorizzazione nella cache in entrambe le richieste e le risposte. Le direttive di caching sono unidirezionali, nel senso che una determinata direttiva in una richiesta non implica che nella risposta debba essere data la stessa direttiva.

Sintassi

Le direttive non fanno distinzione tra maiuscole e minuscole (non sono case sentitive) e hanno un argomento facoltativo, che può essere utilizzato sia con token che con la sintassi della stringa tra virgolette. Le direttive multiple sono separate da virgola.

Direttive Cache request

Direttive Cache-Control standard che possono essere utilizzate dal client in una richiesta HTTP.

Cache-Control: max-age=

  • Specifica la quantità massima di tempo in cui una risorsa sarà considerata fresca. Contrariamente a Expires, questa direttiva è relativa al momento della richiesta. Questa direttiva specifica il tempo massimo espresso in secondi durante il quale la risposta recuperata può essere riutilizzata a partire dalla richiesta; ad esempio, “max-age=60” indica che la risposta può essere messa in cache e riutilizzata per i successivi 60 secondi.

Cache-Control: max-stale[=]

  • Indica che il client è disposto ad accettare una risposta che ha superato la sua scadenza. Facoltativamente, è possibile assegnare un valore in secondi, indicando il tempo entro il quale la risposta non deve essere scaduta.

Cache-Control: min-fresh=

  • Indica che il client desidera una risposta che sarà comunque aggiornata almeno per il numero specificato di secondi.

Cache-Control: no-cache

  • Forza le cache per inviare la richiesta al server di origine per la convalida prima di rilasciare una copia memorizzata nella cache. “no-cache” indica che la risposta ricevuta non può essere utilizzata per soddisfare una richiesta successiva per il medesimo URL senza prima verificare con il server se la risposta è cambiata. Di conseguenza, se è presente un token di convalida (ETag) idoneo, il no-cache effettuerà un roundtrip per convalidare la risposta in cache, ma potrà annullare il download se la risorsa non è cambiata.

Cache-Control: no-store

  • La cache non deve memorizzare nulla sulla richiesta del client o sulla risposta del server. Rispetta a “no-cache”, la direttive “no-store” è molto più semplice, poiché si limita a impedire al browser e a tutte le cache intermedie di memorizzare qualsiasi versione della risposta ricevuta, ad es. contenente dati sensibili o bancari. Ogni volta che l’utente richiede tale attività, la richiesta viene inviata al server e scaricata una risposta completa ogni volta.

Cache-Control: no-transform

  • Nessuna trasformazione o conversione dovrebbe essere apportata alla risorsa. Le intestazioni Content-Encoding, Content-Range, Content-Type non devono essere modificate da un proxy. Un proxy non trasparente potrebbe, ad esempio, convertire tra formati di immagine per risparmiare spazio nella cache o per ridurre la quantità di traffico su un collegamento lento. La direttiva no-transform non consente questo.

Cache-Control: only-if-cached

  • Indica di non recuperare nuovi dati. Stando così le cose, il server desidera che il client ottenga una risposta solo una volta e poi la cache. Da questo momento il client dovrebbe continuare a rilasciare una copia memorizzata nella cache ed evitare di contattare il server di origine per verificare se esiste una nuova copia.

Direttive Cache response

Direttive Cache-Control standard che possono essere utilizzate dal server in una risposta HTTP.

Cache-Control: must-revalidate

  • La cache deve verificare lo stato delle risorse stantie prima di usarle e quelle non dovrebbero essere utilizzate.

Cache-Control: no-cache

  • Forza le cache per inviare la richiesta al server di origine per la convalida prima di rilasciare una copia memorizzata nella cache.

Cache-Control: no-store

  • La cache non deve memorizzare nulla sulla richiesta del client o sulla risposta del server.

Cache-Control: no-transform

  • Nessuna trasformazione o conversione dovrebbe essere apportata alla risorsa. Le intestazioni Content-Encoding, Content-Range, Content-Type non devono essere modificate da un proxy. Un proxy non trasparente potrebbe, ad esempio, convertire tra formati di immagine per risparmiare spazio nella cache o per ridurre la quantità di traffico su un collegamento lento. La direttiva no-transform non consente questo.

Cache-Control: public

  • Indica che la risposta potrebbe essere memorizzata nella cache da qualsiasi cache. Se la risposta è contrassegnata come “public”, può essere messa in cache anche se ad essa è associata un’autenticazione HTTP, e anche quando lo status code della risposta non può di norma essere messo in cache. La maggior parte delle volte, “public” non è necessario, perché il caching esplicito di informazioni (ad es. “max-age”) indica che la risposta può comunque essere messa in cache.

Cache-Control: private

  • Indica che la risposta è destinata a un singolo utente e non deve essere memorizzata da una cache condivisa. Una cache privata può memorizzare la risposta. Al contrario di “public”, le risposte “private” possono essere messe in cache dal browser ma sono di norma rivolte a un singolo utente e non possono quindi essere messe in una cache intermedia; ad esempio, una pagina HTML con informazioni sensibili dell’utente può essere messa in cache dal browser dell’utente stesso, ma non da un CDN.

Cache-Control: proxy-revalidate

  • Uguale a must-revalidate, ma si applica solo alle cache condivise (ad es. Proxy) e viene ignorato da una cache privata.

Cache-Control: max-age=

  • Specifica la quantità massima di tempo in cui una risorsa sarà considerata fresca. Contrariamente a Expires, questa direttiva è relativa al momento della richiesta. Questa direttiva specifica il tempo massimo espresso in secondi durante il quale la risposta recuperata può essere riutilizzata a partire dalla richiesta; ad esempio, “max-age=60” indica che la risposta può essere messa in cache e riutilizzata per i successivi 60 secondi.

Cache-Control: s-maxage=

  • Sovrascrive l’età massima o l’intestazione Expires, ma si applica solo alle cache condivise (ad es. Proxy) e viene ignorata da una cache privata.

Direttive Extension Cache-Control

Le direttive Extension Cache-Control non fanno parte del documento di base degli standard di caching HTTP. Assicurati di controllare la tabella di compatibilità dei browser per il loro supporto.

Tabella di compatibilità dei browser

Cache-Control: immutable

  • Indica che il corpo della risposta non cambierà nel tempo. La risorsa, se non scaduta, è invariata sul server e pertanto il client non deve inviare una riconvalida condizionale per esso (es. If-None-Match o If-Modified-Since) per controllare gli aggiornamenti, anche quando l’utente aggiorna esplicitamente la pagina . I client che non sono a conoscenza di questa estensione devono ignorarli secondo le specifiche HTTP. In Firefox, immutable è onorato solo per le transazioni https: //. Per ulteriori informazioni, vedi anche questo post sul blog.

Cache-Control: stale-while-revalidate=

  • Indica che il client è disposto ad accettare una risposta non aggiornata mentre esegue il controllo in background in modo asincrono per una nuova. Il valore dei secondi indica per quanto tempo il client è disposto ad accettare una risposta obsoleta.

Cache-Control: stale-if-error=

  • Indica che il client è disposto ad accettare una risposta obsoleta se il controllo di uno nuovo non riesce. Il valore dei secondi indica per quanto tempo il client è disposto ad accettare la risposta obsoleta dopo la scadenza iniziale.

Annullare e aggiornare le risposte in cache

Una volta che una risorsa è archiviata in cache, potrebbe teoricamente essere servita dalla cache per sempre. Le cache dispongono di spazio di archiviazione limitato, pertanto gli elementi vengono periodicamente rimossi dallo spazio di archiviazione – il processo viene chiamato cache eviction. Dall’altro lato, alcune risorse potrebbero cambiare sul server, quindi la cache dovrebbe essere aggiornata. Poiché HTTP è un protocollo client-server, i server non possono contattare cache e client quando una risorsa cambia; devono comunicare un tempo di scadenza per la risorsa. Prima di questa scadenza, la risorsa è fresca; dopo la scadenza, la risorsa è obsoleta.

Tutte le richieste HTTP del browser vengono prima inviate alla cache del browser per verificare se in essa sia presente una risposta valida utilizzabile per soddisfare la richiesta. In caso di corrispondenza, la risposta viene letta dalla cache, eliminando sia la latenza di rete, sia i costi di trasferimento dei dati.

Ma cosa succede se volessimo aggiornare o annullare una risposta in cache? Supponiamo ad esempio di avere detto ai nostri visitatori di mettere in cache un foglio stile CSS fino a 24 ore (max-age=86400), ma che il nostro webmaster abbia realizzato un aggiornamento che desideriamo mettere a disposizione di tutti gli utenti. Come possiamo comunicare a tutti i visitatori qual è ormai una copia cache “obsoleta” del nostro CSS per poter aggiornare le loro cache? Si tratta di una domanda trabocchetto: non possiamo farlo, a meno che non modifichiamo l’URL della risorsa.

Una volta messa in cache dal browser, la versione verrà utilizzata fino a quando è valida, come determinato da max-age, o non scade, o fino a quando non viene eliminata dalla cache per qualche altra ragione, ad esempio la cancellazione della cache del browser da parte dell’utente. Di conseguenza, è possibile che utenti diversi si trovino ad utilizzare versioni diverse del file quando la pagina viene costruita; gli utenti che hanno appena recuperato la risposta utilizzeranno la nuova versione, mentre quelli che hanno messo in cache una copia precedente (ma sempre valida) useranno una versione precedente di tale risposta.

Come possiamo quindi trarre il massimo vantaggio da entrambi i mondi, ovvero dal caching lato client e dagli aggiornamenti? Semplice: possiamo modificare l’URL della risorsa e forzare l’utente a scaricare la nuova risposta ogni volta che il contenuto cambia. Di norma ciò è possibile includendo un fingerprint del file o un numero versione nel filename, ad es. style.x234dff.css.

Annullare e aggiornare le risposte in cache
Fonte: developers.google.com

La possibilità di definire delle politiche di caching per singola risorsa ci consente di definire delle “gerarchie di caching” che ci permettono di controllare non solo i tempi di conservazione in cache, ma anche le modalità di visualizzazione delle nuove versioni da parte dell’utente. Per illustrare questo analizziamo l’esempio precedente:

L’HTML è contrassegnato come “no-cache”; che significa che il browser dovrà quindi riconvalidare sempre il documento a ogni richiesta e recuperarne l’ultima versione se i contenuti cambiano. Inoltre, nel markup HTML, abbiamo inserito dei fingerprint negli URL per CSS e JavaScript: se il contenuto di tali file cambia, allora cambierà anche l’HTML della pagina e verrà scaricata una nuova copia della risposta HTML.

Il CSS può essere messo in cache da browser e cache intermediarie (ad es., un CDN) ed è impostato con scadenza a un 1 anno. Nota che possiamo utilizzare senza problemi “far future expires” di 1 anno perché abbiamo incluso un fingerprint del file: se il CSS viene aggiornato, cambia anche l’URL.

Anche la scadenza del JavaScript è impostata a 1 anno, ma è contrassegnata come “private”, probabilmente perché contiene dei dati sensibili dell’utente che il CDN non può mettere in cache.

L’immagine è messa in cache senza versione o fingerprint univoca, con scadenza 1 giorno.

La combinazione di ETag, Cache-Control e URL univoci ci consente di offrire il massimo da entrambi i lati: tempi di scadenza lunghi, controllo sul percorso di messa in cache della risposta e aggiornamenti on-demand.

Convalida dei file in cache con ETag

Il metodo migliore per gestire le versioni file scadute forzandone l’aggiornamento è con l’intestazione ETag. Il server usa l’intestazione HTTP ETag per comunicare un token di convalida. Il token di convalida consente di effettuare una verifica efficiente dell’aggiornamento delle risorse: nessun dato viene trasferito se la risorsa non ha subito modifiche. In pratica ad ogni file viene assegnato un token, se il file viene aggiornato (es un file .css) il token cambia ed il sistema di cache dovrà aggiornarlo.

Supponiamo siano trascorsi 120 secondi dal recupero e che il browser abbia inviato una nuova richiesta per la medesima risorsa. Prima di tutto il browser verifica la cache locale e individua la risposta precedente. Sfortunatamente però non può utilizzarla, poiché ormai scaduta. A questo punto, il browser può semplicemente inviare una nuova richiesta e recuperare la nuova risposta. Tuttavia, questo è inefficiente, poiché se la risposta non è cambiata, non c’è motivo di riscaricare gli stessi byte già in cache.

Convalida di risposte messe in cache con ETag
Fonte: developers.google.com

È proprio per risolvere questo tipo di problema che sono stati crearti i token di convalida e nello specifico le intestazioni ETag. Il server genera e invia un token casuale, di norma un hash o un fingerprint dei contenuti del file. Al client non serve sapere come sia stata generato il fingerprint, deve solo inviarlo al server alla successiva richiesta: se il fingerprint è sempre uguale, allora la risorsa non è stata modificata, ed è quindi possibile saltare il download.

Nell’esempio precedente, il client fornisce automaticamente il token ETag nell’intestazione di richiesta HTTP “If-None-Match”; il server confronta nuovamente il token con la risorsa corrente e, se questa non è cambiata, invia una risposta “304 Not Modified”, che indica al browser che la risposta che ha in cache non è cambiata e può essere rinnovata per altri 120 secondi. Nota che non è necessario salvare ancora una volta la risposta, risparmiando tempo e larghezza di banda.

In qualità di sviluppatore web, in che modo puoi trarre vantaggio da una riconvalida efficace? Il browser esegue tutto il lavoro per conto nostro: individua automaticamente ogni token di convalida già specificato in precedenza, lo aggiunge a una richiesta in corso e aggiorna il timestamp della cache in base alla risposta ricevuta dal server. L’unica cosa che ci resta da fare è assicurarci che il server stia effettivamente fornendo i token ETag necessari: per testare puoi usare un lettore HTTP Header.

Verifica HTTP Header eTag

Strategie di caching

Definizione di un metodo di Cache-Control ottimale
Fonte: developers.google.com

Per definire la tua migliore strategia di caching potresti seguire questo albero decisionale. L’immagine ti può aiutare a determinare la politica di memorizzazione nella cache ottimale per una particolare risorsa o un insieme di risorse utilizzate dal sito web. Idealmente, dovresti cercare di memorizzare il maggior numero possibile di risposte sul client per il periodo più lungo possibile e fornire token di convalida per ciascuna risposta per consentire una riconvalida efficiente.

Secondo HTTP Archive, tra i primi 300.000 siti (secondo il ranking di Alexa), il browser può memorizzare quasi la metà di tutte le risposte scaricate, un enorme risparmio per le visite ripetute. Ovviamente, ciò non significa che il tuo sito web possa memorizzare nella cache il 50% delle risorse. Alcuni siti possono memorizzare nella cache più del 90% delle loro risorse, mentre altri siti potrebbero avere molti dati privati o sensibili al fattore tempo che non possono essere memorizzati nella cache.

Controlla le tue pagine per identificare quali risorse possono essere memorizzate nella cache e assicurati che restituiscano intestazioni appropriate di Cache-Control e ETag.

Tieni in considerazione che non esiste un metodo di caching migliore di altri. A seconda del tuo schema di traffico, del tipo di dati scambiati e dei requisiti specifici dell’applicazione per l’aggiornamento dei dati, dovrai definire e configurare le impostazioni idonee per ogni risorsa, oltre alla “gerarchia di caching” generale.

Alcuni suggerimenti e tecniche da tenere a mente nel definire la strategia di caching:

  • Controlla le tue pagine per identificare quali risorse possono essere memorizzate nella cache e assicurati che restituiscano intestazioni appropriate di Cache-Control e ETag.
  • Utilizza URL canonici e coerenti: se offri il medesimo contenuto su URL diversi, tale contenuto verrà recuperato e memorizzato più volte. Ricordati che gli URL sono case sensitive.
  • Assicurati che il server fornisca un token di convalida (ETag): con i token di convalida non è più necessario trasferire gli stessi byte se la risorsa sul server non è cambiata. Individua le risorse che possono essere messe in cache da intermediari: quelle con risposte identiche per tutti gli utenti sono perfette per essere messe in cache da un CDN e altri intermediari.
  • Stabilisci la durata ottimale della cache per ogni risorsa: risorse diverse possono avere esigenze di refresh diverse. Verifica e stabilisci il valore max-age idoneo per ciascuna.
  • Stabilisci la gerarchia di caching migliore per il tuo sito: la combinazione tra URL della risorsa, fingerprint dei contenuti e cache brevi o nessuna cache per i documenti HTML ti consentono di controllare la frequenza degli aggiornamenti eseguiti dal client.
  • Riduci al minimo i download: alcune risorse sono aggiornate più frequentemente di altre. Se una determinata parte di una risorsa (ad es. una funzione JavaScript oppure alcuni set di stili CSS) viene aggiornata di frequente, valuta l’invio di tale parte di codice come file separato. Così facendo, il codice che non cambia molto spesso può essere recuperato dalla cache, minimizzando i contenuti scaricati ad ogni aggiornamento.

Fonti:

Articoli correlati

Autore

Commenti |3

Lascia un commento Lascia un commento
  1. Paolo 1 commento

    Giovanni buongiorno, vorrei porti una domanda:
    È possibile capire se una risorsa (ad esempio l’immagine Pippo.jpg) risiede nella cache del browser o nella cache del server?
    Grazie

    1. Giovanni Sacheli 754 risposte

      Ciao Paolo, ci sono due metodi per fare questa verifica:
      1. controllare l’intestazione HTTP del file in questione per vedere se il web server chiede al browser di metterla in cache oppure se vieta di fatto la cache.
      2. usare il report “Network” in Chrome Dev Tools e guardare la colonna “Size”. Se in quel campo Chrome dice “memory cache” significa che l’ha recuperata dalla sua cache.

  2. Rodrigo 1 commento

    Complimenti per l’esaustività e la chiarezza dell’articolo.
    Salvato tra i preferiti!

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Ultimi articoli aggiornati

Richiedi un preventivo SEO e Google Ads

Porta il tuo sito web al livello successivo con l’expertise di EVE Milano. La nostra agenzia di Search Marketing ha ricevuto oltre 1126 richieste di preventivo, un segnale chiaro della fiducia che imprenditori e manager, come te, ripongono nella nostra specializzazione tecnica e verticale nella SEO e PPC. Se la tua organizzazione cerca competenze specifiche per emergere nei risultati di Google, noi siamo pronti a fornire quel valore aggiunto. Affidati alla nostra esperienza per fare la differenza.
Richiedi un preventivo

Non perderti altre guide, iscriviti per ricevere un avviso mensile con gli aggiornamenti del blog!

Iscriviti alla newsletter!

Informativa sui cookies

Noi e terze parti selezionate utilizziamo cookie o tecnologie simili per finalità tecniche e, con il tuo consenso, anche per le finalità di esperienza e misurazione come specificato nella cookie policy. Puoi liberamente prestare, rifiutare o revocare il tuo consenso, in qualsiasi momento, accedendo al pannello delle preferenze. Il rifiuto del consenso può rendere non disponibili le relative funzioni. Usa il pulsante “Accetta” per acconsentire. Usa il pulsante “Rifiuta” per continuare senza accettare.