La tua cache ❤️

Gli utenti che caricano il tuo sito una seconda volta utilizzeranno la cache HTTP, quindi assicurati che funzioni correttamente.

Questo post è complementare al video Ama la tua cache, che fa parte dei contenuti estesi del Chrome Dev Summit 2020. Guarda il video:

Quando gli utenti caricano il tuo sito una seconda volta, il browser utilizzerà le risorse all'interno della sua cache HTTP per velocizzare il caricamento. Tuttavia, gli standard per la memorizzazione nella cache sul web risalgono al 1999 e sono definiti in modo piuttosto ampio. Determinare se un file, come un CSS o un'immagine, può essere recuperato di nuovo dalla rete o caricato dalla cache è una scienza un po' imprecisa.

In questo post, illustrerò un'impostazione predefinita moderna e sensata per la memorizzazione nella cache, che non esegue alcuna memorizzazione nella cache. Tuttavia, si tratta solo del valore predefinito e, ovviamente, è più sfumato di una semplice "disattivazione". Continua a leggere.

Obiettivi

Quando un sito viene caricato per la seconda volta, hai due obiettivi:

  1. Assicurati che i tuoi utenti ricevano la versione più aggiornata disponibile. Se hai apportato una modifica, questa dovrebbe essere applicata rapidamente.
  2. Esegui il passaggio 1 recuperando il meno possibile dalla rete

In senso più ampio, vuoi inviare ai clienti solo la minima modifica quando caricano di nuovo il tuo sito. Inoltre, strutturare il sito in modo da garantire la distribuzione più efficiente di qualsiasi modifica è una sfida (di seguito e nel video sono riportate maggiori informazioni in merito).

Detto questo, hai a disposizione anche altri parametri per la cache. Ad esempio, potresti decidere di lasciare che la cache HTTP del browser di un utente memorizzi il tuo sito per molto tempo in modo che non siano necessarie richieste di rete per pubblicarlo. In alternativa, hai creato un service worker che pubblicherà un sito completamente offline prima di verificare se è aggiornato. Si tratta di un'opzione estrema, valida e utilizzata per molte esperienze web simili ad app offline, ma il web non deve essere necessariamente basato solo sulla cache o solo sulla rete.

Sfondo

In qualità di sviluppatori web, siamo tutti abituati all'idea di avere una "cache non aggiornata". Tuttavia, sappiamo, quasi istintivamente, quali sono gli strumenti disponibili per risolvere il problema: esegui un "aggiornamento forzato", apri una finestra di navigazione in incognito o utilizza una combinazione di strumenti per sviluppatori del browser per cancellare i dati di un sito.

Gli utenti normali su internet non hanno questo lusso. Pertanto, anche se abbiamo alcuni obiettivi principali per garantire che i nostri utenti si divertano con il secondo caricamento, è anche molto importante assicurarsi che non abbiano una esperienza negativa o che non si blocchino. (Guarda il video se vuoi ascoltare la mia storia su come abbiamo rischiato di bloccare il sito web.dev/live.)

Per un po' di contesto, un motivo molto comune per la "cache non aggiornata" è in realtà la modalità predefinita per la memorizzazione nella cache del 1999. Si basa sull'intestazione Last-Modified:

Diagramma che mostra per quanto tempo le risorse diverse vengono memorizzate nella cache dal browser di un utente
Gli asset generati in momenti diversi (in grigio) verranno memorizzati nella cache per periodi diversi, pertanto un secondo caricamento può ottenere una combinazione di asset memorizzati nella cache e nuovi

Ogni file caricato viene conservato per un ulteriore 10% della sua durata attuale, come lo vede il browser. Ad esempio, se index.html è stato creato un mese fa, viene memorizzato nella cache dal browser per altri tre giorni circa.

In passato era un'idea ben intenzionata, ma data la natura strettamente integrata dei siti web di oggi, questo comportamento predefinito significa che è possibile ritrovarsi in una situazione in cui un utente ha file progettati per release diverse del tuo sito web (ad es. il codice JS della release di martedì e il codice CSS della release di venerdì), il tutto perché questi file non sono stati aggiornati esattamente nello stesso momento.

