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
- Ya no se pueden usar documentos HTML de origen cruzado para las URLs que corresponden a un redireccionamiento HTTP para satisfacer una solicitud de navegación con
workbox-precaching
. Por lo general, esta situación no es común. workbox-precaching
ahora ignora el parámetro de consulta de URLfbclid
cuando busca una respuesta almacenada en caché 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
(cumple el mismo propósito que la cadena que se pasó al constructor en la v5),plugins
(reemplaza el métodoaddPlugins()
de la v5) yfallbackToNetwork
(reemplaza la opción similar que se pasó acreateHandler()
y "createHandlerBoundToURL() en la v5). - Los métodos
install()
yactivate()
dePrecacheController
ahora toman exactamente un parámetro, que debe establecerse en unInstallEvent
oActivateEvent
correspondiente, respectivamente. - Se quitó el método
addRoute()
dePrecacheController
. En su lugar, la nueva clasePrecacheRoute
se puede usar para crear una ruta que luego puedes registrar. - Se quitó el método
precacheAndRoute()
dePrecacheController
. (Aún existe como un método de ayuda estático que exporta el móduloworkbox-precaching
). Se quitó porque se puede usarPrecacheRoute
en 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 propiedadstrategy
del objetoPrecacheController
para controlar las solicitudes. - La exportación estática de
createHandler()
ya se quitó del móduloworkbox-precaching
. En su lugar, los desarrolladores deben crear una instancia dePrecacheController
y usar su propiedadstrategy
. - La ruta registrada con
precacheAndRoute()
ahora es una ruta "real" que usa la claseRouter
deworkbox-routing
de 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, y el valor predeterminado es 'GET'
.
- Si usas
setDefaultHandler()
y todas tus solicitudes sonGET
, 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 versiones posteriores
Las versiones anteriores a la 10 de Node.js 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 versión 6, todas las clases de estrategias 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 controla una estrategia
Nueva clase "controlador"
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 los complementos funcionen, pero no se expone a los desarrolladores.
La nueva clase "controlador", StrategyHandler
, expondrá estos métodos para que las estrategias personalizadas puedan llamar a fetch()
o cacheMatch()
y hacer que 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 personalizadas de ciclo de vida que podrían ser específicas de sus estrategias y que “solo funcionen” con la interfaz de 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 versión 6, a todas las devoluciones de llamada de complementos también se les pasará 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 usar para establecer el estado del controlador inicial (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 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 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 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, ya que todo 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 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 decirle al trabajador en segundo plano"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 activarskipWaiting()
. - Elige el service worker "en espera" correcto para publicar este mensaje, incluso si no es el mismo 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 "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 en false de lo contrario.
Esto simplifica algunos textos 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 hacerlo).
workbox-precaching
Usa workbox-strategies
Se reescribió 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 handlerDidError
agregado 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:
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 trabajador de servicio en lugar de escribirlo a mano, 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 sean sencillas. Si tienes problemas que no se abordan en esta guía, abre un problema en GitHub para informarnos al respecto.