La tua cache ❤️

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

Questo post è un complemento del video Love your cache, che fa parte della sezione Extended Content al Chrome Dev Summit 2020. Non perderti il video:

Quando gli utenti caricano il tuo sito una seconda volta, il browser utilizza le risorse nella cache HTTP per velocizzare il caricamento. Tuttavia, gli standard per la memorizzazione nella cache sul web risalgono al 1999 e sono definiti in modo abbastanza ampio, quindi non è sufficiente stabilire se un file, come CSS o un'immagine, può essere recuperato nuovamente dalla rete e non caricato dalla cache.

In questo post ti parlerò di un valore predefinito ragionevole e moderno per la memorizzazione nella cache, che in realtà non prevede alcuna memorizzazione nella cache. Ma questa è solo l'impostazione predefinita ed è ovviamente più articolata rispetto al semplice "disattivarlo". Continua a leggere.

Obiettivi

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

  1. Assicurati che gli utenti dispongano della versione più aggiornata disponibile. Se hai apportato delle modifiche, la versione si riflette rapidamente
  2. Esegui la prima operazione di recupero dalla rete il più possibile

In senso lato, l'obiettivo è inviare la modifica minima ai clienti solo quando ricaricano il tuo sito. Inoltre, strutturare il sito in modo da garantire la distribuzione più efficiente di qualsiasi modifica non è facile (scopri di più di seguito e nel video).

Detto questo, sono disponibili anche altre manopole per la memorizzazione nella cache. Magari hai deciso di lasciare che la cache HTTP del browser di un utente rimanga sul tuo sito per molto tempo, in modo che non siano necessarie richieste di rete per gestirlo. Oppure hai creato un service worker che pubblicherà un sito interamente offline prima di verificare se è aggiornato. Si tratta di un'opzione estrema, valida (e utilizzata per molte esperienze web simili a quelle delle app offline), ma il web non deve trovarsi a un livello estremo solo della cache o addirittura del solo rete.

Contesto

In qualità di sviluppatori web, siamo tutti abituati all'idea di avere una "cache inattiva". Ma sappiamo, quasi istintivamente, gli strumenti disponibili per risolvere questo problema: eseguire un "aggiornamento forzato", aprire una finestra di navigazione in incognito oppure utilizzare una combinazione degli strumenti per sviluppatori del browser per cancellare i dati di un sito.

Gli utenti abituali su internet non hanno lo stesso lusso. Pertanto, anche se abbiamo alcuni obiettivi fondamentali per assicurarci che i nostri utenti si divertano con il loro secondo caricamento, è anche molto importante assicurarsi che non abbiano un brutto momento o che non rimangano bloccati. Guarda il video se vuoi che mi parli di come abbiamo quasi bloccato il sito web.dev/live.

Per qualche informazione generale, uno dei motivi più comuni per la "cache inattiva" è in realtà l'impostazione predefinita degli anni '99 per la memorizzazione nella cache. Si basa sull'intestazione Last-Modified:

Diagramma che mostra per quanto tempo i diversi asset vengono memorizzati nella cache dal browser di un utente
Gli asset generati in momenti diversi (in grigio) verranno memorizzati nella cache in momenti diversi, quindi un secondo caricamento può ottenere una combinazione di asset aggiornati e memorizzati nella cache

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

In passato era un'idea ben ideata, ma data la natura strettamente integrata dei siti web odierni, questo comportamento predefinito consente di entrare in uno stato in cui un utente dispone di file progettati per versioni diverse del sito web (ad es. il codice JS della release di martedì e il CSS della release di venerdì), il tutto perché quei file non sono stati aggiornati esattamente nello stesso momento.

Il percorso ben illuminato

Un valore predefinito moderno per la memorizzazione nella cache è non eseguire alcuna memorizzazione nella cache e utilizzare le CDN per avvicinare i contenuti agli utenti. Ogni volta che un utente carica il tuo sito, visita la rete per verificare che sia aggiornato. Questa richiesta avrà una bassa latenza, in quanto verrà fornita da una CDN geograficamente vicina a ogni utente finale.

Puoi configurare l'host web in modo che risponda alle richieste web con questa intestazione:

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

Questo fondamentalmente dice che il file non è valido per niente e che deve essere convalidato dalla rete prima di poterlo utilizzare di nuovo (in caso contrario è solo "suggerito").

Questo processo di convalida è relativamente economico in termini di byte trasferiti. Se un file immagine di grandi dimensioni non è cambiato, il browser riceverà una risposta 304 di dimensioni ridotte, ma costa latenza perché un utente deve comunque accedere alla rete per scoprirlo. Questo è il principale svantaggio di questo approccio. Può funzionare molto bene per chi dispone di connessioni veloci nel primo mondo e in cui la rete CDN scelta ha un'ottima copertura, ma non per chi potrebbe utilizzare connessioni mobili più lente o un'infrastruttura scadente.

In ogni caso, si tratta di un approccio moderno che è l'impostazione predefinita su una rete CDN molto diffusa, Netlify, ma che può essere configurato su quasi tutte le reti CDN. Per Firebase Hosting, puoi includere questa intestazione nella sezione relativa all'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"
    }
  }
]

