Mantén todo actualizado con stale-while-revalidate

Es una herramienta adicional que te ayuda a equilibrar la inmediatez y la actualización cuando se entrega tu app web.

stale-while-revalidate ayuda a los desarrolladores a equilibrar la inmediatez (cargar el contenido almacenado en caché de inmediato) y la actualización (garantizar que se usen las actualizaciones del contenido almacenado en caché en el futuro). Si mantienes un servicio web o una biblioteca de terceros que se actualiza según un cronograma regular, o tus elementos propios tienden a tener duraciones breves, stale-while-revalidate puede ser un complemento útil para tus políticas de almacenamiento en caché existentes.

La compatibilidad para configurar stale-while-revalidate junto con max-age en el encabezado de respuesta Cache-Control está disponible en Chrome 75 y Firefox 68.

Los navegadores que no admiten stale-while-revalidate ignorarán de forma silenciosa ese valor de configuración y usarán max-age, como explicaré en breve…

¿Qué significa?

Dividamos stale-while-revalidate en dos partes: la idea de que una respuesta almacenada en caché podría estar desactualizada y el proceso de revalidación.

En primer lugar, ¿cómo sabe el navegador si una respuesta almacenada en caché está "inactiva"? Un encabezado de respuesta Cache-Control que contiene stale-while-revalidate también debe contener max-age, y la cantidad de segundos especificada a través de max-age es lo que determina la inactividad. Cualquier respuesta almacenada en caché que sea más reciente que max-age se considera actualizada, y las respuestas almacenadas en caché más antiguas están inactivas.

Si la respuesta almacenada en caché localmente aún está actualizada, se puede usar tal como está para completar la solicitud de un navegador. Desde la perspectiva de stale-while-revalidate, no hay nada que hacer en esta situación.

Sin embargo, si la respuesta almacenada en caché está inactiva, se realiza otra verificación basada en la antigüedad: ¿la antigüedad de la respuesta almacenada en caché está dentro del período adicional proporcionado por la configuración de stale-while-revalidate?

Si la antigüedad de una respuesta inactiva se encuentra dentro de este período, se usará para completar la solicitud del navegador. Al mismo tiempo, se realizará una solicitud de "revalidación" a la red de una manera que no retrase el uso de la respuesta almacenada en caché. La respuesta que se muestra puede contener la misma información que la respuesta almacenada en caché anteriormente o puede ser diferente. De cualquier manera, la respuesta de la red se almacena de forma local, lo que reemplaza lo que era antes almacenado en caché y restablece el temporizador de “actualización” que se usó durante cualquier comparación futura de max-age.

Sin embargo, si la respuesta almacenada en caché inactiva tiene la antigüedad suficiente como para que se agote fuera del período stale-while-revalidate, no cumplirá con la solicitud del navegador. En su lugar, el navegador recuperará una respuesta de la red y la usará para completar la solicitud inicial y también para propagar la caché local con una respuesta nueva.

Ejemplo en vivo

A continuación, se muestra un ejemplo simple de una API de HTTP para mostrar la hora actual, más precisamente, la cantidad actual de minutos transcurridos desde la hora.

En esta situación, el servidor web usa este encabezado Cache-Control en su respuesta HTTP:

Cache-Control: max-age=1, stale-while-revalidate=59

Este parámetro de configuración significa que, si se repite una solicitud de hora en el próximo segundo, el valor almacenado en caché anteriormente seguirá siendo actual y se usará tal como está, sin ninguna validación.

Si se repite una solicitud entre 1 y 60 segundos más tarde, el valor almacenado en caché estará inactivo, pero se usará para entregar la solicitud a la API. Al mismo tiempo, se realizará una solicitud de nueva validación en segundo plano para propagar la caché con un valor actualizado para su uso futuro.

Si se repite una solicitud después de más de 60 segundos, no se usa la respuesta inactiva, y la entrega de la solicitud del navegador y la validación de la caché dependerán de que se reciba una respuesta de la red.

A continuación, se muestra un desglose de esos tres estados distintos, junto con el período en el que se aplica cada uno de ellos en nuestro ejemplo:

Un diagrama que ilustra la información de la sección anterior.

¿Cuáles son los casos de uso comunes?

Si bien el ejemplo anterior de un servicio de API de "minutos después de la hora" es artificial, ilustra el caso de uso esperado: servicios que proporcionan información que es necesario actualizar, pero en los que se acepta cierto grado de inactividad.

Algunos ejemplos menos elaborados podrían ser una API para las condiciones climáticas actuales o los titulares de noticias principales que se escribieron en la última hora.

Por lo general, cualquier respuesta que se actualice en un intervalo conocido, sea probable que se solicite varias veces y sea estática dentro de ese intervalo es un buen candidato para el almacenamiento en caché a corto plazo a través de max-age. El uso de stale-while-revalidate además de max-age aumenta la probabilidad de que las solicitudes futuras se puedan entregar desde la caché con contenido más reciente, sin bloquear una respuesta de red.

¿Cómo interactúa con los trabajadores del servicio?

Si escuchaste sobre stale-while-revalidate, es probable que haya sido en el contexto de las recetas que se usan en un trabajador de servicio.

El uso de datos inactivos durante la validación a través de un encabezado Cache-Control comparte algunas similitudes con su uso en un trabajador de servicio, y se aplican muchas de las mismas consideraciones sobre las compensaciones de actualización y las duraciones máximas. Sin embargo, hay algunas consideraciones que debes tener en cuenta cuando decidas si implementarás un enfoque basado en service workers o solo te basarás en la configuración del encabezado Cache-Control.

Usa un enfoque de trabajador de servicio en los siguientes casos:

  • Ya usas un service worker en tu app web.
  • Necesitas un control detallado sobre el contenido de tus cachés y quieres implementar algo como una política de vencimiento que se usó de forma menos reciente. El módulo Cache Expiration de Workbox puede ayudarte con esto.
  • Quieres recibir una notificación cuando cambie una respuesta inactiva en segundo plano durante el paso de validación. El módulo Broadcast Cache Update de Workbox puede ayudarte con esto.
  • Necesitas este comportamiento de stale-while-revalidate en todos los navegadores modernos.

Usa un enfoque de control de caché en los siguientes casos:

  • Prefieres no lidiar con la sobrecarga de implementar y mantener un service worker para tu app web.
  • No te importa permitir que la administración automática de la caché del navegador evite que las cachés locales crezcan demasiado.
  • No te importa usar un enfoque que, actualmente, no es compatible con todos los navegadores modernos (a partir de julio de 2019; es posible que la compatibilidad aumente en el futuro).

Si usas un service worker y también tienes habilitado stale-while-revalidate para algunas respuestas a través de un encabezado Cache-Control, el service worker, en general, tendrá la "primera oportunidad" de responder a una solicitud. Si el trabajador de servicio decide no responder o, en el proceso de generar una respuesta, realiza una solicitud de red con fetch(), el comportamiento configurado a través del encabezado Cache-Control entrará en vigencia.

Más información

Imagen hero de Samuel Zeller.