Workbox

Mantener la lógica de almacenamiento en caché y el service worker puede ser todo un desafío a medida que crece tu AWP. Workbox es un conjunto de bibliotecas de código abierto para ayudarte con eso. Workbox encapsula las APIs de bajo nivel, como la API de Service Worker y la API de Cache Storage, y expone interfaces más fáciles de usar para los desarrolladores.

Algunas de las tareas en las que puede ayudar son hacer coincidir las estrategias de almacenamiento en caché con las rutas de acceso (o patrones de enrutamiento), trabajar con transmisiones y usar funciones como la sincronización en segundo plano con resguardos adecuados.

Workbox puede ayudarte a administrar tus necesidades de entrega y almacenamiento en caché de recursos. También es la biblioteca más usada para service workers. que se usa en el 54% de los sitios móviles y se utiliza en muchas herramientas de compilación y CLI, incluidas las CLI de Angular, Create-React-App y Vue. También existen complementos para la mayoría de las bibliotecas y frameworks, como Next.js.

El 54%

Los sitios móviles con service workers usan la biblioteca de Workbox

Módulos del cuadro de trabajo

Workbox incluye varias bibliotecas, denominadas módulos internamente, cada una enfocada en un aspecto diferente de la administración de recursos y el comportamiento del service worker.

Los módulos de la caja de trabajo funcionan en diferentes contextos, como los siguientes:

  • Dentro del contexto de un service worker: Importas los módulos que necesitas y los usas desde tu archivo de service worker, por ejemplo, para administrar el almacenamiento en caché y entregar archivos con diferentes estrategias.
  • Dentro del contexto window principal: ayudar a registrar un service worker y comunicarse con él
  • Como parte de un sistema de compilación: Por ejemplo, webpack, para crear un manifiesto de tus recursos o incluso generar tu service worker completo.

Estos son algunos de los módulos más populares:

  • workbox-routing: Cuando el service worker intercepta solicitudes, este módulo enruta esas solicitudes a diferentes funciones que proporcionan respuestas. Es una implementación del controlador de eventos fetch, como se menciona en el capítulo de Publicación.
  • workbox-strategies: Es un conjunto de estrategias de almacenamiento en caché en el entorno de ejecución que controlan la respuesta a una solicitud, como caché primero y inactiva durante la revalidación. Se trata de una implementación de las diferentes estrategias mencionadas en el capítulo Publicación de anuncios.
  • workbox-precaching: Es una implementación de almacenamiento en caché de archivos en el controlador de eventos install del service worker (también conocido como almacenamiento previo en caché), como se menciona en el capítulo sobre almacenamiento en caché. Con este módulo, puedes prealmacenar un conjunto de archivos en caché con facilidad y administrar las actualizaciones de esos activos de manera eficiente. Abordaremos la actualización de recursos en el capítulo Actualizar.
  • workbox-expiration: Es un complemento que se usa con las estrategias de almacenamiento en caché para quitar solicitudes en caché según la cantidad de elementos en la caché o según la antigüedad de la solicitud almacenada en caché. Ayuda a administrar las cachés y establece límites en el tiempo y la cantidad de elementos en cada caché.
  • workbox-window: Un conjunto de módulos diseñados para ejecutarse en el contexto de la ventana, es decir, dentro de las páginas web de la AWP. Puedes simplificar el proceso de registro y actualizaciones del service worker, así como facilitar la comunicación entre el código que se ejecuta en el contexto del service worker y el contexto de la ventana.

Uso de Workbox

Workbox proporciona diferentes formas de integrar a tu AWP. Puedes elegir la que mejor se adapte a la arquitectura de tu app:

  • CLI de Workbox: Es una utilidad de línea de comandos que genera un service worker completo, inserta un manifiesto en el almacenamiento previo en caché o copia los archivos necesarios de Workbox.
  • Compilación de Workbox: Es un módulo de npm que genera un service worker completo, inserta un manifiesto en el almacenamiento previo en caché y copia los archivos de Workbox. Esto está diseñado para integrarse en tu propio proceso de compilación.
  • workbox-sw: Es una forma de cargar paquetes de service worker de Workbox desde una CDN que no usa un proceso de compilación.

La CLI de Workbox proporciona un asistente que te guía a través de la creación del service worker. Para ejecutar el asistente, escribe lo siguiente en una línea de comandos:

npx workbox-cli wizard

La CLI de Workbox en acción en una terminal

Almacenamiento en caché y entrega con Workbox

Un uso común de Workbox es usar los módulos de enrutamiento y estrategias juntos para almacenar en caché y entregar archivos.

