Cómo migrar de Workbox v5 a v6

Esta guía se enfoca en los cambios rotundos que se introdujeron en Workbox v6, con ejemplos de los cambios que deberías realizar cuando actualices desde Workbox v5.

Cambios rotundos

workbox-core

El método skipWaiting() en workbox-core ya no agregará un controlador install y equivale a llamar a self.skipWaiting().

A partir de ahora, usa self.skipWaiting(), ya que es probable que skipWaiting() se quite en Workbox v7.

workbox-precaching

  • Los documentos HTML de origen cruzado para las URLs que corresponden a un redireccionamiento HTTP ya no se pueden usar para satisfacer una solicitud de navegación con workbox-precaching. Por lo general, esta situación no es común.
  • Ahora workbox-precaching ignora el parámetro de consulta de URL fbclid cuando busca una respuesta almacenada en caché previamente para una solicitud determinada.
  • El constructor PrecacheController ahora toma un objeto con propiedades específicas como parámetro, en lugar de una cadena. Este objeto admite las siguientes propiedades: cacheName (que tiene el mismo propósito que la cadena que se pasó al constructor en la v5), plugins (reemplaza el método addPlugins() de la v5) y fallbackToNetwork (reemplaza la opción similar que se pasó a createHandler() y `createHandlerBoundToURL() en la v5).
  • Los métodos install() y activate() de PrecacheController ahora toman exactamente un parámetro, que se debe establecer en un InstallEvent o ActivateEvent correspondientes, respectivamente.
  • Se quitó el método addRoute() de PrecacheController. En su lugar, se puede usar la nueva clase PrecacheRoute para crear una ruta que luego puedes registrar.
  • Se quitó el método precacheAndRoute() de PrecacheController. (Aún existe como un método de ayuda estático que exporta el módulo workbox-precaching). Se quitó porque se puede usar PrecacheRoute en su lugar.
  • Se quitó el método createMatchCalback() de PrecacheController. En su lugar, se puede usar el nuevo PrecacheRoute.
  • Se quitó el método createHandler() de PrecacheController. En su lugar, se puede usar la propiedad strategy del objeto PrecacheController para controlar las solicitudes.
  • La exportación estática createHandler() ya se quitó del módulo workbox-precaching. En su lugar, los desarrolladores deben crear una instancia de PrecacheController y usar su propiedad strategy.
  • La ruta registrada con precacheAndRoute() ahora es una ruta "real" que usa la clase Router de workbox-routing de forma interna. Esto puede generar un orden de evaluación diferente de tus rutas si intercalas llamadas a registerRoute() y precacheAndRoute().

workbox-routing

El método setDefaultHandler() ahora toma un segundo parámetro opcional que corresponde al método HTTP al que se aplica, y el valor predeterminado es 'GET'.

  • Si usas setDefaultHandler() y todas tus solicitudes son GET, no es necesario realizar ningún cambio.
  • Si tienes alguna solicitud que no sea GET (POST, PUT, etcétera), setDefaultHandler() ya no hará que esas solicitudes coincidan.

Configuración de compilación

La opción mode para los modos getManifest y injectManifest en workbox-build y workbox-cli no estaba destinada a ser compatible y se quitó. Esto no se aplica a workbox-webpack-plugin, que sí admite mode en su complemento InjectManifest.

Las herramientas de compilación requieren Node.js v10 o una versión posterior

Las versiones de Node.js anteriores a la v10 ya no son compatibles con workbox-webpack-plugin, workbox-build ni workbox-cli. Si ejecutas una versión de Node.js anterior a la v8, actualiza el entorno de ejecución a una versión compatible.

Nuevas mejoras

workbox-strategies

Workbox v6 presenta una nueva forma para que los desarrolladores externos definan sus propias estrategias de Workbox. Esto garantiza que los desarrolladores externos puedan extender Workbox de manera que satisfaga todas sus necesidades.

Nueva clase base de estrategia

En la v6, todas las clases de estrategia de Workbox deben extender la nueva clase base Strategy. Todas las estrategias integradas se reescribieron para admitir esto.

La clase base Strategy es responsable de dos aspectos principales:

  • Invocar devoluciones de llamada de ciclo de vida del complemento comunes a todos los controladores de estrategias (p. ej., cuando se inician, responden y terminan)
  • Crear una instancia de "controlador", que pueda administrar el estado de cada solicitud individual que controle una estrategia

Nueva clase "handler"

Anteriormente, teníamos módulos internos llamados fetchWrapper y cacheWrapper, que (como su nombre lo indica) unen las diversas APIs de recuperación y almacenamiento en caché con hooks en su ciclo de vida. Este es el mecanismo que actualmente permite que funcionen los complementos, pero no se expone a los desarrolladores.

La nueva clase de "controlador", StrategyHandler, expondrá estos métodos para que las estrategias personalizadas puedan llamar a fetch() o cacheMatch() y tendrán los complementos que se agregaron a la instancia de estrategia invocados automáticamente.

Esta clase también permitiría que los desarrolladores agreguen sus propias devoluciones de llamada de ciclo de vida personalizadas que podrían ser específicas de sus estrategias, y “simplemente funcionarían” con la interfaz del complemento existente.

Nuevo estado del ciclo de vida del complemento

En Workbox v5, los complementos no tienen estado. Eso significa que, si una solicitud de /index.html activa las devoluciones de llamada de requestWillFetch y cachedResponseWillBeUsed, esas dos devoluciones de llamada no tienen forma de comunicarse entre sí ni siquiera de saber que fueron activadas por la misma solicitud.

En la v6, todas las devoluciones de llamada de complementos también recibirán un nuevo objeto state. Este objeto de estado será único para este objeto de complemento en particular y esta invocación de estrategia en particular (es decir, la llamada a handle()). Esto permite a los desarrolladores escribir complementos en los que una devolución de llamada puede hacer algo de forma condicional en función de lo que hizo otra devolución de llamada en el mismo complemento (p. ej., calcular la diferencia de tiempo entre ejecutar requestWillFetch y fetchDidSucceed o fetchDidFail).

Nuevas devoluciones de llamada del ciclo de vida del complemento

Se agregaron nuevas devoluciones de llamada del ciclo de vida del complemento para permitir que los desarrolladores aprovechen por completo el estado del ciclo de vida del complemento:

  • handlerWillStart: Se llama antes de que comience a ejecutarse cualquier lógica del controlador. Esta devolución de llamada se puede utilizar para establecer el estado inicial del controlador (p.ej., registrar la hora de inicio).
  • handlerWillRespond: Se llama antes de que el método handle() de las estrategias devuelva una respuesta. Esta devolución de llamada se puede usar para modificar esa respuesta antes de devolverla a un controlador de ruta o a otra lógica personalizada.
  • handlerDidRespond: Se llama después de que el método handle() de la estrategia muestra una respuesta. Esta devolución de llamada se puede usar para registrar los detalles de la respuesta final, p.ej., después de los cambios que realicen otros complementos.
  • handlerDidComplete: Se llama después de que se liquidan todas las promesas de extender el ciclo de vida agregadas al evento desde la invocación de esta estrategia. Esta devolución de llamada se puede usar para informar sobre cualquier dato que deba esperar hasta que el controlador termine para calcular (p.ej., el estado de acierto de caché, la latencia de caché o la latencia de red).
  • handlerDidError: Se llama si el controlador no pudo proporcionar una respuesta válida de ninguna fuente. Esta devolución de llamada se puede usar para proporcionar contenido de "reemplazo" como alternativa a un error de red.

Los desarrolladores que implementan sus propias estrategias personalizadas no tienen que preocuparse por invocar estas devoluciones de llamada por su cuenta. Todo eso se controla mediante una nueva clase base Strategy.

Tipos de TypeScript más precisos para controladores

Se normalizaron las definiciones de TypeScript para varios métodos de devolución de llamada. Esto debería mejorar la experiencia de los desarrolladores que usan TypeScript y escriben su propio código para implementar o llamar controladores.

ventana-de-trabajo-de-trabajo

Nuevo método messageSkipWaiting()

Se agregó un método nuevo, messageSkipWaiting(), al módulo workbox-window para simplificar el proceso de decirle al service worker"en espera" que se active. Esto ofrece algunas mejoras:

  • Llama a postMessage() con el cuerpo de mensaje estándar de facto, {type: 'SKIP_WAITING'}, que un trabajador de servicio generado por Workbox busca para activar skipWaiting().
  • Elige el service worker "en espera" correcto para publicar este mensaje, incluso si no es el mismo service worker con el que se registró workbox-window.

Se quitaron los eventos "externos" en favor de una propiedad isExternal.

Se quitaron todos los eventos "externos" de workbox-window en lugar de los eventos "normales" con una propiedad isExternal establecida en true. Esto permite que los desarrolladores que se preocupan por la distinción la detecten, y los desarrolladores que no necesitan saberlo pueden ignorar la propiedad.

Receta más clara para "Ofrecer una recarga de página para los usuarios"

Gracias a ambos cambios anteriores, se puede simplificar la receta "Ofrecer una recarga de página para los usuarios":

MULTI_LINE_CODE_PLACEHOLDER_0

workbox-routing

Se pasa un nuevo parámetro booleano, sameOrigin, a la función matchCallback que se usa en workbox-routing. Se establece en true si la solicitud es para una URL del mismo origen. De lo contrario, se establece en falso.

Esto simplifica un código estándar común:

MULTI_LINE_CODE_PLACEHOLDER_1

matchOptions en workbox-expiration

Ahora puedes configurar matchOptions en workbox-expiration, que luego se pasará como CacheQueryOptions a la llamada cache.delete() subyacente. (La mayoría de los desarrolladores no necesitarán hacer esto).

workbox-precaching

Usa workbox-strategies

Se volvió a escribir workbox-precaching para usar workbox-strategies como base. Esto no debería generar cambios drásticos y debería generar una mejor coherencia a largo plazo en la forma en que los dos módulos acceden a la red y a la caché.

El almacenamiento en caché previo ahora procesa las entradas de una en una, no de forma masiva.

Se actualizó workbox-precaching para que solo se solicite y almacene en caché una entrada del manifiesto de almacenamiento en caché a la vez, en lugar de intentar solicitarlas y almacenarlas en caché todas a la vez (lo que le permite al navegador determinar cómo reducir la velocidad).

Esto debería reducir la probabilidad de errores de net::ERR_INSUFFICIENT_RESOURCES durante la precaché y también debería reducir la contención de ancho de banda entre la precaché y las solicitudes simultáneas que realiza la app web.

PrecacheFallbackPlugin permite un resguardo sin conexión más fácil.

workbox-precaching ahora incluye un PrecacheFallbackPlugin, que implementa el nuevo método de ciclo de vida de handlerDidError que se agregó en la versión 6.

Esto facilita la especificación de una URL almacenada en caché como "alternativa" para una estrategia determinada cuando, de otro modo, no habría una respuesta disponible. El complemento se encargará de construir correctamente la clave de caché correcta para la URL almacenada en caché previamente, incluido cualquier parámetro de revisión que sea necesario.

A continuación, se muestra un ejemplo de cómo usarlo para responder con un /offline.html almacenado en caché cuando la estrategia de NetworkOnly no puede generar una respuesta para una solicitud de navegación; en otras palabras, muestra una página HTML sin conexión personalizada:

MULTI_LINE_CODE_PLACEHOLDER_2

precacheFallback en el almacenamiento en caché del entorno de ejecución

Si usas generateSW para crear un service worker en lugar de escribirlo manualmente, puedes usar la nueva opción de configuración precacheFallback en runtimeCaching para lograr lo mismo:

{
  // ... other generateSW config options...
  runtimeCaching: [{
    urlPattern: ({request}) => request.mode === 'navigate',
    handler: 'NetworkOnly',
    options: {
      precacheFallback: {
        // This URL needs to be included in your precache manifest.
        fallbackURL: '/offline.html',
      },
    },
  }],
}

Cómo obtener ayuda

Prevemos que la mayoría de las migraciones serán sencillas. Si tienes problemas que no se abordan en esta guía, abre un problema en GitHub para informarnos al respecto.