Memorizzazione nella cache

Lo spazio di archiviazione della cache è uno strumento potente. Le tue app sono meno dipendenti dalle condizioni della rete. Se utilizzi bene le cache, puoi rendere la tua app web disponibile offline e pubblicare gli asset il più rapidamente possibile in qualsiasi condizione di rete. Come indicato in Asset e dati, puoi decidere la strategia migliore per memorizzare nella cache gli asset necessari. Per gestire la cache, il tuo 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 tramite i worker di servizio è che il relativo ciclo di vita non è legato alla finestra, il che significa che non blocchi il thread principale. Tieni presente che per utilizzare l'API Cache Storage la maggior parte di questi contesti deve essere sotto una connessione TLS.

Che cosa memorizzare nella cache

La prima domanda che potresti porti sulla memorizzazione nella cache riguarda cosa memorizzare nella cache. Sebbene non esista una sola risposta a questa domanda, puoi iniziare con tutte le risorse minime necessarie per eseguire il rendering dell'interfaccia utente.

Queste risorse devono 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.
  • File JavaScript necessari per il rendering dell'interfaccia utente.
  • Dati, ad esempio un file JSON, necessari per visualizzare un'esperienza di base.
  • Caratteri web.
  • In un'applicazione multipagina, altri documenti HTML che vuoi pubblicare rapidamente o offline.

Pronto per l'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 il messaggio di errore di un browser che indica 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 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 rapidamente, 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 insieme di cache all'interno dell'origine, ognuna identificata con un nome di 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 open 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
});

Download e archiviazione di asset

Per chiedere al browser di scaricare e memorizzare gli asset, utilizza i metodi add o addAll. Il metodo add invia una richiesta e memorizza una risposta HTTP, mentre addAll un gruppo di risposte HTTP come transazione in base a 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 memorizza l'intera risposta, incluse tutte le intestazioni e il corpo. Di conseguenza, puoi recuperarla in un secondo momento utilizzando una richiesta HTTP o un URL come chiave. Scopri come farlo nel capitolo Pubblicazione.

Quando memorizzare nella cache

Nella tua PWA, sei tu a decidere quando memorizzare nella cache i file. Sebbene un approccio sia quello di archiviare il maggior numero possibile di asset quando il service worker è installato, in genere non è la soluzione migliore. La memorizzazione nella cache di risorse non necessarie comporta uno spreco di larghezza di banda e spazio di archiviazione e potrebbe causare il caricamento di risorse obsolete non intenzionali da parte dell'app.

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

  • All'installazione del service worker.
  • Dopo il primo caricamento pagina.
  • Quando l'utente passa a una sezione o a un percorso.
  • Quando la rete è inattiva.

Puoi richiedere la memorizzazione nella cache di nuovi file nel thread principale o nel contesto del servizio 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 di archiviazione della cache all'interno dell'evento install nel service worker.

Poiché il thread del worker del servizio può essere interrotto in qualsiasi momento, puoi chiedere al browser di attendere il completamento della promessa addAll per aumentare le possibilità 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 (soddisfatta o non riuscita) prima di terminare il processo del worker di servizio. Potresti dover concatenare le promesse e restituire le chiamate add() o addAll() in modo che un singolo risultato venga inviato al metodo waitUntil().

Puoi anche gestire le promesse utilizzando la sintassi async/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 non trasparenti

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 cross-domain, l'interazione con la cache è molto simile alle richieste con la stessa origine. La richiesta viene eseguita e una copia della risposta viene archiviata nella cache. Come per gli altri asset memorizzati nella cache, può essere utilizzato solo nell'origine dell'app.

La risorsa verrà archiviata come risposta opaca, il che significa che il codice non potrà vedere o modificare i contenuti o le intestazioni di questa risposta. Inoltre, le risposte opache non ne espongono le dimensioni effettive nell'API Storage, con ripercussioni sulle quote. Alcuni browser mostrano dimensioni elevate, ad esempio 7 MB, indipendentemente dal fatto che il file sia di soli 1 KB.

Aggiornamento ed eliminazione di asset

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

Per ulteriori dettagli, consulta la documentazione dell'oggetto Cache.

Debug dello spazio di archiviazione cache

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

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

Risorse