Il recupero delle risorse tramite la rete è lento e costoso:
- Le risposte di grandi dimensioni richiedono molti roundtrip tra il browser e il server.
- La pagina non verrà caricata finché non saranno state scaricate completamente tutte le sue risorse critiche.
- Se un utente accede al tuo sito con un piano dati mobile limitato, ogni richiesta di rete non necessaria è uno spreco di denaro.
Come puoi evitare richieste di rete non necessarie? La cache HTTP del browser è la tua prima linea di difesa. Non è necessariamente l'approccio più potente o flessibile e hai un controllo limitato sulla durata delle risposte memorizzate nella cache, ma è efficace, è supportato in tutti i browser e non richiede molto lavoro.
Questa guida illustra le nozioni di base di un'implementazione efficace della memorizzazione nella cache HTTP.
Compatibilità del browser
In realtà non esiste una singola API chiamata cache HTTP. È il nome generico di una raccolta di API della piattaforma web. Queste API sono supportate in tutti i browser:
Cache-Control
ETag
Last-Modified
Come funziona la cache HTTP
Tutte le richieste HTTP effettuate dal browser vengono prima indirizzate alla memorizzazione nella cache del browser per verificare se esiste una risposta memorizzata nella cache valida che può essere utilizzata per soddisfare la richiesta. Se esiste una corrispondenza, la risposta viene letta dalla cache, eliminando sia la latenza di rete sia i costi dei dati sostenuti per il trasferimento.
Il comportamento della cache HTTP è controllato da una combinazione di intestazioni della richiesta e intestazioni della risposta. In uno scenario ideale, avrai il controllo sia sul codice della tua applicazione web (che determinerà le intestazioni della richiesta) sia sulla configurazione del tuo server web (che determinerà le intestazioni della risposta).
Per una panoramica concettuale più approfondita, consulta l'articolo di MDN sulla memorizzazione nella cache HTTP.
Intestazioni delle richieste: in genere, mantieni le impostazioni predefinite
Esistono diverse intestazioni importanti che devono essere incluse nelle richieste in uscita della tua app web, ma il browser si occupa quasi sempre di impostarle per tuo conto quando effettua le richieste. Le intestazioni della richiesta che influiscono sul controllo dell'aggiornamento, come If-None-Match e If-Modified-Since, vengono visualizzate in base alla comprensione da parte del browser dei valori correnti nella cache HTTP.
Questa è una buona notizia: significa che puoi continuare a includere tag come <img src="my-image.png"> nel tuo codice HTML e il browser si occuperà automaticamente della memorizzazione nella cache HTTP, senza ulteriori sforzi.
Intestazioni delle risposte: configura il server web
La parte più importante della configurazione della memorizzazione nella cache HTTP sono le intestazioni che il server web aggiunge a ogni risposta in uscita. Le seguenti intestazioni influiscono tutte sul comportamento di memorizzazione nella cache:
Cache-Control. Il server può restituire un'istruzioneCache-Controlper specificare come e per quanto tempo il browser e altre cache intermedie devono memorizzare nella cache la singola risposta.ETag. Quando il browser trova una risposta memorizzata nella cache scaduta, può inviare un piccolo token (di solito un hash dei contenuti del file) al server per verificare se il file è cambiato. Se il server restituisce lo stesso token, il file è lo stesso e non è necessario scaricarlo di nuovo.Last-Modified: questa intestazione ha lo stesso scopo diETag, ma utilizza una strategia basata sul tempo per determinare se una risorsa è cambiata, anziché la strategia basata sui contenuti diETag.
Alcuni server web dispongono di un supporto integrato per l'impostazione predefinita di queste intestazioni, mentre altri le omettono completamente, a meno che non vengano configurate esplicitamente. I dettagli specifici su come configurare le intestazioni variano notevolmente a seconda del server web utilizzato. Per informazioni più precise, consulta la documentazione del tuo server.
Per risparmiarti un po' di ricerche, ecco le istruzioni per configurare alcuni server web più diffusi:
L'omissione dell'intestazione della risposta Cache-Control non disattiva la memorizzazione nella cache HTTP. I browser indovinano il tipo di comportamento di memorizzazione nella cache più sensato per un determinato tipo di contenuti. È probabile che tu voglia un maggiore controllo rispetto a quello offerto, quindi prenditi il tempo necessario per configurare le intestazioni della risposta.
Quali valori delle intestazioni della risposta devi utilizzare?
Esistono due scenari importanti da considerare quando configuri le intestazioni della risposta del tuo server web.
Memorizzazione nella cache di lunga durata per gli URL con versione
Supponiamo che il tuo server indichi ai browser di memorizzare nella cache un file CSS per 1 anno (Cache-Control: max-age=31536000), ma il tuo designer ha appena apportato un aggiornamento di emergenza che devi implementare immediatamente. Come fai a comunicare ai browser di aggiornare la copia memorizzata nella cache "obsoleta" del file? Non puoi, almeno non senza modificare l'URL della risorsa.
Dopo che il browser ha memorizzato nella cache la risposta, la versione memorizzata nella cache viene utilizzata finché non è più aggiornata, come determinato da max-age o expires, o finché non viene rimossa dalla cache per un altro motivo, ad esempio se l'utente svuota la cache del browser. Di conseguenza, utenti diversi potrebbero finire per utilizzare versioni diverse del file quando viene creata la pagina: gli utenti che hanno appena recuperato la risorsa utilizzano la nuova versione, mentre gli utenti che hanno memorizzato nella cache una copia precedente (ma ancora valida) utilizzano una versione precedente della risposta.
Come si ottiene il meglio di entrambi i mondi: memorizzazione nella cache lato client e aggiornamenti rapidi? Modifichi l'URL della risorsa e forzi l'utente a scaricare la nuova risposta ogni volta che i suoi contenuti cambiano. In genere, questa operazione viene eseguita incorporando un'impronta del file o un numero di versione nel nome file, ad esempio style.x234dff.css.
Quando rispondi alle richieste di URL che contengono "fingerprint" o informazioni sul controllo delle versioni e i cui contenuti non devono mai cambiare, aggiungi Cache-Control: max-age=31536000 alle tue risposte.
L'impostazione di questo valore indica al browser che,quando deve caricare lo stesso URL in qualsiasi momento nel corso dell'anno successivo (31.536.000 secondi,il valore massimo supportato), può utilizzare immediatamente il valore nella cache HTTP, senza dover effettuare una richiesta di rete al tuo server web. Ottimo: hai ottenuto immediatamente l'affidabilità e la velocità che derivano dall'evitare la rete.
Gli strumenti di build come webpack possono automatizzare il processo di assegnazione delle impronte hash agli URL degli asset.
Nuova convalida del server per gli URL senza versione
Purtroppo, non tutti gli URL caricati sono sottoposti a controllo delle versioni. Forse non puoi includere un passaggio di build prima di eseguire il deployment della tua app web, quindi non puoi aggiungere hash agli URL degli asset. Inoltre, ogni applicazione web ha bisogno di file HTML, che non includeranno (quasi!) mai informazioni sul controllo della versione, poiché nessuno si preoccuperà di utilizzare la tua app web se deve ricordare che l'URL da visitare è https://example.com/index.34def12.html. Cosa puoi fare per questi URL?
Questo è uno scenario in cui devi ammettere la sconfitta. La memorizzazione nella cache HTTP da sola non è sufficiente per evitare completamente la rete. (Non preoccuparti: presto scoprirai i service worker, che forniranno il supporto necessario per ribaltare la situazione a tuo favore.) Tuttavia, puoi seguire alcuni passaggi per assicurarti che le richieste di rete siano il più rapide ed efficienti possibile.
I seguenti valori Cache-Control possono aiutarti a perfezionare dove e come vengono memorizzati nella cache gli URL senza versione:
no-cache. In questo modo, il browser viene informato che deve eseguire la riconvalida con il server ogni volta prima di utilizzare una versione memorizzata nella cache dell'URL.no-store. In questo modo, il browser e le altre cache intermedie (come le CDN) non memorizzano mai alcuna versione del file.private. I browser possono memorizzare il file nella cache, ma le cache intermedie no.public. La risposta può essere memorizzata da qualsiasi cache.
Consulta l'Appendice: diagramma di flusso di Cache-Control per visualizzare il processo di decisione dei valori Cache-Control da utilizzare. Cache-Control può anche accettare un elenco di istruzioni separate da virgole. Consulta l'Appendice: esempi di Cache-Control.
Anche l'impostazione di ETag o Last-Modified può essere utile. Come indicato in Intestazioni della risposta, ETag e Last-Modified hanno lo stesso scopo: determinare se il browser deve scaricare nuovamente un file memorizzato nella cache che è scaduto. Ti consigliamo di utilizzare ETag perché è più preciso.
Supponiamo che siano trascorsi 120 secondi dal recupero iniziale e che il browser abbia avviato una nuova richiesta per la stessa risorsa. Innanzitutto, il browser controlla la cache HTTP e trova la risposta precedente. Purtroppo, il browser non può utilizzare la risposta precedente perché è scaduta. A questo punto, il browser potrebbe inviare una nuova richiesta e recuperare la nuova risposta completa. Tuttavia, questo è inefficiente perché se la risorsa non è cambiata, non c'è motivo di scaricare le stesse informazioni già presenti nella cache.
Questo è il problema che i token di convalida, come specificato nell'intestazione ETag, sono progettati per risolvere. Il server genera e restituisce un token arbitrario, che in genere è un hash o un'altra impronta dei contenuti del file. Il browser non ha bisogno di sapere come viene generata l'impronta, deve solo inviarla al server alla richiesta successiva. Se l'impronta è ancora la stessa, la risorsa non è cambiata e il browser può saltare il download.
L'impostazione di ETag o Last-Modified rende la richiesta di riconvalida molto più efficiente, consentendo di attivare le intestazioni della richiesta If-Modified-Since o If-None-Match menzionate in Intestazioni della richiesta.
Quando un server web configurato correttamente vede queste intestazioni delle richieste in entrata, può confermare se la versione della risorsa che il browser ha già nella sua cache HTTP corrisponde all'ultima versione sul server web. Se esiste una corrispondenza, il server può rispondere con una risposta HTTP 304 Not Modified, che equivale a dire "Ehi, continua a utilizzare ciò che hai già". I dati da trasferire quando si invia questo tipo di risposta sono molto pochi, quindi l'operazione è in genere molto più rapida rispetto all'invio di una copia della risorsa effettivamente richiesta.
/file al server e include l'intestazione If-None-Match per indicare al server di restituire il file completo solo se il valore ETag del file sul server non corrisponde al valore If-None-Match del browser. In questo caso, i due valori corrispondono, quindi il server restituisce una risposta 304 Not Modified con istruzioni su per quanto tempo il file deve essere memorizzato nella cache (Cache-Control: max-age=120).
Riepilogo
La cache HTTP è un modo efficace per migliorare le prestazioni di caricamento perché riduce le richieste di rete non necessarie. È supportato in tutti i browser e la sua configurazione non richiede troppi sforzi.
Le seguenti configurazioni di Cache-Control sono un buon punto di partenza:
Cache-Control: no-cacheper le risorse che devono essere riconvalidate con il server prima di ogni utilizzo.Cache-Control: no-storeper le risorse che non devono mai essere memorizzate nella cache.Cache-Control: max-age=31536000per le risorse con controllo delle versioni.
Inoltre, l'intestazione ETag o Last-Modified può aiutarti a riconvalidare le risorse della cache scadute in modo più efficiente.
Scopri di più
Se vuoi andare oltre le nozioni di base sull'utilizzo dell'intestazione Cache-Control, consulta la guida Caching best practices and max-age gotchas di Jake Archibald.
Consulta Love your cache per indicazioni su come ottimizzare l'utilizzo della cache per i visitatori di ritorno.
Appendice: altri suggerimenti
Se hai più tempo, ecco altri modi per ottimizzare l'utilizzo della cache HTTP:
- Utilizza URL coerenti. Se pubblichi gli stessi contenuti su URL diversi, questi verranno recuperati e archiviati più volte.
- Riduci al minimo l'abbandono. Se una parte di una risorsa (ad esempio un file CSS) viene aggiornata di frequente, mentre il resto del file non lo è (ad esempio il codice della libreria), valuta la possibilità di suddividere il codice che viene aggiornato di frequente in un file separato e di utilizzare una strategia di memorizzazione nella cache di breve durata per il codice che viene aggiornato di frequente e una strategia di memorizzazione nella cache di lunga durata per il codice che non cambia spesso.
- Dai un'occhiata alla nuova istruzione
stale-while-revalidatese nella tua policyCache-Controlè accettabile un certo grado di obsolescenza.
Appendice: diagramma di flusso Cache-Control
Cache-Control.
Appendice: esempi di Cache-Control
Valore Cache-Control |
Spiegazione |
|---|---|
max-age=86400 |
La risposta può essere memorizzata nella cache dai browser e dalle cache intermedie per un massimo di 1 giorno (60 secondi x 60 minuti x 24 ore). |
private, max-age=600 |
La risposta può essere memorizzata nella cache dal browser (ma non dalle cache intermedie) per un massimo di 10 minuti (60 secondi x 10 minuti). |
public, max-age=31536000 |
La risposta può essere memorizzata da qualsiasi cache per 1 anno. |
no-store |
La risposta non può essere memorizzata nella cache e deve essere recuperata per intero a ogni richiesta. |