Almacenamiento en caché

El almacenamiento en caché es una herramienta poderosa. Hace que tus apps dependan menos de las condiciones de red. Con un buen uso de las memorias caché, puedes hacer que tu app web esté disponible sin conexión y publicar tus recursos lo más rápido posible en cualquier condición de red. Como se mencionó en Recursos y datos, puedes decidir la mejor estrategia para almacenar en caché los recursos necesarios. Para administrar la caché, tu service worker interactúa con la API de Cache Storage.

Navegadores compatibles

  • 43
  • 16
  • 41
  • 11.1

Origen

La API de Cache Storage está disponible en diferentes contextos:

  • El contexto de la ventana (el subproceso principal de la AWP)
  • El service worker
  • Cualquier otro trabajador que uses.

Una de las ventajas de administrar tu caché con service worker es que su ciclo de vida no está vinculado a la ventana, lo que significa que no bloqueas el subproceso principal. Ten en cuenta que, para usar la API de Cache Storage, la mayoría de estos contextos deben estar en una conexión TLS.

Qué almacenar en caché

La primera pregunta que puedes tener sobre el almacenamiento en caché es qué almacenar en caché. Si bien no hay una sola respuesta para esa pregunta, puedes comenzar con todos los recursos mínimos necesarios para renderizar la interfaz de usuario.

Esos recursos deben incluir:

  • El código HTML de la página principal (la start_url de tu aplicación).
  • Hojas de estilo CSS necesarias para la interfaz de usuario principal
  • Imágenes usadas en la interfaz de usuario.
  • Archivos JavaScript necesarios para procesar la interfaz de usuario.
  • Son los datos necesarios, como un archivo JSON, para renderizar una experiencia básica.
  • Fuentes web.
  • En una aplicación de varias páginas, otros documentos HTML que quieras publicar de forma rápida o sin conexión.

Listo sin conexión

Si bien poder trabajar sin conexión es uno de los requisitos de una aplicación web progresiva, es esencial comprender que no todas las AWP necesitan una experiencia sin conexión completa, por ejemplo, soluciones de videojuegos en la nube o aplicaciones de criptoactivos. Por lo tanto, está bien ofrecer una interfaz de usuario básica que guíe a los usuarios en esas situaciones.

Tu AWP no debe renderizar un mensaje de error del navegador que indique que el motor de renderización web no pudo cargar la página. En su lugar, usa tu service worker para mostrar tus propios mensajes y así evitar un error genérico y confuso del navegador.

Hay muchas estrategias de almacenamiento en caché diferentes que puedes usar según las necesidades de tu AWP. Por ello, es importante diseñar el uso de la caché para brindar una experiencia rápida y confiable. Por ejemplo, si todos tus recursos de aplicación se descargan rápidamente, no consumen mucho espacio y no necesitan actualizarse en cada solicitud, almacenar en caché todos los recursos sería una estrategia válida. Si, por otro lado, tiene recursos que necesitan la última versión, quizás le convenga considerar no almacenar en caché esos elementos en absoluto.

Cómo usar la API

Usa la API de Cache Storage para definir un conjunto de cachés dentro de tu origen, cada una identificada con un nombre de cadena que puedas definir. Accede a la API a través del objeto caches, y el método open habilita la creación o la apertura de una caché ya creada. El método abierto muestra una promesa para el objeto de caché.

caches.open("pwa-assets")
.then(cache => {
  // you can download and store, delete or update resources with cache arguments
});

Descarga y almacenamiento de elementos

Para pedirle al navegador que descargue y almacene los recursos, usa los métodos add o addAll. El método add realiza una solicitud y almacena una respuesta HTTP, y addAll, un grupo de respuestas HTTP como una transacción basada en un array de solicitudes o URLs.

caches.open("pwa-assets")
.then(cache => {
  cache.add("styles.css"); // it stores only one resource
  cache.addAll(["styles.css", "app.js"]); // it stores two resources
});

La interfaz de almacenamiento en caché almacena toda una respuesta, incluidos todos los encabezados y el cuerpo. Por lo tanto, puedes recuperarlos más tarde con una solicitud HTTP o una URL como clave. Verás cómo hacerlo en el capítulo Publicación.

