Ciclo de vida y privacidad de la caché del service worker
Cómo el registro, la instalación, la activación y la actualización de un service worker definen quién posee cada caché y cómo versionarla, limpiarla y borrarla al cerrar sesión.
Quieres la documentación estructurada de Identidad?
Este artículo forma parte de la biblioteca editorial. Para pasos de configuración, material de referencia y actualizaciones continuas, entra en la sección de docs.
Por qué la caché de un service worker necesita un responsable
Un service worker permite que un sitio responda a peticiones de red desde un almacén local, normalmente Cache Storage. Eso sirve para páginas sin conexión y visitas repetidas más rápidas. También significa que una respuesta puede sobrevivir a la página, a la visita y, a veces, a la cuenta que provocó que se guardara. La especificación de Service Workers describe el worker y su ciclo de vida, y la referencia de CacheStorage en MDN describe las cachés con nombre que el worker o la página pueden abrir.
Cache Storage pertenece al origen, no a una versión concreta del worker. Una caché creada por un worker antiguo sigue ahí cuando un worker nuevo toma el control, y nada la elimina salvo que el código de la aplicación la borre, que el navegador expulse datos por falta de espacio o que el usuario o una respuesta con Clear-Site-Data borre los datos del sitio. El momento de esa expulsión cambia entre navegadores y versiones, así que tómala como una red de seguridad y no como un plan de limpieza.
La pregunta práctica es, por tanto, la propiedad. Para cada caché, un equipo debería poder decir qué versión del worker la creó, qué versión tiene permiso para borrarla y a qué sesión o cuenta de usuario pertenece su contenido. Una caché sin responsable con nombre es una caché que nadie limpiará.
Piensa en una tableta compartida en un mostrador de atención. El personal inicia sesión, abre un panel y cierra sesión al terminar el turno. Si el worker guardó respuestas de API específicas de la cuenta mientras trabajaban, la siguiente persona que abra el panel puede encontrar esas respuestas en el almacenamiento del navegador aunque la interfaz muestre un estado sin sesión. Nada de ese fallo aparece en pantalla, y por eso es fácil pasarlo por alto. El mismo patrón se da en ordenadores familiares, quioscos y cualquier perfil de navegador que use más de una cuenta con el tiempo.
Cache Storage es, además, solo uno de los lugares donde un sitio guarda estado. La caché HTTP del navegador, las cookies, localStorage, IndexedDB y los registros de service workers son almacenes distintos con vías de limpieza distintas. Vaciar uno no vacía los demás. Cuando una revisión pregunta qué queda tras un cierre de sesión, debería enumerar cada almacén que usa la aplicación y comprobarlos uno por uno, en lugar de concluir a partir de una única lista vacía que el dispositivo está limpio.
La obsolescencia y la privacidad comparten una causa. Una caché que nunca se limpia puede servir un script desactualizado después de una corrección, y puede servir una vista de cuenta desactualizada después de un cierre de sesión. En ambos casos el usuario ve contenido que el servidor ya no devolvería. Tratar la limpieza como parte de la versión, en lugar de una tarea posterior, aborda ambos riesgos con la misma regla y la misma revisión.
Las fases del ciclo de vida
Una página pide al navegador que registre un worker para un ámbito. El navegador descarga el script y ejecuta la fase de instalación. Un worker que se instaló mientras otro más antiguo todavía controla páginas abiertas pasa a un estado de espera hasta que esas páginas se cierran o la aplicación decide saltarse la espera. Después se ejecuta la fase de activación y, desde ese momento, el worker atiende los eventos fetch de las páginas que controla. La guía del ciclo de vida de web.dev recorre estas fases con ejemplos.
Las actualizaciones dependen del propio script. Cuando el navegador detecta que el script del worker difiere del instalado, instala la versión nueva junto a la antigua en lugar de sustituirla directamente. La frecuencia con la que el navegador comprueba si el script cambió depende de la navegación, de los eventos funcionales y de la política del propio navegador, así que un despliegue no debe suponer que cada usuario recibe el worker nuevo en un momento predecible.
Por eso un worker nuevo puede estar instalado y aun así no estar en servicio. Quien revisa y ve el script nuevo en el servidor no puede concluir que ya atiende páginas. El worker está activo, en espera o reemplazado, y la comprobación debe leer ese estado en lugar de darlo por supuesto. Consulta la guía Using Service Workers para ver los eventos implicados.
Dos llamadas cambian el comportamiento de la espera y merecen una decisión deliberada. Saltarse la fase de espera hace que un worker nuevo se active de inmediato, y reclamar clientes le permite tomar el control de páginas que se abrieron antes que él. Ambas pueden ser adecuadas para una corrección pequeña, pero también implican que una página abierta que cargó scripts antiguos puede empezar a recibir respuestas de una caché preparada para la versión nueva. Si la página antigua y la caché nueva no son compatibles, el usuario ve un comportamiento roto que ninguna versión contiene por separado. Registra si la aplicación se salta la espera y qué efecto tiene eso en las páginas abiertas.
El ámbito de registro también importa. Un worker solo controla las páginas dentro de su ámbito, y las páginas del mismo origen comparten el acceso a las mismas entradas de caché. Una caché rellenada por un worker puede, por tanto, ser leída por páginas que ese worker no controla, otra razón para nombrar cada caché y a su responsable.
La fase fetch es donde el worker decide qué servir. Los recursos estáticos que solo cambian con una versión encajan con un enfoque de caché primero, porque la etiqueta de versión ya controla la frescura. Las páginas personalizadas y las respuestas de API suelen encajar con un enfoque de red primero, y algunas no deberían guardarse nunca. Escribir la estrategia por categoría de petición, en lugar de una sola regla para el sitio completo, simplifica la regla de limpieza posterior, porque cada categoría corresponde a una caché con un responsable y una vida útil conocidos.
Una actualización desplegada se puede observar en lugar de adivinar. Las herramientas de desarrollo muestran el worker registrado, la dirección de su script y si hay una versión más reciente en espera. Tras una versión, carga la aplicación en un contexto nuevo, lee ese panel y anota el estado en el registro de la versión. Si se indica un worker en espera, decide si esperar a que se cierren las páginas, pedir al usuario que recargue o saltarte la espera, y deja la decisión por escrito.
Cachés versionadas y limpieza en la activación
Da a cada caché un nombre que lleve una etiqueta de versión, por ejemplo un prefijo para el armazón de la aplicación y una etiqueta de versión a continuación. Crea la nueva caché versionada y rellénala durante la fase de instalación, porque es el momento en que el worker nuevo prepara sus propios recursos mientras el antiguo sigue sirviendo páginas desde la caché antigua.
Separa las cachés por finalidad, no solo por versión. Una caché para los archivos del armazón de la aplicación, otra para las imágenes y otra para los datos de la cuenta tienen vidas útiles distintas. La caché del armazón se reemplaza en cada versión, la de imágenes puede recortarse por antigüedad o cantidad, y la de la cuenta termina con la sesión. Mantenerlas en cachés con nombres distintos permite que la regla de limpieza trate bien a cada una y que quien revisa responda qué caché guarda qué sin abrir entradas individuales.
Borra las cachés antiguas durante la fase de activación. La activación es el primer momento en que el worker antiguo deja de ser necesario, y eliminar su caché antes puede romper páginas que siguen en ejecución. Una regla habitual enumera los nombres de caché, conserva los que corresponden a la versión actual y borra el resto. Deja esa regla por escrito para que una revisión pueda comprobarla.
Ten cuidado con los nombres que la regla de limpieza puede borrar. Cache Storage es compartida por el origen completo, así que una lista de nombres de caché puede incluir cachés creadas por otro código del mismo origen, como un worker antiguo de otra función. Limita el borrado a los nombres que empiezan con tu propio prefijo. Recuerda también que una petición fallida mientras se rellena la caché nueva durante la instalación puede impedir que el worker nuevo llegue a instalarse, y entonces el worker antiguo y su caché siguen en su sitio. Comprueba el estado del worker tras una versión en lugar de suponer que la instalación terminó.
Cache Storage no aplica por sí sola las reglas de frescura de HTTP. Una entrada permanece hasta que el código la borra, y por eso una respuesta obsoleta puede seguir apareciendo después de corregir el servidor. Mantén la etiqueta de versión en el nombre de la caché, coloca el contenido cambiante bajo un nombre nuevo y deja que la regla de activación elimine el anterior.
No uses un worker para interceptar, reescribir o conservar datos más allá de lo que la página necesita para funcionar. El objetivo de este ciclo de vida es un almacenamiento más pequeño y predecible, no una capa oculta que retenga respuestas que nadie ve. Mantén la limpieza visible para las personas que operan el sitio.
Mantén el código de limpieza pequeño y probado. Una rutina que lista nombres, filtra por prefijo y borra versiones antiguas es lo bastante corta como para leerla en una revisión. Ejecútala en un contexto que ya tenga varias versiones antiguas, porque una rutina probada solo en una instalación nueva nunca se enfrenta al caso para el que existe. Durante las pruebas, imprime en la consola de desarrollo los nombres que elimina para poder comparar el resultado con la lista de cachés después.
Cierre de sesión, cambio de cuenta y Clear-Site-Data
Algunas respuestas son específicas de un usuario con sesión iniciada. Una caché que las contiene no es un recurso sin conexión inofensivo: tras un cierre de sesión o un cambio de cuenta en un dispositivo compartido, el siguiente usuario puede ver lo que guardó la cuenta anterior. Es preferible no guardar en caché respuestas autenticadas o específicas de una cuenta. Si una función las necesita sin conexión, limita la caché a esa cuenta y bórrala cuando termine la sesión.
El orden de los pasos al cerrar sesión importa. Termina primero la sesión del servidor, después borra las cachés de la cuenta y por último limpia el estado que la página conserve en memoria. Si la aplicación tiene varias pestañas abiertas, avisa a las demás de que la cuenta cambió, por ejemplo con un mensaje de difusión, para que una pestaña que sigue abierta no siga mostrando datos en caché de la cuenta anterior. Prueba la secuencia con dos pestañas abiertas, porque una prueba con una sola pestaña oculta este caso.
Al cerrar sesión, la aplicación puede borrar las cachés de la cuenta desde el código de la página y pedir al worker que descarte cualquier estado en memoria. La especificación Clear-Site-Data también define una cabecera de respuesta cuyas directivas pueden pedir al navegador que borre datos en caché o almacenados del origen, y la directiva de almacenamiento abarca el almacenamiento del origen accesible por scripts y da de baja sus service workers; la especificación no menciona Cache Storage por su nombre. El soporte de las directivas y su alcance exacto varían según el navegador, así que confirma el resultado en cada navegador que usan tus usuarios en lugar de fiarte del nombre de la cabecera.
Las cabeceras del servidor ayudan, pero no sustituyen la lógica del worker. Una respuesta marcada para no almacenarse indica a las cachés compartidas y privadas cómo comportarse, pero Cache Storage deja esa decisión al código del worker, que elige si introduce una respuesta en una caché. Haz que el worker compruebe lo que va a guardar y mantén por defecto las respuestas específicas de una cuenta fuera de las cachés de larga duración. Una lista breve y explícita de rutas almacenables en caché es más fácil de revisar que una lista larga de excepciones.
Un cambio de cuenta merece la misma atención que un cierre de sesión, porque el perfil del navegador sigue siendo el mismo mientras cambia el usuario. Borra o limita las cachés de la primera cuenta antes de que cargue la segunda y luego lee la lista de cachés para confirmarlo. Leer la lista es una señal más fuerte que confiar en que el código de limpieza se ejecutó.
Las personas que comparten un dispositivo merecen una forma visible de borrar los datos almacenados. Si la aplicación guarda datos de la cuenta sin conexión, ofrece un control claro al cerrar sesión o en los ajustes que los elimine, y explica con palabras sencillas qué se va a eliminar. Quienes usan dispositivos compartidos no pueden inspeccionar Cache Storage por sí mismos, así que la aplicación es el único lugar donde se puede ofrecer esta opción.
Mantén también esta frontera clara para los usuarios. Un cierre de sesión visible que deja discretamente respuestas de la cuenta en el dispositivo es un defecto de privacidad, aunque no intervenga ningún rastreador. Para más contexto sobre cómo los navegadores separan el estado, consulta particionado del almacenamiento y privacidad y gestión de cookies.
Probar el comportamiento de la caché por contexto
BotBrowser permite asignar a cada BrowserContext su propio almacenamiento y estado de sesión, y los service workers creados en un contexto heredan la huella de ese contexto, de modo que un equipo puede probar el ciclo de vida de la caché de un worker por separado para cada identidad. BotBrowser no escribe, no versiona ni purga las cachés del service worker de una aplicación, y no puede hacer seguro un diseño de caché obsoleta o con fugas; el nombrado de cachés, la limpieza en la activación y el borrado al cerrar sesión siguen siendo responsabilidad de la aplicación.
El aislamiento por contexto es útil porque el mismo sitio puede cargarse en dos contextos con cuentas distintas, y cada contexto muestra su propio registro y su propia lista de cachés. Si el segundo contexto muestra entradas creadas por el primero, la aplicación tiene un problema de ámbito, no un problema del navegador. La documentación de aislamiento multicuenta describe el modelo de almacenamiento por contexto, y aislamiento de navegador multicuenta explica cómo lo planifican los equipos.
Una prueba práctica usa dos contextos. En el primer contexto, inicia sesión con una cuenta, carga la aplicación, deja que el worker se instale y abre algunas páginas. Registra el estado del registro y los nombres de las cachés. En el segundo contexto, inicia sesión con otra cuenta y registra los mismos datos. Las dos listas no deberían compartir entradas específicas de una cuenta. Después cierra sesión en el primer contexto y vuelve a leer su lista de cachés. Por último, confirma que el segundo contexto sigue teniendo sus propias entradas, de modo que la limpieza en un contexto no llegó al otro.
Mantén el registro breve y repetible. Anota la versión del navegador, el nombre del contexto, la versión del script del worker, la lista de cachés antes y después de la actualización, la lista de cachés tras cerrar sesión y el estado del worker. No pegues cuerpos de respuesta, tokens ni datos de clientes en el registro. Una lista breve de nombres de caché con resultados de aprobado o fallido basta para una revisión de versión, y permite que la siguiente persona repita la misma comprobación tras el próximo despliegue.
Ejecuta la misma revisión del ciclo de vida en cada contexto que importe para el producto y registra el resultado por contexto. No reutilices el resultado correcto de un contexto para otro.
Ejecuta las comprobaciones del ciclo de vida de la caché
Ejecuta estas comprobaciones en las herramientas de desarrollo del navegador o con un script breve, y registra aprobado o fallido para cada caché.
- Nombra las fases del ciclo de vida que usa el worker (registro, instalación, espera, activación, fetch). Aprobado si las cachés versionadas se crean en el manejador de instalación y se borran en el de activación. Fallido si la limpieza se ejecuta en la instalación.
- Enumera cada nombre de caché con su etiqueta de versión y su responsable. Aprobado si cada nombre corresponde a una versión del worker y a una categoría de datos. Fallido para cualquier nombre que nadie sepa explicar.
- Escribe la regla de limpieza en la activación y la regla de cierre de sesión. Aprobado si ambas indican qué se conserva y qué se borra.
- Cuando el worker nuevo se active, vuelve a listar las cachés. Aprobado si no queda ninguna caché de una versión antigua. Fallido si todavía aparece un nombre antiguo. Mientras el worker esté en espera, registra la caché antigua como pendiente.
- Comprueba el estado del worker tras la actualización. Aprobado si el worker nuevo está activo o consta como en espera. Fallido si la revisión supuso que estaba en servicio sin leer el estado.
- Localiza las cachés que guardan respuestas autenticadas o específicas de una cuenta. Aprobado si están limitadas a la cuenta y desaparecen tras cerrar sesión o cambiar de cuenta. Fallido si se tratan como recursos sin conexión corrientes.
- Repite las comprobaciones 1 a 6 en cada contexto del navegador y registra un resultado distinto para cada uno.
Fuentes
Artículos Relacionados
Lleva BotBrowser de la investigación a producción
Usa estas guías para entender el modelo y después avanzar hacia validación multiplataforma, contextos aislados y despliegue de navegador preparado para escalar.