El módulo Workbox-strategies brinda instrucciones listas para usar las estrategias de almacenamiento en caché que se analizan en los capítulos Recursos y datos y Publicación.

El módulo enrutamiento de la caja de trabajo ayuda a ordenar las solicitudes entrantes del service worker y hacerlas coincidir con estrategias o funciones de almacenamiento en caché para obtener respuestas a esas solicitudes.

Después de la coincidencia de las rutas con las estrategias, Workbox también ofrece la posibilidad de filtrar qué respuestas se agregarán a la caché con el complemento workbox-cacheable-response. Con este complemento, puedes, por ejemplo, almacenar en caché solo las respuestas que se mostraron sin errores.

En la siguiente muestra de código, se usa una estrategia que prioriza la caché (a través del módulo CacheFirst) para almacenar en caché y publicar navegaciones de páginas.

import { registerRoute } from 'workbox-routing';
import { CacheFirst } from 'workbox-strategies';
import { CacheableResponsePlugin } from 'workbox-cacheable-response';

const pageStrategy = new CacheFirst({
  // Put all cached files in a cache named 'pages'
  cacheName: 'pages',
  plugins: [
    // Only requests that return with a 200 status are cached
    new CacheableResponsePlugin({
      statuses: [200],
    }),
  ],
});

El complemento te permite aprovechar el ciclo de vida de resolución de solicitudes y el almacenamiento en caché de Workbox. Aquí, CacheableResponsePlugin solo se usa para almacenar en caché las solicitudes que dan como resultado un estado 200, lo que evita que se guarden solicitudes incorrectas en la caché.

Una vez creada la estrategia, es hora de registrar una ruta para usarla. En el siguiente ejemplo, se llama a registerRoute() y se pasa un objeto Request a su devolución de llamada. Si request.mode es "navigate", usa la estrategia CacheFirst (aquí llamada pageStrategy) que se definió en el ejemplo de código anterior.

// Cache page navigations (HTML) with a Cache First strategy
registerRoute( ({ request }) => request.mode === 'navigate',
  pageStrategy );

Lee la documentación de Workbox para ver más ejemplos y prácticas recomendadas.

Resguardo sin conexión

El módulo workbox-routing también tiene un setCatchHandler() exportado, que brinda control si una ruta arroja un error. Puedes usar esta opción para configurar un resguardo sin conexión y notificar a los usuarios que la ruta solicitada no está disponible en este momento.

Aquí, una combinación de Workbox y la API de Cache Storage proporciona un resguardo sin conexión a través de una estrategia de solo caché. Primero, durante el ciclo de vida de instalación del service worker, se abre la caché offline-fallbacks y se agrega a ella el array de resguardos sin conexión.

import { setCatchHandler } from 'workbox-routing';

// Warm the cache when the service worker installs
self.addEventListener('install', event => {
  const files = ['/offline.html']; // you can add more resources here
  event.waitUntil(
    self.caches.open('offline-fallbacks')
        .then(cache => cache.addAll(files))
  );
});

Luego, en setCatchHandler(), se determina el destino de la solicitud que arrojó un error y se abre la caché offline-fallbacks. Si el destino es un documento, el contenido del resguardo sin conexión se muestra al usuario. Si no existe o el destino no es un documento (como una imagen o una hoja de estilo), se muestra una respuesta de error. Puedes ampliar este patrón no solo para documentos, sino también para imágenes, videos, fuentes y todo lo que desees proporcionar como resguardo sin conexión.

// Respond with the fallback if a route throws an error
setCatchHandler(async (options) => {
  const destination = options.request.destination;
  const cache = await self.caches.open('offline-fallbacks');
  if (destination === 'document') {
    return (await cache.match('/offline.html')) || Response.error();
  }
  return Response.error();
});

Recetas

Varios patrones de enrutamiento y almacenamiento en caché, como las navegaciones de NetworkFirst y los resguardos sin conexión, son lo suficientemente comunes como para encapsularse en recetas reutilizables. Consulta las recetas de la caja de trabajo, ya que pueden ayudarte si proporcionan una solución adecuada para tu arquitectura. Suelen estar disponibles como una línea de código que debes agregar al código de tu service worker.

Almacenamiento en caché y actualización de activos

Almacenar recursos en caché también implica actualizarlos. Workbox ayuda a actualizar tus elementos de la manera que consideres más conveniente. Podría tratarse de mantenerlos actualizados si cambian en el servidor o esperar hasta que tengas una nueva versión de tu app. Obtén más información sobre este tema en el capítulo Actualizar.

Juega con Workbox

Puedes jugar con Workbox de inmediato mediante el siguiente codelab:

Recursos