Il percorso ben illuminato

Un'impostazione predefinita moderna per la memorizzazione nella cache è non eseguire alcuna memorizzazione nella cache e utilizzare CDN per avvicinare i contenuti ai tuoi utenti. Ogni volta che un utente carica il tuo sito, si reca sulla rete per verificare se è aggiornato. Questa richiesta avrà una latenza ridotta, in quanto verrà fornita da una CDN geograficamente vicina a ogni utente finale.

Puoi configurare il tuo host web in modo che risponda alle richieste web con questa intestazione:

Cache-Control: max-age=0,must-revalidate,public

In pratica, il file non è valido per nessun periodo di tempo e devi convalidarlo dalla rete prima di poterlo utilizzare di nuovo (altrimenti è solo "suggerito").

Questa procedura di convalida è relativamente economica in termini di byte trasferiti: se un file immagine di grandi dimensioni non è cambiato, il browser riceverà una piccola risposta 304, ma comporta un costo in termini di latenza, poiché l'utente deve comunque accedere alla rete per scoprirlo. Ed è questo il principale svantaggio di questo approccio. Può funzionare molto bene per gli utenti con connessioni rapide nei paesi sviluppati e dove la CDN scelta ha una copertura eccezionale, ma non per gli utenti con connessioni mobile più lente o che utilizzano infrastrutture scadenti.

Tuttavia, si tratta di un approccio moderno che è predefinito su una popolare CDN, Netlify, ma può essere configurato su quasi tutte le CDN. Per Firebase Hosting, puoi includere questo intestazione nella sezione di hosting del file firebase.json:

