Gestione delle risposte di fallback

In determinate situazioni, potresti voler memorizzare nella cache una risposta di fallback nel caso in cui l'utente sia offline. L'implementazione di un fallback è un'alternativa ai comportamenti di memorizzazione nella cache forniti da strategie come network-first o stale-while-revalidate.

Un fallback è una risposta generica e valida per tutti che rappresenta un segnaposto migliore di quello che il browser fornirà per impostazione predefinita in caso di esito negativo di una richiesta. Ecco alcuni esempi:

  • Un'alternativa al segnaposto "immagine mancante".
  • Un'alternativa HTML alla pagina standard "Nessuna connessione di rete disponibile".

Solo pagina offline

Se non devi fare altro che fornire una pagina HTML offline personalizzata, ma nient'altro, ecco una formula di base che puoi seguire:

import {offlineFallback} from 'workbox-recipes';
import {setDefaultHandler} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';

setDefaultHandler(new NetworkOnly());

offlineFallback();

Il codice riportato sopra utilizza setDefaultHandler per usare una strategia di sola rete come predefinita per tutte le route. Quindi esegue la formula offlineFallback per fornire il fallback offline in caso di errore. La formula presuppone che al file HTML di riserva offline venga denominato offline.html e venga pubblicato dalla directory principale del server web.

Fallback completi

Ogni volta che si verifica un errore di rete o un fallimento della cache, le strategie di memorizzazione nella cache offerte da workbox-strategies rifiutano in modo coerente. Ciò favorisce l'impostazione di un gestore "catch" globale per gestire eventuali errori in un'unica funzione di gestore, consentendoti di offrire diversi fallback per diversi valori request.destination.

L'esempio seguente utilizza la formula warmStrategyCache di workbox-recipes e imposta un gestore di cattura per pubblicare in anticipo gli elementi memorizzati nella cache nella cache di runtime. Tuttavia, la pre-memorizzazione nella cache può essere più adatta per la tua applicazione:

import {warmStrategyCache} from 'workbox-recipes';
import {setDefaultHandler, setCatchHandler} from 'workbox-routing';
import {CacheFirst, StaleWhileRevalidate} from 'workbox-strategies';

// Fallback assets to cache
const FALLBACK_HTML_URL = '/offline.html';
const FALLBACK_IMAGE_URL = '/images/image-not-found.jpg';
const FALLBACK_STRATEGY = new CacheFirst();

// Warm the runtime cache with a list of asset URLs
warmStrategyCache({
  urls: [FALLBACK_HTML_URL, FALLBACK_IMAGE_URL],
  strategy: FALLBACK_STRATEGY,
});

// Use a stale-while-revalidate strategy to handle requests by default.
setDefaultHandler(new StaleWhileRevalidate());

// This "catch" handler is triggered when any of the other routes fail to
// generate a response.
setCatchHandler(async ({request}) => {
  // The warmStrategyCache recipe is used to add the fallback assets ahead of
  // time to the runtime cache, and are served in the event of an error below.
  // Use `event`, `request`, and `url` to figure out how to respond, or
  // use request.destination to match requests for specific resource types.
  switch (request.destination) {
    case 'document':
      return FALLBACK_STRATEGY.handle({event, request: FALLBACK_HTML_URL});

    case 'image':
      return FALLBACK_STRATEGY.handle({event, request: FALLBACK_IMAGE_URL});

    default:
      // If we don't have a fallback, return an error response.
      return Response.error();
  }
});

Nel prossimo video, le risposte di riserva vengono pre-memorizzate nella cache utilizzando injectManifest con gli strumenti di creazione di Workbox e verranno utilizzate come riserva in caso di errore con il metodo matchPrecache.

import {matchPrecache, precacheAndRoute} from 'workbox-precaching';
import {setDefaultHandler, setCatchHandler} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';

// Optional: use the injectManifest mode of one of the Workbox
// build tools to precache a list of URLs, including fallbacks.
precacheAndRoute(self.__WB_MANIFEST);

// Use a stale-while-revalidate strategy to handle requests by default.
setDefaultHandler(new StaleWhileRevalidate());

// This "catch" handler is triggered when any of the other routes fail to
// generate a response.
setCatchHandler(async ({request}) => {
  // Fallback assets are precached when the service worker is installed, and are
  // served in the event of an error below. Use `event`, `request`, and `url` to
  // figure out how to respond, or use request.destination to match requests for
  // specific resource types.
  switch (request.destination) {
    case 'document':
      // FALLBACK_HTML_URL must be defined as a precached URL for this to work:
      return matchPrecache(FALLBACK_HTML_URL);

    case 'image':
      // FALLBACK_IMAGE_URL must be defined as a precached URL for this to work:
      return matchPrecache(FALLBACK_IMAGE_URL);

    default:
      // If we don't have a fallback, return an error response.
      return Response.error();
  }
});

Un esempio di caso d'uso per la seconda configurazione di riserva è il caso in cui una pagina sia stata memorizzata nella cache in anticipo, al contrario delle immagini (o di altri asset) richieste dalla pagina. La pagina può comunque essere letta dalla cache quando l'utente è offline, ma in caso di errore di rete possono essere forniti segnaposto di riserva o funzionalità alternative.

Riscaldamento della cache di runtime

Workbox mantiene cache separate per le cache di pre-memorizzazione e di runtime e potrebbero verificarsi situazioni in cui vuoi memorizzare qualcosa in anticipo senza fare affidamento sulla pre-memorizzazione nella cache, poiché gli aggiornamenti del manifest di pre-cache richiedono il deployment di un service worker aggiornato.

Per preparare in anticipo la cache di runtime con gli asset, puoi farlo utilizzando la formula warmStrategyCache di workbox-recipes. Di base, questa strategia chiama Cache.addAll nell'evento install di un service worker.

import {warmStrategyCache} from 'workbox-recipes';
import {CacheFirst} from 'workbox-strategies';

// This can be any strategy, CacheFirst used as an example.
const strategy = new CacheFirst();
const urls = [
  '/offline.html',
];

warmStrategyCache({urls, strategy});

Conclusione

La gestione delle risposte di riserva per le richieste non riuscite richiede un po' di lavoro, ma con un po' di pianificazione anticipata puoi configurare la tua app web in modo che fornisca un certo livello di contenuti e funzionalità quando l'utente è offline.