Volver al blog

Síguenos y suscríbete

Uso de ESI (I): Edge Side Includes sin complicaciones

Simon Wistow

Vicepresidente de Strategic Initiatives, Fastly

Nota: ESI ya está disponible para todos los clientes y no es necesario contactar con el servicio de soporte para activarlo. Para consultar la documentación y las variables, visita el Developer Hub. Si tienes alguna pregunta relacionada con el coste, ponte en contacto con el servicio de soporte.

El lenguaje de marcado Edge Side Includes (ESI) es una especificación que fue propuesta inicialmente por Akamai y Oracle, entre otras empresas. Permite a los servidores del edge (como las memorias cachés de Fastly) combinar contenido procedente de varias direcciones URL.

Los clientes de Fastly pueden utilizar ESI para almacenar en caché páginas con contenido tanto almacenable como no almacenable en caché (p. ej., información específica del usuario). Antes, la presencia de cualquier contenido no almacenable en caché en una página habría evitado el almacenamiento en caché de toda la página, aun cuando dicha parte fuera un porcentaje pequeño del contenido global. Cuantas más páginas haya con contenido no almacenable en caché, mayor será la frecuencia con que Fastly tenga que solicitar la página al origen del cliente en lugar de servir ese contenido desde la caché.

ESI permite dividir la parte no almacenable en caché en una petición independiente, lo que significa que casi la totalidad de la página puede almacenarse en la memoria caché. Se incrementa así la relación entre las peticiones almacenadas en caché y las peticiones no almacenadas en caché (lo que denominamos «proporción de aciertos de caché»). Una proporción de aciertos de caché más baja equivale a una mayor lentitud de las páginas, un incremento de costes y una menor supervivencia frente a picos de tráfico.

Caso práctico: sitio web de comercio electrónico

En un sitio de comercio electrónico típico, la página de inicio es totalmente almacenable en caché. El contenido es el mismo para todos los usuarios que accedan a la página de inicio: el logotipo, las miniaturas y el código HTML de la propia página.

Sin embargo, una vez que el usuario inicia sesión y comienza el proceso de compra, la página de inicio ya no puede almacenarse en caché porque el número de artículos en la cesta de la compra varía de un usuario a otro.

En este punto, la página de inicio debe volver a generarse para cada usuario que inicie sesión, aunque la mayoría de los objetos de la página sean los mismos para todos los usuarios. Se incrementa así la carga del origen y se ralentizan los tiempos de carga de la página, dos factores que repercuten negativamente en los sitios web.

De qué manera ayuda ESI

En lugar de incluir código pertinente para la cesta de la compra en una página, la aplicación web de la empresa puede reemplazar esa sección con una etiqueta de ESI que incorpore dicho código.

El código HTML tendría este aspecto:

<html>
<head>
<title>My Ecommerce Site</title>
</head>
<body>
<div id="content">
<div id="header">
<img src="/images/logo.jpg" />
**<esi:include src="/shopping_cart" />**
</div>
<div id="items">
<span id="item_1">...</span>
<span id="item_2">...</span>
...
<span id="item_n">...</span>
</div>
</div>
</body>
</html>

Los navegadores no detectarán en ningún caso la etiqueta de ESI (la parte <esi:include src="/shopping_cart" />) porque, cuando atraviese algún elemento que comprenda ESI (como Fastly u otros servidores web que tengan instalados plugins especiales), esa etiqueta será reemplazada por el contenido de la URL /shopping_cart.

Nota: Por motivos de rendimiento, Fastly no verifica todas y cada una de las peticiones que requieran ESI; ponte en contacto con support@fastly.com para averiguar cómo habilitar ESI en una petición.

Una vez que se haya agregado la etiqueta de ESI, la empresa de comercio electrónico necesita que algún elemento lógico en VCL o su aplicación web verifique si el usuario ha iniciado sesión. En caso afirmativo, la aplicación web devuelve el código HTML correspondiente a la cesta de la compra; en caso negativo, devuelve una cadena vacía o el código HTML correspondiente a una cesta vacía, en función de cuál deba ser la experiencia.

Dado que la etiqueta de ESI divide el contenido personalizado (la parte de la cesta de la compra) en una petición independiente, la página de inicio es ahora igual para todo el mundo, lo que significa que es totalmente almacenable en caché y que no debe volver a generarse para todos y cada uno de los usuarios. Además, Fastly podría almacenar en caché el código HTML correspondiente a la cesta de la compra por usuario: ni siquiera es necesario volver a generar el contenido personalizado cada vez, sino únicamente cuando haya cambios en la cesta.

AJAX, la alternativa

Quizás os hayáis dado cuenta de que los mismos resultados se podrían lograr con AJAX. Por ejemplo, en lugar de utilizar la etiqueta de ESI, el usuario podría utilizar un elemento span vacío y algo de código JavaScript que capture el código HTML de la cesta de la compra y reemplace el contenido del span:

<html>
<head>
<title>My Ecommerce Site</title>
**<script src="/jquery.js" />
<script>
$(document).ready(function() {
$.get("/shopping_cart", function(data){
$("#shopping_cart").html(data);
});
});
</script>**
</head>
<body>
<div id="content">
<div id="header">
<img src="/images/logo.jpg" />
**<span id="shopping cart" />**
</div>
<div id="items">
<span id="item_1">...</span>
<span id="item_2">...</span>
...
<span id="item_n">...</span>
</div>
</div>
</body>
</html>

No obstante, esto solo funciona si tratas de insertar algo en código HTML en el que ya haya código JavaScript disponible. Pero si no se dispone de código JavaScript, aquí entra en juego ESI.

Uso de ESI con código JSON

Imagínate que te interesa que un widget capture algo de código JSON en tu página. Aunque ese código JSON sea el mismo para todos los usuarios, también te interesa incluir la geolocalización de estos. Todos los elementos de la respuesta JSON pueden almacenarse en caché, excepto los datos de la ciudad del usuario:

{
"amp_volume": 11,
"other_variable": "Reticulating Splines",
"geo_data": {
"city": "New York"
}
}

Con ESI, el código tendría este otro aspecto:

{
"amp_volume": 11,
"message": "Reticulating Splines",
"geo_data": {
**<esi:include src="/geo_information" />**
}
}

El ejemplo parece un poco raro porque mezcla código JSON y XML, pero funciona a la perfección.

Es posible que en la aplicación tengas una URL que devuelva información de geolocalización. En ese caso, Fastly te dota de la capacidad de crear respuestas personalizadas en el edge (lo que en terminología de Varnish se denomina «synthetic»). Puesto que en VCL exponemos la información de geolocalización por IP del usuario, el código posiblemente tenga este aspecto:

sub vcl_recv {
if (req.url == "/geo_information") {
error 900;
}
}

sub vcl_error {
if (obj.status == 900) {
set obj.status = 200;
set obj.response = "OK";
synthetic {"{"city": ""} geoip.city {"""} {"}
"};
return(deliver);
}
}

Llegados a este punto, habrás logrado almacenar en caché el código JSON íntegramente, incluida información personalizada y dinámica que puede proporcionarse desde el edge en lugar de desde tu origen, con lo que se acelera mucho más la carga de ese widget.

Qué viene ahora

En la segunda parte de esta serie analizaré unas cuantas cosas más complicadas que puedes hacer con ESI, como crear devoluciones de llamada de JSONP sobre la marcha.