"headers": [
  // Be sure to put this last, to not override other headers
  {
    "source": "**",
    "headers": [ {
      "key": "Cache-Control",
      "value": "max-age=0,must-revalidate,public"
    }
  }
]

Sebbene continui a consigliarla come impostazione predefinita sensata, non è altro che questo: l'impostazione predefinita. Continua a leggere per scoprire come intervenire e aggiornare i valori predefiniti.

URL con impronta digitale

Se includi un hash dei contenuti del file nel nome di asset, immagini e così via pubblicati sul tuo sito, puoi assicurarti che questi file abbiano sempre contenuti unici. Ad esempio, i file avranno nomi come sitecode.af12de.js. Quando il tuo server risponde alle richieste di questi file, puoi chiedere in tutta sicurezza ai browser degli utenti finali di memorizzarli nella cache per molto tempo configurandoli con questo intestazione:

Cache-Control: max-age=31536000,immutable

Questo valore è un anno in secondi. E, in base alla specifica, è effettivamente uguale a "per sempre".

È importante non generare questi hash manualmente, perché è un lavoro troppo manuale. Puoi utilizzare strumenti come Webpack, Rollup e così via per aiutarti. Assicurati di leggere di più nel report sugli strumenti.

Ricorda che non è solo JavaScript a poter trarre vantaggio dagli URL con impronta; anche asset come icone, CSS e altri file di dati immutabili possono essere denominati in questo modo. Inoltre, guarda il video qui sopra per scoprire di più sulla suddivisione del codice, che ti consente di pubblicare meno codice ogni volta che il tuo sito cambia.

Indipendentemente dall'approccio del tuo sito alla memorizzazione nella cache, questi tipi di file con impronte digitali sono incredibilmente importanti per qualsiasi sito che potresti creare. La maggior parte dei siti non cambia con ogni release.

Ovviamente, non possiamo rinominare in questo modo le nostre pagine "amichevoli" rivolte agli utenti: rinominare il file index.html in index.abcd12.html non è fattibile, non puoi chiedere agli utenti di visitare un nuovo URL ogni volta che caricano il tuo sito. Questi URL "amichevoli" non possono essere rinominati e memorizzati nella cache in questo modo, il che mi fa pensare a un possibile compromesso.

La via di mezzo

Ovviamente, esiste una via di mezzo per la memorizzazione nella cache. Ho presentato due opzioni estreme: cache mai o cache sempre. Inoltre, potresti voler memorizzare nella cache per un po' di tempo una serie di file, ad esempio gli URL "amichevoli" che ho menzionato sopra.

Se vuoi memorizzare nella cache questi URL "amichevoli" e il relativo codice HTML, vale la pena di considerare le dipendenze che includono, come possono essere memorizzati nella cache e in che modo la memorizzazione nella cache dei relativi URL per un determinato periodo di tempo potrebbe influire su di te. Esamineremo una pagina HTML che include un'immagine come questa:

<img src="/images/foo.jpeg" loading="lazy" />

Se aggiorni o modifichi il tuo sito eliminando o modificando questa immagine con caricamento differito, gli utenti che visualizzano una versione memorizzata nella cache del tuo codice HTML potrebbero visualizzare un'immagine errata o mancante, perché hanno ancora memorizzato nella cache l'/images/foo.jpeg originale quando visitano di nuovo il tuo sito.

Se fai attenzione, questo problema potrebbe non riguardarti. In generale, però, è importante ricordare che il tuo sito, quando viene memorizzato nella cache dagli utenti finali, non esiste più solo sui tuoi server. Potrebbe invece essere presente in pezzi all'interno delle cache dei browser degli utenti finali.

In generale, la maggior parte delle guide sulla memorizzazione nella cache parla di questo tipo di impostazione: vuoi memorizzare nella cache per un'ora, per diverse ore e così via. Per impostare questo tipo di cache, utilizza un'intestazione come questa (che memorizza nella cache per 3600 secondi, ovvero un'ora):

Cache-Control: max-age=3600,immutable,public

Un ultimo punto. Se crei contenuti tempestivi che in genere potrebbero essere acceduti dagli utenti solo una volta, come gli articoli di notizie, secondo me non dovrebbero mai essere memorizzati nella cache e dovresti utilizzare il valore predefinito ragionevole riportato sopra. Penso che spesso overestimate il valore della memorizzazione nella cache rispetto al desiderio di un utente di vedere sempre i contenuti più recenti e migliori, ad esempio un aggiornamento critico su una notizia o un evento di attualità.

Opzioni non HTML

Oltre all'HTML, alcune altre opzioni per i file che si trovano a metà tra i due estremi includono:

  • In generale, cerca asset che non influiscono su altri

    • Ad esempio, evita il CSS, in quanto causa modifiche al modo in cui viene visualizzato il codice HTML.
  • Immagini di grandi dimensioni utilizzate all'interno di articoli tempestivi

    • I tuoi utenti probabilmente non visiteranno un singolo articolo più di un paio di volte, quindi non memorizzare nella cache foto o immagini hero per sempre e sprecare spazio di archiviazione
  • Una risorsa che rappresenta qualcosa che ha una durata

    • I dati JSON relativi al meteo potrebbero essere pubblicati solo ogni ora, quindi puoi memorizzare nella cache il risultato precedente per un'ora, poiché non cambierà nella finestra
    • Le build di un progetto open source potrebbero essere limitate in termini di frequenza, quindi memorizza nella cache un'immagine dello stato di compilazione finché non è possibile che lo stato cambi

Riepilogo

Quando gli utenti caricano il tuo sito una seconda volta, hanno già dato un voto di fiducia: vogliono tornare e usufruire di più di ciò che offri. A questo punto, non si tratta sempre solo di ridurre il tempo di caricamento e hai a disposizione una serie di opzioni per assicurarti che il browser esegua solo le operazioni necessarie per offrire un'esperienza rapida e aggiornata.

La memorizzazione nella cache non è un concetto nuovo sul web, ma forse ha bisogno di un valore predefinito sensato. Valuta la possibilità di utilizzarne uno e di attivare vivamente strategie di memorizzazione nella cache migliori quando ne hai bisogno. Grazie per l'attenzione.

Vedi anche

Per una guida generale sulla cache HTTP, consulta Impedire le richieste di rete non necessarie con la cache HTTP.