Cabeceras HTTP de caché

Existen cabeceras de caché que se pueden utilizar desde el protocolo HTTP a la hora de decirle al navegador si ese contenido ha de guardarse o no, y durante cuánto tiempo.

NOTA: En este artículo se hace un repaso de los elemenos más interesantes y aplicables. Si te interesa conocer con más detalle otras posibilidades, por favor, revisa las Cabeceras HTTP en Web Docs.

Age

La cabecera Age sólo se debería utilizar si tenemos una caché intermedia, ya sea algo del estilo a Cloudflare como un de un web-proxy, tipo Varnish. Esta cabecera está soportada por todos los navegadores.

Esta cabecera debería indicar el tiempo que hace que está cacheado ese objeto, es decir, el tiempo desde el momento actual hasta en el que se puso en caché.

El número que se indica está en segundos.

Un elemento que hace una hora y media que está en caché indicaría tal que así:

Age: 5400

Cache-Control

La cabecera Cache-Control se manda al navegador desde el servidor para indicar cómo se debe cachear ese objeto en el propio navegador. Esta cabecera está soportada por todos los navegadores, aunque tiene un elemento experimental que sólo soporta Firefox (luego lo detallo).

Este elemento dispone de varias posibles partes (no se han de utilizar todas siempre).

Almacenamiento

Además de la caché propia que define el navegador, se pueden forzar algunas cosas diferentes.

Por ejemplo, por defecto, una petición bajo HTTPS no se debe cachear, pero como hoy en día la mayoría del tráfico viaja sobre HTTPS, quizá queramos que sí que se cacheen. Un ejemplo simple pero clarificador es el del logo de la página, que se va a utilizar probablemente en todos sitios… y por tanto deberíamos cachearlo.

De la misma forma, quizá haya algún elemento que queramos cachear pero sólo para ese usuario y en esa sesión. Esta petición sería privada.

Si queremos que un elemento no se almacene en la caché deberemos decirle que no se almacene específicamente. Un ejemplo podría ser, por ejemplo, una imagen de un captcha, o la de un PDF con datos bancarios.

Algunos ejemplos de estos casos serían:

Cache-Control: public;
Cache-Control: private;
Cache-Control: no-store;

Es importante tener en cuenta que la opción no-cache no significa que no se vaya a almacenar, sino que si existe una versión cacheada se ha de revalidar con el servidor.

En resumen, con estos elementos le decimos al navegador dónde se ha de almacenar la información.

Expiración

Cuando almacenamos algo en la caché del navegador deberíamos informar cuánto debería durar esa información, o dejar un datos con el que poder calcular cuándo se ha guardado.

Por norma general le indicaremos cuánto tiempo debería estar ese elemento en la caché, el tiempo máximo. En este caso indicaremos los segundos que estará.

Por norma general este tiempo se define según el tipo de fichero. Por ejemplo, las imágenes suelen poderse guardar meses, pero un fichero que pueda llegar a modificarse, minutos u horas.

Cache-Control: max-age=3600;

Pero, también por nuestra seguridad, podríamos indicar al navegador qué ocurre si un contenido está obsoleto, y no se puede recuperar del servidor una nueva versión.

De la misma forma que el caso anterior, podríamos indicar este elemento dependiendo del tipo de contenido.

Cache-Control: max-stale=3600;

En la misma línea, podemos también forzar cada cuánto tiempo debería refrescarse este elemento, aunque tengamos los datos previos incluidos.

Cache-Control: min-fresh=600;

Validación y recarga

El tercero de los elementos que podríamos indicar es cómo es este elemento que queremos cachear y qué hacer en determinados casos.

Una opción sería la de indicar que un elemento debe volverse a actualizar una vez haya pasado la fecha de caducidad (cumpliendo las otras posibles reglas). En este caso deberemos informar que debe validarse de nuevo.

Cache-Control: must-revalidate;

En el caso contrario, es posible que tengamos algunos elementos que sabemos que nunca van a cambiar. Sobre todo si cuando subimos un elemento no lo sobrescribimos sino que lo versionamos de alguna manera, por lo que tenemos todos las versiones en ficheros distintos. En este caso esos elementos son inmutables.

Cache-Control: immutable;

Algunos casos y ejemplos