Cuándo almacenar en caché

En tu AWP, tú eres el responsable de decidir cuándo almacenar archivos en caché. Si bien un enfoque es almacenar tantos recursos como sea posible cuando se instala el service worker, no suele ser la mejor idea. El almacenamiento en caché de recursos innecesarios desperdicia ancho de banda y espacio de almacenamiento, y podría hacer que tu app entregue recursos desactualizados no deseados.

No es necesario que almacenes en caché todos los recursos a la vez, puedes almacenarlos en caché muchas veces durante el ciclo de vida de tu AWP, como los siguientes:

  • Durante la instalación del service worker
  • Después de que se cargue la primera página
  • Cuando el usuario navega a una sección o ruta.
  • Cuando la red está inactiva.

Puedes solicitar que se almacenen en caché los archivos nuevos en el subproceso principal o en el contexto del service worker.

Almacena recursos en caché en un service worker

Una de las situaciones más comunes es almacenar en caché un conjunto mínimo de elementos cuando se instala el service worker. Para ello, puedes usar la interfaz de almacenamiento en caché dentro del evento install en el service worker.

Debido a que el subproceso del service worker se puede detener en cualquier momento, puedes solicitar al navegador que espere a que finalice la promesa addAll para aumentar las posibilidades de almacenar todos los recursos y mantener la coherencia de la app. En el siguiente ejemplo, se muestra cómo hacerlo con el método waitUntil del argumento de eventos recibido en el objeto de escucha de eventos del service worker.

const urlsToCache = ["/", "app.js", "styles.css", "logo.svg"];
self.addEventListener("install", event => {
   event.waitUntil(
      caches.open("pwa-assets")
      .then(cache => {
         return cache.addAll(urlsToCache);
      });
   );
});

El método waitUntil() recibe una promesa y le pide al navegador que espere a que se resuelva la tarea (completada o con errores) antes de finalizar el proceso del service worker. Es posible que debas encadenar promesas y mostrar las llamadas add() o addAll() para que un solo resultado llegue al método waitUntil().

También puedes manejar promesas con la sintaxis async/await. En ese caso, debes crear una función asíncrona que pueda llamar a await y que muestre una promesa a waitUntil() después de que se la llame, como en el siguiente ejemplo:

const urlsToCache = ["/", "app.js", "styles.css", "logo.svg"];
self.addEventListener("install", (event) => {
   let cacheUrls = async () => {
      const cache = await caches.open("pwa-assets");
      return cache.addAll(urlsToCache);
   };
   event.waitUntil(cacheUrls());
});

Solicitudes multidominio y respuestas opacas

Tu AWP puede descargar y almacenar en caché recursos de tu origen y de varios dominios, como el contenido de CDN de terceros. Con una app multidominio, la interacción de la caché es muy similar a las solicitudes del mismo origen. Se ejecuta la solicitud y se almacena una copia de la respuesta en tu caché. Al igual que con otros elementos almacenados en caché, solo está disponible para su uso en el origen de tu app.

El recurso se almacenará como una respuesta opaca, lo que significa que tu código no podrá ver ni modificar el contenido ni los encabezados de esa respuesta. Además, las respuestas opacas no exponen su tamaño real en la API de almacenamiento, lo que afecta las cuotas. Algunos navegadores exponen tamaños grandes, como 7 MB, sin importar si el archivo pesa solo 1 KB.

Cómo actualizar y borrar elementos

Puedes actualizar elementos utilizando cache.put(request, response) y borrar recursos con delete(request).

Consulta la documentación de objetos en caché para obtener más detalles.

Depuración del almacenamiento en caché

Muchos navegadores ofrecen una manera de depurar el contenido del almacenamiento en caché dentro de la pestaña Aplicación de Herramientas para desarrolladores. Allí podrás ver el contenido de cada caché dentro del origen actual. Encontrarás más información sobre estas herramientas en el capítulo Herramientas y depuración.

Las Herramientas para desarrolladores de Chrome depuran el contenido del almacenamiento en caché.

Recursos