Trabajadores de servicio más recientes, de forma predeterminada

tl;dr

A partir de Chrome 68, la caché HTTP ya no completará de forma predeterminada las solicitudes HTTP que verifiquen si hay actualizaciones de la secuencia de comandos del service worker. Esto soluciona un punto problemático común para los desarrolladores, en el que configurar un encabezado Cache-Control involuntario en la secuencia de comandos del service worker podría generar actualizaciones retrasadas.

Si ya inhabilitaste el almacenamiento en caché HTTP para la secuencia de comandos /service-worker.js mediante la entrega 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 mediante importScripts(). Cualquier cambio que se realice 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 página nueva que esté dentro del alcance de un service worker, llama explícitamente a registration.update() desde JavaScript o cuando se "despierte" a un service worker mediante un evento push o sync, el navegador, en paralelo, solicitará el recurso 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 lo son la mayoría de las recuperaciones). Esto significaba que, si la secuencia de comandos se envió originalmente con Cache-Control: max-age=600, las actualizaciones en los próximos 600 segundos (10 minutos) no irían 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ía como si fuera 86400, para evitar que los usuarios se quedaran atascados con una versión en particular para siempre.

A partir de 68, la caché HTTP se ignorará cuando se soliciten actualizaciones de la secuencia de comandos del service worker, por lo que es posible que las aplicaciones web existentes experimenten un aumento en la frecuencia de solicitudes de la secuencia de comandos del service worker. Las solicitudes de importScripts se enviarán 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

Ahora, los desarrolladores 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 cómo se hace cuando se realiza la solicitud HTTP para verificar si hay recursos del service worker actualizados.

  • Cuando se configura como 'imports', nunca se consulta la caché HTTP cuando se comprueba si hay actualizaciones de la secuencia de comandos /service-worker.js, pero se consulta cuando se recuperan secuencias de comandos importadas (path/to/import.js, en nuestro ejemplo). Este es el valor predeterminado, y coincide con el comportamiento a partir de Chrome 68.

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

  • Cuando se establece en 'none', no se consulta la caché HTTP cuando se realizan solicitudes para el /service-worker.js de nivel superior o para cualquier secuencia de comandos importada, como la path/to/import.js hipotética.

Por ejemplo, el siguiente código registrará un service worker y garantizará que la caché HTTP nunca se consulte cuando se busquen actualizaciones en la secuencia de comandos /service-worker.js o en cualquier secuencia de comandos a la que se haga referencia mediante importScripts() dentro de /service-worker.js:

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/service-worker.js', {
    updateViaCache: 'none',
    // Optionally, set 'scope' here, if needed.
  });
}

Comprueba si hay actualizaciones de las secuencias de comandos importadas

Antes de Chrome 78, cualquier secuencia de comandos de service worker que se cargara a través de importScripts() se recuperaba una sola vez (verificando primero la caché HTTP o a través de la red, según la configuración de updateViaCache). Después de esa recuperación inicial, el navegador lo almacenaría de forma interna y nunca los volvería a recuperar.

La única manera de forzar a un service worker ya instalado para que realice los cambios en una secuencia de comandos importada era cambiar la URL de la secuencia de comandos. Para ello, se podía agregar un valor semver (p. ej., importScripts('https://example.com/v1.1.0/index.js')) o incluir 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 del service worker de nivel superior cambia el contenido de la secuencia de comandos, que, a su vez, activa el contenido de la secuencia de comandos del service worker de nivel superior.

A partir de Chrome 78, cada vez que se realiza una verificación de actualización para un archivo de service worker de nivel superior, se realizan comprobaciones al mismo tiempo para determinar si cambiaron o no el contenido de las secuencias de comandos importadas. Según los encabezados Cache-Control que se usen, la caché HTTP puede llevar a cabo estas verificaciones de secuencias de comandos importadas si updateViaCache se establece en 'all' o 'imports' (que es el valor predeterminado), o las verificaciones pueden 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 byte por byte en comparación con lo que almacenó previamente el service worker, eso, a su vez, activará el flujo de actualización de service worker completo, incluso si el archivo del service worker de nivel superior permanece igual.

El comportamiento de Chrome 78 coincide con lo que Firefox implementó hace varios años, en Firefox 56. Safari ya también implementa este comportamiento.

¿Qué deben hacer los desarrolladores?

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

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

Dado que puede haber una gran cantidad de usuarios en versiones anteriores del navegador, se recomienda seguir 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 explícitamente el almacenamiento en caché de HTTP para sus secuencias de comandos importadas y agregar updateViaCache: 'none' a su registro de service worker si corresponde.

Entrega las 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 URL y dependan del comportamiento predeterminado updateViaCache de 'imports'.

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

Lecturas adicionales

Todos los desarrolladores que implementan algo en la Web son las secciones "The Service Worker Lifecycle" y "Caching best practices & max-age caprich", de Jake Archibald.