Resumen
A partir de Chrome 68, la caché HTTP ya no entregará de forma predeterminada las solicitudes HTTP que buscan actualizaciones de la secuencia de comandos del servicio trabajador. Esto soluciona un problema común de los desarrolladores, en el que configurar un encabezado Cache-Control
imprevisto en la secuencia de comandos del servicio de trabajo podría provocar actualizaciones demoradas.
Si ya inhabilitaste la caché HTTP para tu secuencia de comandos /service-worker.js
publicándola con Cache-Control: max-age=0
, no deberías ver ningún cambio debido al nuevo comportamiento predeterminado.
Además, a partir de Chrome 78, la comparación byte por byte se aplicará a las secuencias de comandos cargadas en un service worker a través de importScripts()
.
Cualquier cambio que se realice en una secuencia de comandos importada activará el flujo de actualización del servicio de trabajo, al igual que lo haría un cambio en el servicio de trabajo de nivel superior.
Segundo plano
Cada vez que navegas a una página nueva que está bajo el alcance de un service worker, llama de forma explícita a registration.update()
desde JavaScript o, cuando un service worker se "activa" a través de un evento push
o sync
, el navegador, en paralelo, solicitará el recurso de JavaScript que se pasó originalmente a la llamada navigator.serviceWorker.register()
para buscar actualizaciones en la secuencia de comandos del service worker.
A los efectos de este artículo, supongamos que su URL es /service-worker.js
y que contiene una sola llamada a importScripts()
, que carga código adicional que se ejecuta dentro del trabajador de servicio:
// Inside our /service-worker.js file:
importScripts('path/to/import.js');
// Other top-level code goes here.
¿Cuáles son los cambios?
Antes de Chrome 68, la solicitud de actualización de /service-worker.js
se realizaba a través de la caché HTTP (como la mayoría de las recuperaciones). Esto significaba que, si la secuencia de comandos se enviaba originalmente con Cache-Control:
max-age=600
, las actualizaciones en los próximos 600 segundos (10 minutos) no se enviarían a la red, por lo que es posible que el usuario no reciba la versión más actualizada del trabajador del servicio. Sin embargo, si max-age
fuera mayor que 86400 (24 horas), se trataría como si fuera 86400 para evitar que los usuarios se queden con una versión en particular para siempre.
A partir de la versión 68, se ignorará la caché HTTP cuando se soliciten actualizaciones de la secuencia de comandos del trabajador de servicio, por lo que es posible que las aplicaciones web existentes vean un aumento en la frecuencia de las solicitudes de su secuencia de comandos del trabajador de servicio. Las solicitudes de importScripts
seguirán pasando por la caché HTTP. Sin embargo, esta es solo la opción predeterminada. Hay disponible una nueva opción de registro, updateViaCache
, que ofrece control sobre este comportamiento.
updateViaCache
Los desarrolladores ahora pueden pasar una opción nueva cuando llaman a navigator.serviceWorker.register()
: el parámetro updateViaCache
.
Toma uno de los tres valores: 'imports'
, 'all'
o 'none'
.
Los valores determinan si la caché HTTP estándar del navegador entra en juego y cómo cuando se realiza la solicitud HTTP para verificar si hay recursos de trabajador de servicio actualizados.
Cuando se establece en
'imports'
, la caché HTTP nunca se consultará cuando se verifiquen actualizaciones de la secuencia de comandos/service-worker.js
, pero se consultará cuando se recuperen secuencias de comandos importadas (path/to/import.js
, en nuestro ejemplo). Esta es la opción predeterminada y coincide con el comportamiento a partir de Chrome 68.Cuando se establece en
'all'
, se consultará la caché HTTP cuando se realicen solicitudes para la secuencia de comandos/service-worker.js
de nivel superior, así como para cualquier secuencia de comandos importada dentro del trabajador de servicio, comopath/to/import.js
. Esta opción corresponde al comportamiento anterior de Chrome, antes de Chrome 68.Cuando se establece en
'none'
, no se consultará la caché HTTP cuando se realicen solicitudes para el/service-worker.js
de nivel superior ni para las secuencias de comandos importadas, como lapath/to/import.js
hipotética.
Por ejemplo, el siguiente código registrará un trabajador de servicio y se asegurará de que nunca se consulte la caché HTTP cuando se verifiquen actualizaciones de la secuencia de comandos /service-worker.js
o de cualquier secuencia de comandos a la que se haga referencia a través de importScripts()
dentro de /service-worker.js
:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js', {
updateViaCache: 'none',
// Optionally, set 'scope' here, if needed.
});
}
Busca actualizaciones de las secuencias de comandos importadas.
Antes de Chrome 78, cualquier secuencia de comandos de servicio trabajador cargada a través de importScripts()
se recuperaba solo una vez (se verificaba primero en la caché de HTTP o a través de la red, según la configuración de updateViaCache
). Después de esa recuperación inicial, el navegador la almacenaría de forma interna y nunca la volvería a recuperar.
La única forma de forzar a un trabajador del servicio ya instalado a detectar cambios en una secuencia de comandos importada era cambiar la URL de la secuencia de comandos, por lo general, agregando un valor de semver (p.ej., importScripts('https://example.com/v1.1.0/index.js')
) o incluyendo un hash del contenido (p.ej., importScripts('https://example.com/index.abcd1234.js')
). Un efecto secundario de cambiar la URL importada es que cambia el contenido de la secuencia de comandos del trabajador del servicio de nivel superior, lo que, a su vez, activa el flujo de actualización del trabajador del servicio.
A partir de Chrome 78, cada vez que se realice una verificación de actualización para un archivo de trabajador de servicio de nivel superior, se realizarán verificaciones al mismo tiempo para determinar si cambió el contenido de alguna secuencia de comandos importada. Según los
encabezados Cache-Control
que se usen, la caché HTTP podría completar estas verificaciones de secuencias de comandos importadas si updateViaCache
se establece en 'all'
o 'imports'
(que es
el valor predeterminado), o las verificaciones podrían ir directamente a la red si
updateViaCache
se establece en 'none'
.
Si una verificación de actualización de una secuencia de comandos importada genera una diferencia de byte a byte en comparación con lo que el servicio trabajador almacenó anteriormente, esto a su vez activará el flujo de actualización completo del servicio trabajador, incluso si el archivo del servicio trabajador de nivel superior sigue siendo el mismo.
El comportamiento de Chrome 78 coincide con lo que Firefox implementó hace varios años, en Firefox 56. Safari ya implementa este comportamiento.
¿Qué deben hacer los desarrolladores?
Si inhabilitaste de forma efectiva la caché HTTP para tu secuencia de comandos /service-worker.js
publicándola con Cache-Control: max-age=0
(o un valor similar), no deberías ver ningún cambio debido al nuevo comportamiento predeterminado.
Si publicas tu secuencia de comandos /service-worker.js
con el almacenamiento en caché HTTP habilitado, ya sea de forma intencional o porque es la configuración predeterminada de tu entorno de alojamiento, es posible que comiences a ver un aumento en la cantidad de solicitudes HTTP adicionales para /service-worker.js
que se realizan a tu servidor. Estas son solicitudes que solía entregar la caché HTTP. Si deseas seguir permitiendo que el valor del encabezado Cache-Control
influya en la actualización de tu /service-worker.js
, deberás comenzar a configurar updateViaCache: 'all'
de forma explícita cuando registres tu trabajador de servicio.
Dado que puede haber un grupo de usuarios de cola larga en versiones anteriores de navegadores, sigue siendo una buena idea seguir configurando el encabezado HTTP Cache-Control: max-age=0
en las secuencias de comandos de los trabajadores del servicio, aunque los navegadores más nuevos puedan ignorarlos.
Los desarrolladores pueden aprovechar esta oportunidad para decidir si quieren inhabilitar de forma explícita las secuencias de comandos importadas del almacenamiento en caché de HTTP ahora y agregar updateViaCache: 'none'
a su registro de trabajador de servicio si corresponde.
Publicación de secuencias de comandos importadas
A partir de Chrome 78, es posible que los desarrolladores vean más solicitudes HTTP entrantes para los recursos cargados a través de importScripts()
, ya que ahora se verificarán si hay actualizaciones.
Si deseas evitar este tráfico HTTP adicional, configura encabezados Cache-Control
de larga duración cuando entregues secuencias de comandos que incluyan semver o hashes en sus URLs y confía en el comportamiento predeterminado de updateViaCache
de 'imports'
.
Como alternativa, si deseas que se verifiquen tus secuencias de comandos importadas en busca de actualizaciones frecuentes, asegúrate de publicarlas con Cache-Control: max-age=0
o de usar updateViaCache: 'none'
.
Lecturas adicionales
"El ciclo de vida del servicio de trabajador" y "Prácticas recomendadas de almacenamiento en caché y errores de tiempo de vida máximo", ambos de Jake Archibald, son lecturas recomendadas para todos los desarrolladores que implementan contenido en la Web.