Cómo usar workbox-window

Un módulo de Workbox que aún no se ha cubierto mucho en esta documentación es workbox-window, que es un conjunto de módulos diseñados para ejecutarse en window. Los objetivos de este módulo son los siguientes:

  • Para simplificar el registro y las actualizaciones de los service workers, se ayuda a los desarrolladores a identificar los momentos críticos del ciclo de vida de los service workers y se facilita la respuesta en esos momentos.
  • Para evitar que los desarrolladores cometan errores comunes, como registrar un trabajador de servicio en el alcance incorrecto.
  • Para simplificar los mensajes entre window y el alcance del trabajador de servicio.

Importa y usa workbox-window

La exportación que usarás con mayor frecuencia desde workbox-window es la clase Workbox, que puedes importar en Node o desde la CDN en una página web.

Crea un paquete local

Si tu cadena de herramientas incluye un agrupador como webpack o Rollup, puedes empaquetar workbox-window de forma local.

Primero, instala workbox-window como una dependencia de producción de tu aplicación:

npm install workbox-window --save

Luego, en el código JavaScript de tu aplicación, puedes import la clase Workbox desde workbox-window:

<script type="module">
import {Workbox} from 'workbox-window';

if ('serviceWorker' in navigator) {
  const wb = new Workbox('/sw.js');

  wb.register();
}
</script>

Aunque workbox-window es bastante pequeño, podrías separarlo de la lógica de la aplicación principal de tu sitio web con import dinámico, lo que puede reducir el tamaño del paquete principal de tu página:

<script type="module">
if ('serviceWorker' in navigator) {
  const {Workbox} = await import('workbox-window');

  const wb = new Workbox('/sw.js');
  wb.register();
}
</script>

Usa la CDN

Si bien no es el enfoque recomendado, una manera más fácil de usar workbox-window es importarlo desde una CDN:

<script type="module">
  import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/6.2.0/workbox-window.prod.mjs';

  if ('serviceWorker' in navigator) {
    const wb = new Workbox('/sw.js');

    wb.register();
  }
</script>

Notarás que el elemento <script> en el ejemplo anterior usa el atributo type="module". Esto es obligatorio si deseas usar sentencias import estáticas en el navegador sin un paso de compilación. Todos los navegadores principales que admiten service workers también admiten módulos de JavaScript, por lo que puedes entregar este código a cualquier navegador, ya que los navegadores más antiguos ignorarán los elementos <script> con un valor de atributo type de "module".

Registra un service worker

El registro de un service worker con workbox-window se realiza con el método register de la clase Workbox de la siguiente manera:

import {Workbox} from 'workbox-window';

const wb = new Workbox('/sw.js');
wb.register();

Puede parecer que esto es lo mismo que registrar un service worker tú mismo con navigator.serviceWorker.register. Sin embargo, Workbox.register se encarga de esperar hasta el evento window load antes de registrar el service worker. Esto es conveniente en situaciones en las que se usa el almacenamiento en caché previo para evitar la contención de ancho de banda que puede retrasar el inicio de la página.

Comunicación entre window y el alcance del trabajador de servicio

Los trabajadores de servicio tienen su propio alcance, independiente de window, y solo tienen acceso a un subconjunto de las APIs disponibles en window. Sin embargo, es posible comunicarse entre window y el trabajador de servicio. workbox-window permite una comunicación más sencilla entre los dos alcances con el método messageSW del módulo workbox-window.

Workbox usa un formato específico para los mensajes, que es un objeto con las siguientes propiedades:

  • type es una cadena única obligatoria que identifica el mensaje. El formato debe estar en mayúsculas y tener guiones bajos para separar las palabras (por ejemplo, CACHE_URLS).
  • meta es una cadena opcional que representa el nombre del paquete de Workbox que envía el mensaje y, por lo general, se omite.
  • payload es un parámetro opcional que representa los datos que deseas enviar. Puede ser de cualquier tipo.

A continuación, se muestra un ejemplo de cómo funciona messageSW, comenzando por el código del service worker:

// sw.js
const SW_VERSION = '1.0.0';

self.addEventListener('message', (event) => {
  if (event.data.type === 'GET_VERSION') {
    event.ports[0].postMessage(SW_VERSION);
  }
});

Y, luego, el siguiente código en tu página web:

const wb = new Workbox('/sw.js');
wb.register();

const swVersion = await wb.messageSW({type: 'GET_VERSION'});
console.log('Service Worker version:', swVersion);

Hay muchos casos en los que puede ser útil la comunicación entre un trabajador de servicio y window, como notificar al usuario cuando hay una actualización de trabajador de servicio disponible. Esa receta se basa en un método de ayuda especial para self.skipWaiting llamado messageSkipWaiting, que envía un mensaje con un valor type de SKIP_WAITING.