Trabajadores de servicio más recientes, de forma predeterminada

tl;dr

A partir de Chrome 68, la caché HTTP ya no satisfará las solicitudes HTTP que verifican actualizaciones de la secuencia de comandos del service worker de forma predeterminada. Esto soluciona un problema común de desarrollador, en el que configurar un encabezado Cache-Control involuntario en la secuencia de comandos del service worker podría provocar que las actualizaciones se retrasen.

Si ya inhabilitaste el almacenamiento en caché HTTP para la secuencia de comandos de /service-worker.js mediante 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 realizado en una secuencia de comandos importada activará el flujo de actualización del service worker, al igual que lo haría un cambio en el service worker de nivel superior.

Información general

Cada vez que navegues a una nueva página que esté dentro del alcance de un service worker, llama de manera explícita a registration.update() desde JavaScript, o bien, cuando se "active" a un service worker mediante un evento push o sync, el navegador solicitará, en paralelo, el recurso de JavaScript que se pasó originalmente a la llamada navigator.serviceWorker.register() para buscar actualizaciones de 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 service worker:

// 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 de los siguientes 600 segundos (10 minutos) no irán a la red, por lo que es posible que el usuario no reciba la versión más actualizada del service worker. Sin embargo, si max-age fuera superior a 86,400 (24 horas), se tratará como si fuera 86,400 para evitar que los usuarios se queden atascados en una versión en particular para siempre.

A partir de 68, se ignorará la caché HTTP cuando se soliciten actualizaciones de la secuencia de comandos del service worker, por lo que es posible que las aplicaciones web existentes observen un aumento en la frecuencia de las solicitudes de su secuencia de comandos del service worker. Las solicitudes de importScripts se seguirán enviando a través de la caché HTTP. Sin embargo, esta es solo la configuración predeterminada: hay una nueva opción de registro disponible, 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 tres valores: 'imports', 'all' o 'none'.

Los valores determinan si la caché HTTP estándar del navegador entra en juego y de qué manera cuando se realiza la solicitud HTTP para verificar los recursos del service worker actualizados.

  • Cuando se establece en 'imports', nunca se consultará la caché HTTP cuando se verifiquen las actualizaciones de la secuencia de comandos /service-worker.js, pero se la consultará cuando se recuperen las secuencias de comandos importadas (en nuestro ejemplo, path/to/import.js). Este es el comportamiento predeterminado y coincide con el comportamiento a partir de Chrome 68.

  • Cuando se configura en 'all', se consultará la caché HTTP cuando se realicen solicitudes para la secuencia de comandos /service-worker.js de nivel superior y cualquier secuencia de comandos importada dentro del service worker, como path/to/import.js. Esta opción corresponde al comportamiento anterior en Chrome, anterior a Chrome 68.

  • Cuando se configura en 'none', no se consultará la caché HTTP cuando se realicen solicitudes para el /service-worker.js de nivel superior o para cualquier secuencia de comandos importada, como el path/to/import.js hipotético.

Por ejemplo, el siguiente código registrará un service worker y garantizará que nunca se consulte la caché HTTP cuando se verifiquen las actualizaciones de la secuencia de comandos de /service-worker.js ni de las secuencias de comandos a las 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 del service worker cargada a través de importScripts() se recuperaba solo una vez (comprobando primero en la caché HTTP o a través de la red, según la configuración updateViaCache). Después de esa recuperación inicial, el navegador lo almacenará de manera interna y nunca se volverá a recuperar.

La única forma de forzar a un service worker ya instalado para que detecte los cambios en una secuencia de comandos importada era cambiar la URL de la secuencia de comandos, por lo general, agregando un valor 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 el flujo de actualización de la secuencia de comandos del service worker de nivel superior activa el cambio de contenido.

A partir de Chrome 78, cada vez que se realiza una verificación de actualización de un archivo de service worker de nivel superior, se realizan verificaciones al mismo tiempo para determinar si cambió o no el contenido de las secuencias de comandos importadas. Según los encabezados Cache-Control que se usen, la caché HTTP podría llevar a cabo estas verificaciones de secuencia de comandos importadas si updateViaCache se configura como 'all' o 'imports' (que es el valor predeterminado), o bien las verificaciones pueden ir directamente en la red si updateViaCache se establece en 'none'.

Si una verificación de actualización de una secuencia de comandos importada genera una diferencia byte a byte en comparación con lo que antes almacenó el service worker, eso, a su vez, activará el flujo de actualización completo del service worker, incluso si el archivo del service worker 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 también.

¿Qué deben hacer los desarrolladores?

Si inhabilitaste el almacenamiento en caché HTTP para tu secuencia de comandos de /service-worker.js de manera efectiva mediante la entrega con Cache-Control: max-age=0 (o un valor similar), no deberías ver ningún cambio debido al nuevo comportamiento predeterminado.

Si entregas tu secuencia de comandos de /service-worker.js con el almacenamiento en caché HTTP habilitado, ya sea de forma intencional o porque es solo el predeterminado de tu entorno de hosting, es posible que comiences a ver un aumento de solicitudes HTTP adicionales para /service-worker.js realizadas en tu servidor, que son solicitudes que solían satisfacer 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 el service worker.

Dado que puede haber una cola larga de usuarios en versiones anteriores del navegador, te recomendamos que continúes configurando el encabezado HTTP Cache-Control: max-age=0 en las secuencias de comandos del service worker, aunque los navegadores más nuevos puedan ignorarlos.

Los desarrolladores pueden aprovechar esta oportunidad para decidir si desean inhabilitar de forma explícita sus secuencias de comandos importadas del almacenamiento en caché HTTP ahora y agregar updateViaCache: 'none' a su registro de service worker, si corresponde.

Entrega secuencias de comandos importadas

A partir de Chrome 78, es posible que los desarrolladores vean más solicitudes HTTP entrantes para recursos cargados a través de importScripts(), ya que ahora se buscarán 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 hash en sus URLs y usa el comportamiento predeterminado updateViaCache de 'imports'.

Como alternativa, si quieres que tus secuencias de comandos importadas se verifiquen en busca de actualizaciones frecuentes, asegúrate de entregarlas con Cache-Control: max-age=0 o de usar updateViaCache: 'none'.

Lecturas adicionales

"The Service Worker Lifecycle" (El ciclo de vida del service worker) y "Caching best Practices & max-age gotchas", de Jake Archibald, son lecturas recomendadas para todos los desarrolladores que implementan algo en la Web.