Si queremos que un elemento no se guarde en el navegador del usuario, simplemente lanzaremos esta cabecera:

Cache-Control: no-store;

Pero si queremos que, por ejemplo, un logo se almacene, y no se va a cambiar ese fichero, podríamos lanzar algo tal que así:

Cache-Control: public, max-age=2419200, immutable;

Esto por defecto almacenaría ese fichero durante 1 mes y lo utilizaría sin revalidarse.

Clear-Site-Data

En alguna ocasión necesitamos que la caché del navegador de un usuario se vacíe. ¿Cómo conseguirlo desde nuestro propio sitio web? Pues con esta cabecera podemos indicar ciertos elementos que se pueden enviar para que se eliminen.

Esta cabecera permite principalmente eliminar 3 elementos (o todos), que son la caché, las cookies o el almacenamiento (storage).

Uno de los elementos es la caché, y si queremos vaciar todo lo que haya podemos mandar la cabecera correspondiente.

Clear-Site-Data: "cache";

De la misma forma podemos eliminar todas las cookies del sitio.

Clear-Site-Data: "cookies";

Y finalmente lo que se almacena en el sistema de almacenamiento (que no es la propia caché) como el localStorage o el IndexedDB

Clear-Site-Data: "storage";

Aunque también podemos pedirle que elimine combinaciones de varios elementos.

Clear-Site-Data: "cache", "cookies";

O podemos decirle directamente que elimine todos los componentes, con un asterisco.

Clear-Site-Data: "*";

Por ejemplo, al salir (hacer logout) de una página, podríamos eliminar todo el material cacheado. Para WordPress, al menos hasta WordPress 5.7 no viene de forma nativa, por lo que se puede usar el plugin Clear Logout.

Expires

Si sabemos cuándo va a caducar un contenido en vez de informar cuánto tiempo lleva un elemento cacheado, podemos decirle directamente cuándo queremos que ese contenido desaparezca de la caché del navegador.

Este elemento, si existe el Cache-Control, queda inutilizado.

Expires: Wed, 21 Oct 2015 07:28:00 GMT

ETag

Aunque de por sí no es un sistema de caché, si que es un elemento complementario a las cachés, ya que vendría a ser un identificador único de un contenido, una especie de identificador único digital de un contenido en un momento concreto y que se suele basar en varios elementos del propio fichero, como la fecha o el tamaño (entre otras cosas).

Gracias a este sistema dará un poco igual el tiempo que un elemento esté en caché, ya que lo que se hará es validar si es el mismo elemento o no, y en caso de que el identificador de ese componente (imagen, PDF, etc…) cambie, entonces sólo en ese momento se hará la solicitud para que se vuelva a llamar y actualizar desde el servidor.

ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

Vary

Aunque en sí no es un encabezado de caché, si que ayuda a disponer de una o varias cachés según queramos definir.

La idea es que, por ejemplo, una misma URL tenga ficheros o cachés distintas según algún valor. Un ejemplo habitual suele ser el de si una página es para escritorio o para móvil, pudiendo tener unas cabeceras con este estilo:

X-Device: desktop;
Vary: X-Device;

De esta manera, por cada X-Device distinto que tengamos se generará una caché distinta en el navegador.

Hay que tener en cuenta que no todos los servidores web permiten esta normalización de datos o inyección de valores, por lo que hay que analizar caso a caso para que no se generen infinidad de cachés de un mismo fichero.

Resumen

De todos los sistemas de almacenamiento en la caché del navegador sin duda la principal que deberíamos utilizar siempre es la del Cache-Control, sobre todo cuando hablamos de elementos estáticos como CSS, JavaScript, textos (txt) o imágenes.

Para los contenidos dinámicos, dependerá mucho de si queremos tener un sistema que permita mantener elementos cacheables, sobre todo si hablamos de un sitio de alto tráfico que está saturado y preferimos mostrar elementos obsoletos que no errores del servidor.


Sobre este documento

Este documento está regulado por la licencia EUPL v1.2, publicado en WP SysAdmin y creado por Javier Casares. Por favor, si utilizas este contenido en tu sitio web, tu presentación o cualquier material que distribuyas, recuerda hacer una mención a este sitio o a su autor, y teniendo que poner el material que crees bajo licencia EUPL.