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() de workbox-core ya no agregará un controlador install y equivale a solo llamar a self.skipWaiting().
A partir de ahora, usa self.skipWaiting(), ya que es probable que se quite skipWaiting() 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 es poco común. workbox-precachingahora ignora el parámetro de consulta de URLfbclidcuando busca una respuesta almacenada en caché previa para una solicitud determinada.- El constructor
PrecacheControllerahora 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 versión 5),plugins(que reemplaza el métodoaddPlugins()de la versión 5) yfallbackToNetwork(que reemplaza la opción similar que se pasó acreateHandler()y `createHandlerBoundToURL() en la versión 5). - Los métodos
install()yactivate()dePrecacheControllerahora toman exactamente un parámetro, que se debe establecer en unInstallEventoActivateEventcorrespondiente, respectivamente. - Se quitó el método
addRoute()dePrecacheController. En su lugar, se puede usar la nueva clasePrecacheRoutepara crear una ruta que luego puedes registrar. - Se quitó el método
precacheAndRoute()dePrecacheController. (Aún existe como un método auxiliar estático exportado por el móduloworkbox-precaching). Se quitó porque se puede usarPrecacheRouteen su lugar. - Se quitó el método
createMatchCalback()dePrecacheController. En su lugar, se puede usar el nuevoPrecacheRoute. - Se quitó el método
createHandler()dePrecacheController. En su lugar, se puede usar la propiedadstrategydel objetoPrecacheControllerpara controlar las solicitudes. - La exportación estática
createHandler()ya se quitó del móduloworkbox-precaching. En su lugar, los desarrolladores deben construir una instancia dePrecacheControllery usar su propiedadstrategy. - La ruta registrada con
precacheAndRoute()ahora es una ruta "real" que usa la claseRouterdeworkbox-routingde forma interna. Esto puede generar un orden de evaluación diferente de tus rutas si intercalas llamadas aregisterRoute()yprecacheAndRoute().
workbox-routing
El método setDefaultHandler() ahora toma un segundo parámetro opcional que corresponde al método HTTP al que se aplica, con el valor predeterminado 'GET'.
- Si usas
setDefaultHandler()y todas tus solicitudes sonGET, no es necesario que realices ningún cambio. - Si tienes solicitudes que no sean
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 se diseñó para 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 tengan la capacidad de extender Workbox de manera que satisfaga por completo sus necesidades.
Nueva clase base Strategy
En la versión 6, todas las clases de estrategia de Workbox deben extender la nueva clase base Strategy. Todas las estrategias integradas se reescribieron para admitir esta función.
La clase base Strategy es responsable de dos aspectos principales:
- Invocar devoluciones de llamada de ciclo de vida de complementos comunes a todos los controladores de estrategia (p. ej., cuando se inician, responden y finalizan)
- Crear una instancia de "controlador" que pueda administrar el estado de cada solicitud individual que maneja una estrategia
Nueva clase "handler"
Anteriormente, teníamos módulos internos que llamaban a 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 los complementos funcionen, pero no se expone a los desarrolladores.
La nueva clase "controladora", StrategyHandler, expondrá estos métodos para que las estrategias personalizadas puedan llamar a fetch() o cacheMatch(), y se invoquen automáticamente los complementos que se agregaron a la instancia de la estrategia.
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 de complemento existente.
Nuevo estado del ciclo de vida del complemento
En Workbox v5, los complementos no tienen estado. Esto significa que, si una solicitud de /index.html activa las devoluciones de llamada requestWillFetch y cachedResponseWillBeUsed, estas no tienen forma de comunicarse entre sí ni de saber que se activaron por la misma solicitud.
En la versión 6, 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 que los desarrolladores escriban complementos en los que una devolución de llamada pueda 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 la ejecución de 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 de los complementos para permitir que los desarrolladores aprovechen al máximo el estado del ciclo de vida de los complementos:
handlerWillStart: Se llama antes de que comience a ejecutarse cualquier lógica del controlador. Esta devolución de llamada se puede usar para establecer el estado inicial del controlador (p.ej., registrar la hora de inicio).handlerWillRespond: Se llama antes de que el métodohandle()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étodohandle()de la estrategia devuelve una respuesta. Esta devolución de llamada se puede usar para registrar cualquier detalle de la respuesta final, p.ej., después de los cambios realizados por otros complementos.handlerDidComplete: Se llama después de que se resuelven todas las promesas de extensión de la vida útil 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 de 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 "resguardo" 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 sí mismos, ya que todo eso lo controla una nueva clase base Strategy.
Tipos de TypeScript más precisos para los controladores
Se normalizaron las definiciones de TypeScript para varios métodos de devolución de llamada. Esto debería generar una mejor experiencia para los desarrolladores que usan TypeScript y escriben su propio código para implementar o llamar a controladores.
workbox-window
Nuevo método messageSkipWaiting()
Se agregó un método nuevo, messageSkipWaiting(), al módulo workbox-window para simplificar el proceso de indicarle al service worker "en espera" que se active. Esto ofrece algunas mejoras:
- Llama a
postMessage()con el cuerpo del mensaje estándar de facto,{type: 'SKIP_WAITING'}, que un service worker generado por Workbox verifica para activarskipWaiting(). - 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 y se reemplazaron por eventos "normales" con una propiedad isExternal establecida en true. Esto permite que los desarrolladores que se preocupan por la distinción la detecten, y que los desarrolladores que no necesitan saberlo puedan ignorar la propiedad.
Receta más limpia de "Ofrecer una recarga de página para los usuarios"
Gracias a los dos cambios anteriores, se puede simplificar la receta "Ofrece una recarga de página para los usuarios":
// v6:
<script type="module">
import {Workbox} from 'https://storage.googleapis.com/workbox-cdn/releases/6.0.0-alpha.1/workbox-window.prod.mjs';
if ('serviceWorker' in navigator) {
const wb = new Workbox('/sw.js');
const showSkipWaitingPrompt = () => {
// This assumes a hypothetical createUIPrompt() method with
// onAccept and onReject callbacks:
const prompt = createUIPrompt({
onAccept: () => {
wb.addEventListener('controlling', () => {
window.location.reload();
});
// This will postMessage() to the waiting service worker.
wb.messageSkipWaiting();
},
onReject: () => {
prompt.dismiss();
},
});
};
// Listening for externalwaiting is no longer needed.
wb.addEventListener('waiting', showSkipWaitingPrompt);
wb.register();
}
</script>
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 y, de lo contrario, en falso.
Esto simplifica algunas plantillas comunes:
// In v5:
registerRoute(
({url}) =>
url.origin === self.location.origin && url.pathname.endsWith('.png'),
new StaleWhileRevalidate({cacheName: 'local-png'})
);
// In v6:
registerRoute(
({sameOrigin, url}) => sameOrigin && url.pathname.endsWith('.png'),
new StaleWhileRevalidate({cacheName: 'local-png'})
);
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 reescribió workbox-precaching para usar workbox-strategies como base. Esto no debería generar cambios rotundos 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 previo en caché ahora procesa las entradas una por una, no de forma masiva
Se actualizó workbox-precaching para que solo se solicite y almacene en caché una entrada en el manifiesto de almacenamiento previo en caché a la vez, en lugar de intentar solicitarlas y almacenarlas en caché todas a la vez (dejando que el navegador determine cómo limitar).
Esto debería reducir la probabilidad de que se produzcan errores net::ERR_INSUFFICIENT_RESOURCES durante el almacenamiento previo en caché y también debería reducir la contención de ancho de banda entre el almacenamiento previo en caché y las solicitudes simultáneas que realiza la app web.
PrecacheFallbackPlugin permite un resguardo sin conexión más sencillo
workbox-precaching ahora incluye un PrecacheFallbackPlugin, que implementa el nuevo método de ciclo de vida handlerDidError agregado en la versión 6.
Esto facilita la especificación de una URL almacenada en caché previa como "resguardo" para una estrategia determinada cuando, de lo contrario, no habría una respuesta disponible. El complemento se encargará de construir correctamente la clave de caché correcta para la URL almacenada en caché previa, 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é previa cuando la estrategia NetworkOnly no puede generar una respuesta para una solicitud de navegación; en otras palabras, mostrar una página HTML personalizada sin conexión:
import {PrecacheFallbackPlugin, precacheAndRoute} from 'workbox-precaching';
import {registerRoute} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';
// Ensure that /offline.html is part of your precache manifest!
precacheAndRoute(self.__WB_MANIFEST);
registerRoute(
({request}) => request.mode === 'navigate',
new NetworkOnly({
plugins: [
new PrecacheFallbackPlugin({
fallbackURL: '/offline.html',
}),
],
})
);
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.