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é con la que interactúa tu trabajador de servicio, usa la API de Cache Storage.

Browser Support

  • Chrome: 43.
  • Edge: 16.
  • Firefox: 41.
  • Safari: 11.1.

Source

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

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

Una ventaja de administrar tu caché con Service Workers 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 bajo una conexión TLS.

Qué almacenar en caché

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

Esos recursos deben incluir lo siguiente:

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

Listo para el uso sin conexión

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

Tu APW 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 evitar un error genérico y confuso del navegador.

Existen muchas estrategias de almacenamiento en caché diferentes que puedes usar según las necesidades de tu PWA. Por eso, es importante diseñar el uso de la caché para brindar una experiencia rápida y confiable. Por ejemplo, si todos los recursos de tu app se descargan rápido, no ocupan mucho espacio y no necesitan actualizarse en cada solicitud, almacenar en caché todos tus recursos sería una estrategia válida. Por otro lado, si tienes recursos que deben ser la versión más reciente, tal vez te convenga no almacenarlos en caché.

Usa 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 puedes definir. Accede a la API a través del objeto caches, y el método open permite crear o abrir una caché ya creada. El método open devuelve 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 recursos

Para solicitarle 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 de caché almacena la totalidad de una respuesta, incluidos todos los encabezados y el cuerpo. Por lo tanto, puedes recuperarlo más tarde con una solicitud HTTP o una URL como clave. Verás cómo hacerlo en el capítulo sobre la publicación.

Cuándo almacenar en caché

En tu PWA, tú decides cuándo almacenar archivos en caché. Si bien un enfoque es almacenar la mayor cantidad posible de recursos cuando se instala el service worker, por lo general, no es 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 publique recursos desactualizados no deseados.

No es necesario que almacenes en caché todos los recursos a la vez. Puedes hacerlo muchas veces durante el ciclo de vida de tu PWA, por ejemplo:

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

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

Almacenamiento en caché de recursos en un service worker

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

Dado que el subproceso del service worker se puede detener en cualquier momento, puedes solicitarle al navegador que espere a que finalice la promesa addAll para aumentar la oportunidad 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 evento recibido en el objeto de escucha de eventos del trabajador de servicio.

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 de la promesa (cumplida o fallida) antes de finalizar el proceso del service worker. Es posible que debas encadenar promesas y devolver las llamadas a add() o addAll() para que un solo resultado llegue al método waitUntil().

También puedes controlar las promesas con la sintaxis async/await. En ese caso, debes crear una función asíncrona que pueda llamar a await y que devuelva 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 PWA puede descargar y almacenar en caché recursos de tu origen y de dominios cruzados, como contenido de CDN de terceros. Con una app de varios dominios, 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 la caché. Al igual que con otros recursos almacenados en caché, solo está disponible para usarse 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 o los encabezados de esa respuesta. Además, las respuestas opacas no exponen su tamaño real en la API de Storage, lo que afecta las cuotas. Algunos navegadores exponen tamaños grandes, como 7 MB, sin importar si el archivo es de solo 1 KB.

Actualiza y borra recursos

Puedes actualizar recursos con cache.put(request, response) y borrarlos con delete(request).

Consulta la documentación del objeto Cache para obtener más detalles.

Cómo depurar el almacenamiento en caché

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

Las Herramientas para desarrolladores de Chrome depuran el contenido de Cache Storage.

Recursos