Cómo quitar service workers con errores

A veces, un service worker con errores se implementa y, después, puede haber problemas. Por ejemplo, se puede analizar un service worker en el momento del registro y completar la instalación correctamente. Sin embargo, el código con errores en un evento fetch puede provocar que no responda a las solicitudes, lo que genera una página en blanco. Otra posibilidad es que el lenguaje de marcado de la página se almacene en caché de forma agresiva y un service worker solo muestre respuestas de lenguaje de marcado inactivo de una instancia de Cache para visitas posteriores.

Hay muchas maneras en que un service worker puede tener un contratiempo, y eso es un problema aterrador en un sitio web de producción. Aun así, no todo está perdido. Existen formas de solucionar la situación y retomarla.

Implementa un service worker no-op

Por lo general, solo se necesita implementar un service worker no-op básico que se instale y active de inmediato sin un controlador de eventos fetch:

// sw.js

self.addEventListener('install', () => {
  // Skip over the "waiting" lifecycle state, to ensure that our
  // new service worker is activated immediately, even if there's
  // another tab open controlled by our older service worker code.
  self.skipWaiting();
});

self.addEventListener('activate', () => {
  // Optional: Get a list of all the current open windows/tabs under
  // our service worker's control, and force them to reload.
  // This can "unbreak" any open windows/tabs as soon as the new
  // service worker activates, rather than users having to manually reload.
  self.clients.matchAll({
    type: 'window'
  }).then(windowClients => {
    windowClients.forEach((windowClient) => {
      windowClient.navigate(windowClient.url);
    });
  });
});

Este service worker se instalará y activará de inmediato llamando a self.skipWaiting() en el evento install. De manera opcional, se puede implementar código adicional en el evento activate para volver a cargar de manera forzosa cualquier otra pestaña abierta con un WindowClient que el service worker esté controlando.

Es muy importante que un service worker no-op no contenga un controlador de eventos fetch. Cuando un service worker no controla solicitudes, estas pasan al navegador como si no hubiera ningún service worker presente. Una vez que se implementa un service worker no-op, el service worker con errores se puede corregir y, luego, se puede implementar como una actualización más adelante.

Este enfoque funciona en parte porque los navegadores tienen protecciones sólidas contra la ubicación de service workers en la caché HTTP y porque realizan comprobaciones byte por byte del contenido de un service worker en busca de actualizaciones. Estos valores predeterminados permiten implementar un reemplazo no-op para un service worker con errores para solucionar el problema rápidamente.

Medidas adicionales que puedes tomar

La implementación de un service worker no operativo debería ser suficiente para neutralizar uno con errores, pero se pueden tomar medidas adicionales si es necesario.

¿Qué sucede si no conoces la URL del service worker anterior?

A veces, se desconoce la URL de un service worker instalado previamente. Esto puede deberse a que tiene versiones (por ejemplo, contiene un hash en el nombre de archivo). En este caso, implementar un service worker no-op puede resultar complicado que coincida con la URL de cada service worker antiguo que se haya registrado. Esto infringe las prácticas recomendadas, ya que es probable que los desarrolladores no recuerden todos los hashes de cada versión de service worker que se implementó.

Afortunadamente, se envía un encabezado de solicitud HTTP útil con la solicitud de una secuencia de comandos del service worker: Service-Worker. En el servidor web, busca este encabezado y, luego, intercepta la solicitud para entregar un service worker no-op en su lugar. Para lograr esto, dependerá del servidor web y de la pila de backend que se usen. Por lo tanto, consulta la documentación del lenguaje relevante sobre cómo hacerlo.

En cuanto a las futuras implementaciones de service workers, conserva los nombres de los elementos sin versiones (por ejemplo, sw.js). Esto hará que todo sea mucho menos complicado más adelante.

Establece un encabezado Clear-Site-Data

Algunos navegadores cancelarán el registro de todos los service worker para un origen si se establece un encabezado de respuesta Clear-Site-Data con un valor de 'storage'. Sin embargo, debes tener en cuenta los siguientes aspectos con respecto a este enfoque:

Dado que la compatibilidad con este encabezado no es total, no se puede confiar en él solo para solucionar el problema. Por lo tanto, es mejor ver Clear-Site-Data como una medida además de implementar un service worker no-op.

El daño no es permanente

Puede ser aterrador cuando un service worker con errores interrumpe la experiencia del usuario, especialmente para sitios web grandes y conocidos, pero el daño es temporal y reversible.

Si es necesario implementar un service worker no-op para solucionar la situación, tómate un tiempo después del hecho para descubrir exactamente qué salió mal. En el futuro, asegúrate de que un service worker controle solo las solicitudes que se espera que haga. Realiza pruebas con frecuencia en la etapa de pruebas y solo implementa actualizaciones cuando tengas confianza.