Cómo usar workbox-window

Un módulo de Workbox que todavía no recibió mucha cobertura en esta documentación es workbox-window, que es un conjunto de módulos destinados a ejecutarse en window. Estos son los objetivos de este módulo:

  • Ayudar a los desarrolladores a identificar momentos críticos del ciclo de vida del service worker para simplificar el registro y las actualizaciones de los service workers, lo que facilita responder en esos momentos.
  • Para evitar que los desarrolladores cometan errores comunes, como registrar un service worker en el alcance equivocado
  • Para simplificar la mensajería entre window y el permiso de service worker.

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.

Cómo crear un paquete local

Si tu cadena de herramientas incluye un agrupador como webpack o Rollup, puedes agrupar 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>

Si bien workbox-window es bastante pequeño, podrías dividirlo de la lógica principal de la aplicación de tu sitio web con un import dinámico, 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>

Ten en cuenta que el elemento <script> del ejemplo anterior usa el atributo type="module". Esto es necesario si deseas usar instrucciones 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 se puede 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 equivale a registrar un service worker usando 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 previo en caché para evitar la contención del ancho de banda que puede retrasar el inicio de la página.

Comunicación entre el window y el alcance del service worker

Los service workers tienen su propio alcance independiente de window y solo tienen acceso a un subconjunto de las APIs disponibles en window. Sin embargo, es posible la comunicación entre window y el service worker. 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 es un objeto con las siguientes propiedades:

  • type es una cadena única obligatoria que identifica el mensaje. El formato debe estar en mayúsculas con guiones bajos que separen 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 cualquier tipo de datos.

A continuación, se muestra un ejemplo de cómo funciona messageSW, comenzando por el código de tu 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);
  }
});

Luego, verás 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);

Existen muchas instancias en las que la comunicación entre un service worker y el window puede ser útil, como notificar al usuario cuando hay una actualización de service worker disponible. Esa receta se basa en un método auxiliar especial para self.skipWaiting llamado messageSkipWaiting, que envía un mensaje con un valor type de SKIP_WAITING.