Memorizzazione nella cache

Lo spazio di archiviazione della cache è uno strumento potente. Rende le tue app meno dipendenti dalle condizioni della rete. Con un buon utilizzo delle cache puoi rendere la tua applicazione web disponibile offline e pubblicare i tuoi asset il più rapidamente possibile in qualsiasi condizione di rete. Come accennato in Asset e dati, puoi decidere la strategia migliore per memorizzare nella cache gli asset necessari. Per gestire la cache, il service worker interagisce con l'API Cache Storage.

Supporto dei browser

  • Chrome: 43.
  • Edge: 16.
  • Firefox: 41.
  • Safari: 11.1.

Origine

L'API Cache Storage è disponibile per diversi contesti:

  • Il contesto della finestra (il thread principale della tua PWA).
  • Il service worker.
  • Eventuali altri worker che utilizzi.

Un vantaggio della gestione della cache mediante i service worker è che il suo ciclo di vita non è legato alla finestra, il che significa che non stai bloccando il thread principale. Tieni presente che per utilizzare l'API Cache Storage, la maggior parte di questi contesti deve trovarsi sotto una connessione TLS.

Che cosa memorizzare nella cache

La prima domanda che potresti avere sulla memorizzazione nella cache è "cosa devi memorizzare nella cache". Anche se non esiste un'unica risposta a questa domanda, puoi iniziare con tutte le risorse minime necessarie per visualizzare l'interfaccia utente.

