Diferencias entre la caché del navegador y la de la CDN
Este artículo es una adaptación de un artículo que Doc escribió para O’Reilly Radar.
La CDN es, en resumidas cuentas, un tipo de caché, lo que puede llevarte a conclusiones tentadoras como simplificar y ahorrarte el uso de la caché del navegador. Sin embargo, cada caché tiene sus ventajas y puede resultar útil en casos distintos. En este artículo, explicaré las ventajas de cada una. Además, te daré algunos consejos para combinarlas en busca de un rendimiento óptimo para tu sitio web y una experiencia excepcional para tus usuarios finales.
¿Para qué sirve romper la caché?
Este proceso, que también se conoce como «cache busting», consiste en cargar un archivo nuevo que reemplace a otro que se encuentra almacenado en la memoria caché. Romper la caché puede ser útil para evitar que el navegador recupere el archivo antiguo que se ha reemplazado.
Razones para navegar con la caché de una CDN
Las CDN ofrecen un buen desempeño en la distribución de activos, ya que trabajan a altas velocidades. Sin embargo, estas redes pierden su potencial cuando los usuarios se encuentran en lugares remotos y apenas tienen cobertura en el teléfono. De hecho, según algunos informes de Cedexis, el percentil 95 del tiempo de ida y vuelta (RTT) de todas las CDN supera con creces los 200 milisegundos en Estados Unidos. Gracias a estos datos, podemos concluir que, como mínimo, el 5 % de los usuarios tiene una experiencia lenta cuando usan tu sitio web o aplicación. Para que te hagas una idea, la media o el percentil 50 del RTT se sitúa en torno a los 45 milisegundos.
Entonces, ¿para qué molestarse en utilizar una CDN? ¿No basta con la caché del navegador? En realidad, sí que merece la pena usar una CDN. Veamos por qué:
Control: la mayoría de las CDN ofrecen la opción de purgar los activos desde su caché, lo cual es muy útil cuando se producen cambios en los activos. Por el contrario, esta opción no está presente en la caché del navegador.
La primera impresión es lo que cuenta: cuando un usuario accede por primera vez a tu sitio web, la caché del navegador no sirve para nada, ya que se encuentra en frío, sin albergar objetos útiles. Por el contrario, las CDN sí aceleran la experiencia de usuario aunque la caché del navegador esté en frío. En consecuencia, cuando dicha caché entra en calor, la velocidad de carga de las páginas consecutivas es aún más rápida.
Las ventajas geográficas de las CDN: incluso si los usuarios se encuentran en el percentil 95, un RTT de 250 milisegundos sigue siendo mejor que uno de 350. Sobre todo, si tenemos en cuenta que cada activo tendrá que hacer, como mínimo, un trayecto de ida y vuelta en una conexión abierta. No obstante, es necesario un trayecto de ida y vuelta adicional para poder abrir esta conexión. Con la seguridad de la capa de transporte (TLS, antes conocida como «SSL»), se obtienen uno o dos trayectos de ida y vuelta adicionales. Estos trayectos de más acumulan velocidad.
Las CDN son mucho más eficientes, ya que su caché se reparte entre todos los usuarios: esto significa que los servidores de origen reciben menos carga y que no tendrás que establecer por tu cuenta una capa de almacenamiento en caché en la plataforma en la que trabajes.
Uso simultáneo de la CDN y la caché del navegador
Ahora que conoces el valor que aportan una CDN y la caché del navegador por separado, veamos dos métodos para combinarlas:
Combinar un tiempo de vida (TTL) breve en la caché del navegador con purgas y TTL largos en la CDN.
Establecer un TTL largo en la CDN y en la caché del navegador, pero con busters de caché basados en la versión.
A continuación, explicaré cada método con detenimiento e incluso te contaré cómo puedes combinarlos.
TTL breves y largos
Lo ideal sería utilizar un TTL en la caché del navegador que sirva para cubrir una visita completa, pero no más. De esta manera, te aseguras de que tus usuarios disfruten de cargas más rápidas de las páginas y de que los activos no se queden obsoletos cuando los usuarios regresen más adelante. Las herramientas de análisis que utilices deberían indicarte la duración de las visitas a tu sitio. Por lo general, 5 o 10 minutos son una buena estimación.
En lo que respecta a Fastly, recomendaría establecer un TTL de un mes o un año. Y, además, configurar purgas en tu canal de despliegues, de modo que Fastly pueda distribuir nuevas versiones a la mayor brevedad. Si quieres obtener más información sobre las purgas, puedes consultar https://docs.fastly.com/guides/purging/.
Recuerda lo siguiente: no debes enviar el comando de purga hasta que estés seguro de que será el origen el que se encargue de distribuir las nuevas versiones de los activos que quieres actualizar. Lo digo porque, de lo contrario, se genera mucha confusión. Es decir, conozco casos en los que se ha enviado una purga a Fastly y Fastly ha recuperado el archivo de inmediato, antes de que terminase la sincronización con los servidores de origen.
Te recomiendo que utilices el encabezado Cache-Control
en la respuesta de origen para configurar el TTL en la caché del navegador. Después, para configurar el TTL en Fastly, te aconsejo usar el encabezado Surrogate-Control
o la opción de anular.
Aquí tienes un ejemplo:
Cache-Control: max-age=600
Surrogate-Control: max-age=31536000
En el ejemplo anterior, el encabezado Cache-Control dará instrucciones al navegador para almacenar en caché durante 10 minutos; y a Fastly para hacerlo durante un año. En lo que respecta al encabezado Surrogate-Control
, desaparece antes de que la respuesta se envíe al cliente. Es decir, ese detalle de la implementación queda oculto para los usuarios. Si te interesa, puedes consultar nuestra documentación para obtener más información sobre cuáles son los encabezados que te pueden servir para controlar los TTL con Fastly.
Busters de caché basados en la versión
Si se usan con cautela, los busters de caché pueden mejorar el almacenamiento en caché. Un buster de caché no es más que un nuevo parámetro de cadena de consulta que se agrega a una URL. Mientras que los servidores web y la mayoría de los servidores de aplicaciones se limitan a ignorar los parámetros de cadena de consulta que no les interesan, las cachés deben aceptar que cualquier diferencia que se produzca en la cadena de consulta influirá en el resultado. Y, por supuesto, aquí también entran las cachés de los navegadores. Por lo tanto, aunque el servidor devuelva la misma respuesta, los navegadores tendrán que considerar los siguientes objetos como únicos y diferenciados:
https://www.example.com/css/main.css, https://www.example.com/css/main.css?cb=foo
y https://www.example.com/css/main.css?foo=bar
Supongamos que tu aplicación se encuentra en la versión 133. En este caso, tu aplicación enlazaría con https://www.example.com/css/main.css?v=133
en lugar de con https://www.example.com/css/main.css
. Cuando pases a la versión 134, tu aplicación enlazaría con https://www.example.com/css/main.css?v=134
. Así, el navegador tendría que capturar la nueva versión de main.css, incluso si tuviese una copia sin caducar.
Lo más habitual es usar uno de estos tres métodos: un hash (corto) del contenido del archivo, un número de compilación o un hash de confirmación.
Si entramos en los gustos personales, mi favorito es el hash del contenido del archivo porque el buster de caché solo cambia cuando se modifica el contenido. Pasa lo contrario con los números de compilación o los hash de confirmación: el buster de caché cambia siempre que se produzca algún cambio en el contenido. Sin embargo, quizás sea más sencillo utilizar el número de compilación o el hash de confirmación porque todas las URL de los activos que hay en tu sitio deben incluir el buster de caché.
La desventaja que tiene este método es que tienes que actualizar todas las URL de los activos cada vez que se realice un cambio. Lo bueno es que puedes almacenar los activos en caché en el navegador con TTL de bastante duración. Y, aun así, puedes especificar que el navegador capture los activos nuevos cuando su caché esté desactualizada.
La clave: combinar métodos
Podrías plantearte almacenar en caché también todas tus páginas HTML, ya que la CDN de Fastly te permite purgar contenido caducado en tan solo 150 milisegundos. De todas formas, no te aconsejo utilizar busters de caché en las URL de las propias páginas. Ni siquiera si rediseñas tu sitio con busters de caché para activos como imágenes, hojas de estilo y JavaScript: algunos motores de búsqueda como Google te penalizarán por tener cadenas de consulta en las URL de las páginas.
Prueba a usar las técnicas de TTL breves y largos a la hora de almacenar en caché tus páginas. Y, para los activos que las utilizan, usa mejor los busters de caché.
Aspectos avanzados: la revalidación
Una ventaja interesante de usar la caché del navegador es que los navegadores conservan los objetos, aunque estén caducados, y envían encabezados de revalidación adicionales en sus peticiones. Si no ha habido cambios en el objeto incluido en la petición, la CDN suele responder con un estado 304 Not Modified
sin cuerpo. Este tipo de respuesta le indicaría al navegador que puede usar el objeto caducado y, de manera opcional, proporcionar un nuevo TTL.
Cada vez que una petición recibe una respuesta 304, sigue siendo necesario que realice un trayecto de ida y vuelta para completarse. Sin embargo, si el cuerpo de la respuesta no está presente, se ahorra bastante ancho de banda. Esto beneficia a los usuarios que tienen una conexión lenta y, además, podría traducirse en ahorros en tu cuota mensual de CDN.
Para que la revalidación funcione, solo tienes que garantizar que tu origen incluya un encabezado Last-Modified
o ETag
en las respuestas que emite. Por suerte, la mayoría de los servidores web ya incluyen encabezados Last-Modified
y ETag
en cualquier archivo estático que distribuyen desde el disco. Mientras que el valor del encabezado Last-Modified
se basa en la hora de modificación del archivo, el valor del encabezado ETag
(en Apache) se basa en la hora de modificación, el número de inodo y el tamaño.
Cuando un navegador identifica en su caché uno de esos dos encabezados o ambos a la vez en un objeto caducado, agrega un encabezado If-Modified-Since
con el valor de Last-Modified
y agrega un encabezado If-None-Match
con el valor de ETag
. Para considerar un objeto como no modificado, se han de cumplir las siguientes condiciones: a) Los valores de If-None-Match
y ETag
son idénticos. b) El valor de If-Modified-Since
coincide con el valor de Last-Modified
o es posterior a este.
Si cuentas con un único servidor web para tus activos estáticos, lo más probable es que la revalidación ya te funcione de manera predeterminada.
Por el contrario, si tienes varios servidores web por motivos de redundancia y estos tienen almacenamiento local en lugar de compartido, se podría estar provocando un fallo aleatorio de revalidación. No es posible garantizar que a un archivo específico se le asigne el mismo número de inodo en cada servidor web. Eso quiere decir que cada encabezado ETag que se genere para el archivo variará según el servidor. Asimismo, la mayoría de los scripts de despliegue no conservan la hora de modificación cuando se copian archivos, por lo que el encabezado Last-Modified
también cambiará.
Lo anterior es negativo por dos motivos. Primero, cuando Fastly se comunica con tu origen, podría malgastarse mucho ancho de banda innecesario si se ejecutan respuestas completas en lugar de respuestas 304. Segundo, Fastly podría acabar teniendo valores diferentes para ETag
y Last-Modified
repartidos en distintos servidores. A su vez, ello implicaría que los navegadores podrían recibir respuestas completas e innecesarias originadas a partir de una discrepancia de valores porque no hay garantía de que los navegadores vuelvan a comunicarse con el mismo servidor en cada petición.
Si en tu caso hay varios servidores web con almacenamiento local y quieres hacer un uso óptimo de la revalidación, aquí va mi consejo: desactiva ETag
y deja solamente activado Last-Modified
. Luego, asegúrate de que el script de despliegue conserve la hora de modificación cuando se copien archivos.
Si usas un proveedor de servicios en la nube como Google Cloud Storage o Amazon S3, ten en cuenta que el encabezado ETag
ya debería venir preconfigurado como hash del contenido. Por eso, el almacenamiento en la nube se considera uno de los mejores orígenes para Fastly, ya que ETag
no cambia cuando se vuelve a cargar el mismo archivo.
Más información
Espero que este artículo te haya ayudado a sacar el máximo partido a la caché del navegador y a la de la CDN. Si te interesa poner a punto tus mediciones de rendimiento (y llevar al máximo el rendimiento de tu CDN), no te pierdas estos artículos de Hooman Beheshti, VP of Technology de Fastly: «La verdad tras la proporción de aciertos de caché» y «Proporción de aciertos de caché en el edge».