Quindi, anche se suggerisco comunque questo valore predefinito ragionevole, è solo quello: l'impostazione predefinita. Continua a leggere per scoprire come eseguire l'upgrade delle impostazioni predefinite.

URL con fingerprint

Se includi un hash dei contenuti del file nel nome degli asset, delle immagini e così via pubblicati sul tuo sito, puoi assicurarti che questi file avranno sempre contenuti univoci, generando così file denominati sitecode.af12de.js, ad esempio. Quando il tuo server risponde alle richieste di questi file, puoi indicare in modo sicuro ai browser dell'utente finale di memorizzarli nella cache per molto tempo configurandoli con questa intestazione:

Cache-Control: max-age=31536000,immutable

Questo valore è un anno, in secondi. E secondo le specifiche, è uguale a "per sempre".

Soprattutto, non generare questi hash manualmente: si tratta di un lavoro manuale eccessivo. Puoi utilizzare strumenti come Webpack, Rollup e così via per aiutarti. Scopri di più nel report sugli strumenti.

Ricorda che gli URL con fingerprint non sono solo JavaScript, ma anche asset come icone, CSS e altri file di dati immutabili possono essere denominati in questo modo. Guarda anche il video riportato sopra per saperne di più sulla suddivisione del codice, che ti consente di distribuire meno codice ogni volta che il sito cambia.

Indipendentemente dall'approccio del sito per la memorizzazione nella cache, questi tipi di file con fingerprint sono incredibilmente preziosi per qualsiasi sito che potresti creare. La maggior parte dei siti non cambia a ogni versione.

Naturalmente, non possiamo rinominare le nostre pagine "intuitive" rivolte agli utenti in questo modo: rinominando il file index.html in index.abcd12.html. Questo è impossibile. Non puoi chiedere agli utenti di accedere a un nuovo URL ogni volta che caricano il tuo sito. Questi URL semplici non possono essere rinominati e memorizzati nella cache in questo modo, e questo ci porta a un possibile passaggio intermedio.

La via di mezzo

Esiste ovviamente spazio per una via di mezzo per quanto riguarda la memorizzazione nella cache. Ho presentato due opzioni estreme: cache never o cache forever. E ci saranno vari file che potreste voler memorizzare nella cache per un certo periodo, come gli URL "correvoli" di cui sopra.

Se vuoi memorizzare nella cache questi URL "Semplici" e il relativo HTML, vale la pena considerare quali dipendenze includono, come possono essere memorizzate nella cache e in che modo la memorizzazione nella cache degli URL per un determinato periodo di tempo potrebbe interessarti. Diamo un'occhiata a una pagina HTML che include un'immagine simile alla seguente:

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

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

Se fai attenzione, questa situazione potrebbe non interessarti. Ma in generale è importante ricordare che il tuo sito, quando gli utenti finali lo memorizzano nella cache, 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 parlano di questo tipo di impostazione: memorizzare nella cache per un'ora, diverse ore e così via. Per impostare questo tipo di cache, utilizza un'intestazione simile alla seguente (che viene memorizzata nella cache per 3600 secondi o un'ora):

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

Un ultimo punto. Se crei contenuti tempestivi a cui gli utenti potrebbero accedere soltanto una volta, ad esempio gli articoli, credo che questi contenuti non debbano mai essere memorizzati nella cache, perciò dovresti utilizzare la nostra opzione predefinita opportuna. Penso che spesso sopravvalutiamo il valore della memorizzazione nella cache piuttosto che il desiderio di un utente di vedere sempre i contenuti più recenti e migliori, come un aggiornamento critico su una notizia o un evento attuale.

Opzioni non HTML

Oltre all'HTML, ci sono altre opzioni per i file che si trovano nella base centrale:

  • In generale, cerca gli asset che non influiscono sugli altri

    • Ad esempio, evita CSS, perché causa modifiche al modo in cui il tuo codice HTML viene visualizzato.
  • Immagini di grandi dimensioni utilizzate all'interno di articoli di attualità

    • I tuoi utenti probabilmente non visiteranno un singolo articolo più di una manciata di volte, quindi non memorizzare per sempre le foto o le immagini hero e smaltire i rifiuti
  • Una risorsa che rappresenta qualcosa a sé stante

    • I dati JSON sul meteo possono essere pubblicati ogni ora, così puoi memorizzare nella cache il risultato precedente per un'ora,
    • Poiché le build di un progetto open source potrebbero avere limitazioni di frequenza, quindi memorizza nella cache un'immagine di stato della build

Riepilogo

Quando gli utenti caricano il sito una seconda volta, hai già espresso il tuo grado di fiducia: vogliono tornare e ricevere più informazioni sui tuoi prodotti. A questo punto, non sempre si tratta solo di ridurre il tempo di caricamento e hai a disposizione una serie di opzioni per fare in modo che il browser svolga solo il lavoro necessario per offrire un'esperienza veloce e aggiornata.

La memorizzazione nella cache non è un concetto nuovo sul web, ma forse ha bisogno di un valore predefinito ragionevole. Prendi in considerazione l'utilizzo di un valore predefinito e l'attivazione di strategie di memorizzazione nella cache migliori quando ne hai bisogno. Grazie per l'attenzione.

Vedi anche

Per una guida generale sulla cache HTTP, consulta l'articolo Prevenire le richieste di rete non necessarie con la cache HTTP.