Gérer les réponses de remplacement

Dans certains cas, vous pouvez souhaiter qu'une réponse de remplacement soit mise en cache si l'utilisateur est hors connexion. L'implémentation d'un remplacement est une alternative aux comportements de mise en cache fournis par des stratégies telles que les stratégies axées sur le réseau ou obsolètes pendant la revalidation.

Une création de remplacement est une réponse générique et universelle qui offre un meilleur espace réservé que ce que le navigateur fournit par défaut lorsqu'une requête échoue. Par exemple :

  • Une alternative à l'espace réservé "image manquante".
  • Alternative HTML à la page standard "Aucune connexion réseau disponible".

Page hors connexion uniquement

Si vous n'avez qu'à fournir une page HTML hors connexion personnalisée, mais rien d'autre, voici une recette de base que vous pouvez suivre:

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

setDefaultHandler(new NetworkOnly());

offlineFallback();

Le code ci-dessus utilise setDefaultHandler afin d'utiliser par défaut une stratégie basée uniquement sur le réseau pour toutes les routes. Il exécute ensuite la recette offlineFallback pour diffuser la création de remplacement hors connexion en cas d'erreur. La recette suppose que votre fichier HTML de remplacement hors connexion sera nommé offline.html et diffusé à partir de la racine de votre serveur Web.

Créations de remplacement complètes

Chaque fois qu'une défaillance du réseau ou un défaut de cache (miss) se produit, les stratégies de mise en cache proposées par workbox-strategies rejettent systématiquement les règles. Cela favorise le modèle qui consiste à définir un gestionnaire "catch" global pour gérer toute défaillance dans une fonction de gestionnaire unique, ce qui vous permet de proposer différents remplacements pour différentes valeurs request.destination.

L'exemple suivant utilise la recette warmStrategyCache de workbox-recipes et définit un gestionnaire de capture pour diffuser les éléments mis en cache à l'avance dans le cache d'exécution. Toutefois, la mise en cache préalable des remplacements peut être plus adaptée à votre application:

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();
  }
});

Dans cet article, les réponses de remplacement sont mises en cache en amont à l'aide de injectManifest avec les outils de compilation de Workbox et servent de solution de secours en cas d'erreur avec la méthode 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();
  }
});

Voici un exemple de cas d'utilisation pour la deuxième configuration de remplacement : une page a été mise en cache à l'avance, mais pas les images (ou d'autres éléments) demandées par la page. La page peut toujours être lue à partir du cache lorsque l'utilisateur est hors connexion, mais des espaces réservés de remplacement ou une autre fonctionnalité peuvent être fournis en cas d'erreur réseau.

Préparer le cache d'exécution

Workbox gère des caches distincts pour la mise en cache préalable et le cache d'exécution. Dans certains cas, vous pouvez souhaiter mettre en cache un élément à l'avance sans dépendre de la mise en cache préalable, car les mises à jour du fichier manifeste de mise en cache préalable nécessitent le déploiement d'un service worker mis à jour.

Pour amorcer le cache d'exécution à l'avance avec des éléments, vous pouvez utiliser la recette warmStrategyCache de workbox-recipes. En arrière-plan, cette stratégie appelle Cache.addAll dans l'événement install d'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});

Conclusion

La gestion des réponses de remplacement aux requêtes ayant échoué demande un peu de travail. Toutefois, avec un peu de planification, vous pouvez configurer votre application Web pour qu'elle fournisse un certain niveau de contenu et de fonctionnalités lorsque l'utilisateur est hors connexion.