Administra respuestas de resguardo

En algunas situaciones, es posible que quieras almacenar en caché una respuesta de resguardo en caso de que el usuario se encuentre sin conexión. La implementación de un resguardo es una alternativa a los comportamientos de almacenamiento en caché que proporcionan estrategias como la prioridad en la red o el estado inactivo durante la revalidación.

Un resguardo es una respuesta genérica y universal que funciona como un marcador de posición mejor que el que proporcionaría el navegador de forma predeterminada cuando falla una solicitud. Por ejemplo:

  • Una alternativa al marcador de posición "imagen faltante".
  • Es una alternativa HTML a la página estándar "No hay conexión de red disponible".

Solo página sin conexión

Si todo lo que necesitas hacer es proporcionar una página HTML sin conexión personalizada, pero nada más, puedes seguir esta receta de referencia:

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

setDefaultHandler(new NetworkOnly());

offlineFallback();

El código anterior usa setDefaultHandler para emplear una estrategia solo de red como predeterminada para todas las rutas. Luego, ejecuta la receta offlineFallback para entregar el resguardo sin conexión en caso de que se produzca un error. La receta supone que tu archivo HTML de resguardo sin conexión se llamará offline.html y se entregará desde la raíz de tu servidor web.

Resguardos integrales

Cada vez que se produzca una falla en la red o un error de caché, las estrategias de almacenamiento en caché que ofrece workbox-strategies se rechazarán de manera constante. Esto promueve el patrón de configuración de un controlador "catch" global para abordar cualquier falla en una sola función del controlador, lo que te permite ofrecer diferentes resguardos para diferentes valores de request.destination.

En el siguiente ejemplo, se usa la receta warmStrategyCache de workbox-recipes y se configura un controlador de captura para entregar elementos almacenados en caché con anticipación en la caché del entorno de ejecución. Sin embargo, el almacenamiento previo en caché de los resguardos puede ser una mejor opción para tu aplicación:

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

A continuación, las respuestas de resguardo se almacenan previamente en caché mediante injectManifest con las herramientas de compilación de Workbox y se entregan como un resguardo en caso de que se produzca un error con el método 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 ejemplo de caso de uso para la segunda configuración de resguardo es si una página se almacenó en caché antes de tiempo, pero no lo fueron las imágenes (o cualquier otro recurso) solicitada por la página. La página aún se puede leer desde la caché cuando el usuario está sin conexión, pero se pueden proporcionar marcadores de posición de resguardo o funcionalidades alternativas si se produce un error de red.

Cómo calentar la caché del entorno de ejecución

Workbox mantiene cachés separados para el almacenamiento previo en caché y el almacenamiento en caché del entorno de ejecución, y puede haber situaciones en las que quieras almacenar en caché algo con anticipación sin depender del almacenamiento previo en caché, ya que las actualizaciones del manifiesto de almacenamiento previo en caché requerirán que implementes un service worker actualizado.

Para preparar la caché del entorno de ejecución de manera anticipada con elementos, puedes hacerlo mediante la receta warmStrategyCache de workbox-recipes. De forma interna, esta estrategia llama a Cache.addAll en el evento install de 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});

Conclusión

Administrar las respuestas de resguardo para solicitudes fallidas requiere un poco de trabajo, pero con un poco de planificación anticipada, puedes configurar tu aplicación web para que proporcione cierto nivel de contenido y funcionalidad cuando el usuario no tiene conexión.