Tali risorse dovrebbero includere:

  • Il codice HTML della pagina principale (start_url dell'app).
  • I fogli di stile CSS necessari per l'interfaccia utente principale.
  • Immagini utilizzate nell'interfaccia utente.
  • I file JavaScript necessari per il rendering dell'interfaccia utente.
  • Dati, ad esempio un file JSON, necessari per eseguire il rendering di un'esperienza di base.
  • Caratteri web.
  • In un'applicazione con più pagine, gli altri documenti HTML che vuoi pubblicare velocemente o offline.
di Gemini Advanced.

Pronto per l'utilizzo offline

Sebbene la funzionalità offline sia uno dei requisiti di un'app web progressiva, è essenziale capire che non tutte le PWA hanno bisogno di un'esperienza offline completa, ad esempio le soluzioni di cloud gaming o le app di crypto-asset. Pertanto, è possibile offrire un'interfaccia utente di base che guidi gli utenti attraverso queste situazioni.

La PWA non deve visualizzare un messaggio di errore del browser che comunica che il motore di rendering web non è riuscito a caricare la pagina. Utilizza invece il tuo service worker per mostrare i tuoi messaggi, evitando un errore generico e confuso del browser.

Esistono molte strategie di memorizzazione nella cache diverse che puoi utilizzare a seconda delle esigenze della tua PWA. Ecco perché è importante progettare l'utilizzo della cache in modo da offrire un'esperienza rapida e affidabile. Ad esempio, se tutti gli asset dell'app vengono scaricati velocemente, non occupano molto spazio e non devono essere aggiornati in ogni richiesta, la memorizzazione nella cache di tutti gli asset sarebbe una strategia valida. Se invece disponi di risorse che devono essere l'ultima versione, potresti prendere in considerazione di non memorizzarle affatto nella cache.

Utilizzo dell'API

Utilizza l'API Cache Storage per definire un set di cache all'interno della tua origine, ciascuna identificata con un nome stringa che puoi definire. Accedi all'API tramite l'oggetto caches e il metodo open consente la creazione o l'apertura di una cache già creata. Il metodo aperto restituisce una promessa per l'oggetto cache.

caches.open("pwa-assets")
.then(cache => {
  // you can download and store, delete or update resources with cache arguments
});

Scaricare e archiviare gli asset

Per chiedere al browser di scaricare e archiviare gli asset, utilizza i metodi add o addAll. Il metodo add effettua una richiesta e archivia una risposta HTTP, mentre addAll è un gruppo di risposte HTTP come transazione basata su un array di richieste o URL.

caches.open("pwa-assets")
.then(cache => {
  cache.add("styles.css"); // it stores only one resource
  cache.addAll(["styles.css", "app.js"]); // it stores two resources
});

L'interfaccia di archiviazione della cache archivia l'intera risposta, comprese tutte le intestazioni e il corpo. Di conseguenza, puoi recuperarla in un secondo momento utilizzando una richiesta HTTP o un URL come chiave. Per sapere come farlo, consulta il capitolo Pubblicazione.

Quando memorizzare nella cache

Nella PWA, sei tu a decidere quando memorizzare i file nella cache. Sebbene un approccio sia quello di archiviare il maggior numero possibile di asset quando il service worker è installato, di solito non è l'idea migliore. La memorizzazione nella cache di risorse non necessarie spreca larghezza di banda e spazio di archiviazione e potrebbe causare la pubblicazione da parte dell'app di risorse obsolete indesiderate.

Non è necessario memorizzare tutti gli asset nella cache contemporaneamente, puoi memorizzarli molte volte durante il ciclo di vita della PWA, ad esempio:

  • Al momento dell'installazione del service worker.
  • Dopo il primo caricamento pagina.
  • Quando l'utente raggiunge una sezione o un percorso.
  • Quando la rete è inattiva.

Puoi richiedere la memorizzazione nella cache di nuovi file nel thread principale o all'interno del contesto del service worker.

Memorizzazione degli asset nella cache in un service worker

Uno degli scenari più comuni è memorizzare nella cache un insieme minimo di asset quando viene installato il Service worker. Per farlo, puoi utilizzare l'interfaccia dello spazio di archiviazione della cache all'interno dell'evento install nel service worker.

Poiché il thread del service worker può essere interrotto in qualsiasi momento, puoi richiedere al browser di attendere il completamento della promessa addAll per aumentare le opportunità di archiviare tutti gli asset e mantenere l'app coerente. L'esempio seguente mostra come eseguire questa operazione, utilizzando il metodo waitUntil dell'argomento evento ricevuto nel listener di eventi del service worker.

const urlsToCache = ["/", "app.js", "styles.css", "logo.svg"];
self.addEventListener("install", event => {
   event.waitUntil(
      caches.open("pwa-assets")
      .then(cache => {
         return cache.addAll(urlsToCache);
      });
   );
});

Il metodo waitUntil() riceve una promessa e chiede al browser di attendere la risoluzione dell'attività nella promessa (completata o non riuscita) prima di terminare il processo del service worker. Potresti dover concatenare le promesse e restituire le chiamate add() o addAll() in modo che un singolo risultato raggiunga il metodo waitUntil().

Puoi gestire le promesse anche utilizzando la sintassi asincrona/await. In questo caso, devi creare una funzione asincrona che possa chiamare await e che restituisca una promessa a waitUntil() dopo la chiamata, come nell'esempio seguente:

const urlsToCache = ["/", "app.js", "styles.css", "logo.svg"];
self.addEventListener("install", (event) => {
   let cacheUrls = async () => {
      const cache = await caches.open("pwa-assets");
      return cache.addAll(urlsToCache);
   };
   event.waitUntil(cacheUrls());
});

Richieste interdominio e risposte opache

La PWA può scaricare e memorizzare nella cache asset dalla tua origine e tra domini, ad esempio i contenuti di CDN di terze parti. Con un'app interdominio, l'interazione con la cache è molto simile alle richieste della stessa origine. La richiesta viene eseguita e una copia della risposta viene archiviata nella cache. Come per altri asset memorizzati nella cache, possono essere utilizzati solo nell'origine dell'app.

L'asset verrà archiviato come risposta opaca, il che significa che il codice non sarà in grado di vedere o modificare i contenuti o le intestazioni di quella risposta. Inoltre, le risposte opache non espongono la loro dimensione effettiva nell'API Storage, il che influisce sulle quote. Alcuni browser espongono dimensioni di grandi dimensioni, ad esempio 7 Mb, indipendentemente dal fatto che il file sia di soli 1 kB.

Aggiornamento ed eliminazione degli asset

Puoi aggiornare gli asset utilizzando cache.put(request, response) ed eliminarli con delete(request).

Per ulteriori dettagli, consulta la documentazione relativa agli oggetti Cache.

Debug dello spazio di archiviazione della cache

Molti browser offrono un modo per eseguire il debug dei contenuti dello spazio di archiviazione della cache nella scheda Applicazione DevTools. Qui puoi vedere i contenuti di ogni cache all'interno dell'origine attuale. Approfondiremo questi strumenti nel capitolo Strumenti e debug.

Chrome DevTools durante il debug dei contenuti dello spazio di archiviazione della cache.

Risorse