Cache Storage API para apps sin conexión
Diseño respetuoso con la privacidad para Cache Storage API en apps sin conexión, con coincidencia, versiones, reserva y limpieza.
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.
Cache Storage API ofrece a una aplicación web sin conexión un almacén con nombre para objetos Request y Response. Un Service Worker puede abrir una caché, buscar una solicitud y devolver una respuesta guardada cuando la red no está disponible. La API no decide qué recursos deben conservarse, cuándo están actualizados ni qué cuenta puede leerlos; esas decisiones pertenecen a la aplicación.
El modo sin conexión es, por tanto, un problema de almacenamiento además de un problema de Service Worker. Un diseño fiable asigna un nombre a cada caché, usa versiones cuando cambia una entrega, define una reserva por clase de solicitud y ofrece una eliminación previsible. La especificación de Service Workers define el ciclo de vida y la referencia MDN de Cache documenta los métodos y su coincidencia.
Qué controla Cache Storage
caches es el objeto CacheStorage disponible para un worker y, cuando está permitido, para una ventana. caches.open('app-shell-v3') crea o abre una Cache; cache.put(request, response) guarda una respuesta; cache.match(request) busca una entrada; y caches.delete('app-shell-v2') elimina una caché completa. El navegador asocia esos datos con el origen y con el perfil o contexto correspondiente. El nombre de una caché es un espacio de nombres de la aplicación, no una frontera de seguridad entre códigos del mismo origen.
La API guarda objetos web: HTML, JavaScript, CSS, imágenes o JSON, además de cabeceras que pueden cambiar la interpretación del cuerpo. Guarda solamente respuestas cuyo propósito, duración y responsable estén claros. Si una respuesta contiene un token de sesión, datos de cuenta o una decisión de autorización breve, trátala como estado de la aplicación y no como recurso genérico sin conexión.
Cache Storage es distinto de la caché HTTP, las cookies, localStorage, IndexedDB y los registros de Service Worker. Vaciar un almacén no vacía los demás. Una revisión de cierre de sesión debe enumerarlos y probar cada limpieza. Un cache.delete() correcto demuestra que desapareció una caché; no demuestra que desaparecieron cookies o registros de IndexedDB. Consulta el modelo de almacenamiento del navegador y la partición del almacenamiento para separar estas fronteras.
El navegador puede expulsar datos por presión de almacenamiento y la persona puede borrarlos desde sus ajustes. La expulsión es un último recurso de espacio, no un proceso de publicación ni un control de privacidad. Una aplicación que necesita una respuesta sin conexión debe poder descargarla de nuevo y funcionar cuando la caché esté vacía. Cuando varias funciones comparten el origen, usa prefijos separados y limita la eliminación a los nombres que pertenecen a la función actual.
Coincidir solicitudes sin sorpresas
Cache.match() compara una solicitud con las entradas guardadas mediante las reglas de coincidencia de la plataforma. No es una consulta general sobre cuerpos de respuesta ni convierte todos los métodos en operaciones seguras de repetir. Clasifica las solicitudes para que la política del worker sea legible.
Los recursos estáticos con una versión, como un paquete JavaScript, suelen encajar con cache-first: se consulta la caché versionada y, si falta la entrada, se descarga y se guarda. Para navegación o datos que deben reflejar el servidor suele ser mejor network-first: se intenta la red, se actualiza solo con una respuesta válida y se usa lo guardado cuando falla la red.
No guardes toda respuesta correcta automáticamente. Un POST que crea un pedido o cambia un perfil no se vuelve seguro de repetir por guardar su respuesta. Una respuesta personalizada por una cabecera de autorización, una cookie o una cuenta requiere una política explícita. Para muchos productos, la reserva más segura es mostrar un estado no disponible y pedir conexión, en lugar de conservar la respuesta.
Parámetros, cabeceras, método y modo de caché pueden cambiar la coincidencia. Si la representación cambia con una cabecera, incluye esa dimensión en la clave o evita una caché compartida. Una misma URL puede tener varias representaciones válidas; devolver la equivocada es un error de corrección. Documenta una tabla pequeña que relacione clase de solicitud, caché, frescura y reserva.
Una reserva de navegación debe indicar si los datos están actualizados. El worker puede devolver una carcasa de aplicación guardada, pero la interfaz debe señalar el modo sin conexión y ofrecer reintento; no debe presentar un panel antiguo como respuesta viva. Las respuestas opacas y los recursos de otros orígenes necesitan una revisión propia de orígenes permitidos, fallos y eliminación. No uses Cache Storage para inspeccionar contenido privado de otro sitio.
Versiones y actualizaciones
Trata el nombre de caché como un contrato de entrega, por ejemplo offline-shell-v7. Durante install, crea y llena la nueva caché; durante activate, lista los nombres de la función y elimina las versiones antiguas. Un worker nuevo puede quedar esperando mientras otro controla páginas abiertas; consulta la guía MDN del ciclo de vida.
Si falla un recurso obligatorio, rechaza la instalación en vez de activar una entrega incompleta. Los recursos opcionales pueden vivir en otra caché con reintento. La limpieza de activación debe conservar la versión actual y borrar solo nombres con el prefijo propio. Registra versión, nombres antes y después, y si hubo un worker esperando.
skipWaiting() y clients.claim() adelantan el control del nuevo worker, pero una pestaña antigua puede recibir respuestas preparadas para un contrato nuevo. Úsalos solo tras probar compatibilidad; si hay duda, deja esperar al worker y pide recargar en un límite claro. Usa URLs con contenido versionado o con versión de entrega para no cambiar bytes de una caché sin cambiar su nombre.
Reserva y recuperación sin conexión
Define un resultado para carcasa, navegación, imagen, fuente, lectura de API y escritura. Una lectura antigua puede necesitar una etiqueta de antigüedad y un botón de actualizar. Una escritura solo debe encolarse si es idempotente o tiene una clave de idempotencia de la aplicación y un estado de reintento visible. Cache Storage no ofrece por sí sola una cola duradera ni resolución de conflictos.
Distingue una ausencia de caché de un error guardado. No almacenes un 500 temporal ni una redirección de autenticación como página sin conexión. Comprueba estado y tipo de contenido antes de cache.put(). Si no existe reserva, devuelve un documento sin conexión pequeño y controlado que explique la siguiente acción.
Una respuesta de reintento solo reemplaza a la antigua después de pasar las mismas validaciones. Guarda borradores sin conexión en un almacén apropiado y muestra la última sincronización; no ocultes una escritura pendiente en una entrada que una actualización puede eliminar. Prueba contextos frío, cálido y degradado, y registra estado del worker, nombres, clase de solicitud, origen de respuesta y resultado visible sin guardar tokens ni cuerpos.
Limpieza, cierre de sesión y control de la persona
La eliminación es una función. Mantén una operación para cachés de versiones antiguas y otra para cuentas o borradores, para que una entrega no borre trabajo sin conexión y un cierre de sesión no deje datos de cuenta en la carcasa. Al cerrar sesión o cambiar de cuenta, termina primero la sesión del servidor, pide al worker eliminar cachés de cuenta, limpia memoria y avisa a otras pestañas. Prueba dos pestañas abiertas.
Clear-Site-Data puede solicitar la limpieza de categorías de datos del origen, pero su cobertura depende del navegador y no sustituye al código de la aplicación. Del mismo modo, Cache-Control describe la caché HTTP y no impide que un worker llame a cache.put(). El código que escribe Cache Storage debe aplicar la política antes de guardar.
Minimiza los datos: conserva solo la respuesta necesaria para la pantalla sin conexión, evita tokens en cuerpos y define una retención para borradores y medios. El control de limpieza debe decir si afecta a la sesión, al trabajo encolado o solo a recursos estáticos.
Pruebas con BotBrowser y límites documentados
BotBrowser puede crear contextos de navegador repetibles con almacenamiento y sesión aislados, por lo que un equipo puede comparar flujos frío, cálido y de cierre de sesión sin transferir el estado de un contexto a otro. Consulta la documentación de aislamiento multi cuenta y registra estado del worker, nombres de caché y reserva visible. BotBrowser admite contextos aislados para estas comprobaciones, pero no escribe, versiona, purga ni interpreta las entradas Cache Storage, no garantiza la expulsión del navegador, la disponibilidad sin conexión ni la corrección de la estrategia de Service Worker; la aplicación sigue siendo responsable de propiedad y limpieza.
Usa un contexto sin caché, otro tras instalar y otro tras actualizar. Carga una carcasa conocida, corta la red en el límite permitido por la prueba, confirma que la reserva se identifica como sin conexión y, al restaurarla, verifica que solo una respuesta validada reemplaza la anterior. Repite cierre y cambio de cuenta con dos contextos y dos pestañas. Compara nombres y estado del worker, no cuerpos privados.
La evidencia de BotBrowser debe limitarse a aislamiento, navegación, estado del worker visible y aserciones de la lista de cachés de la aplicación. Pasar una comparación no prueba el comportamiento de expulsión de todos los navegadores, la corrección en producción ni la reproducción segura de escrituras; esas afirmaciones requieren pruebas propias, cobertura por navegador y una decisión explícita.
Cada nombre de caché debe indicar su función y su versión.
El instalador debe rechazar recursos obligatorios incompletos.
Los recursos opcionales necesitan un reintento separado.
La activación solo puede borrar el prefijo que pertenece a la función.
Una respuesta guardada no demuestra que la red haya sido utilizada.
Una reserva visible debe explicar cuándo se puede reintentar.
La respuesta de una cuenta no es un recurso público del shell.
Dos pestañas deben recibir la señal de un cambio de cuenta.
La limpieza de una versión no debe eliminar un borrador.
Un contexto nuevo sirve para separar el estado anterior.
Los registros de prueba deben omitir tokens y cuerpos privados.
Fuentes públicas
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.