Cómo probar optimizaciones de la velocidad de un sitio con Compute
Desde el equipo de Ingeniería de Soluciones, ayudamos a los clientes a optimizar la configuración y el rendimiento de sus servicios de Fastly. Una de las optimizaciones más solicitadas es hacer que un sitio se cargue más rápido. Gracias a Compute, que sirve para compilar, probar y desplegar código en nuestro entorno informático sin servidores, podemos comparar las velocidades de antes y después sin ni siquiera cambiar el sitio web de producción. Así, podemos comprobar si las recomendaciones acelerarían la carga de la página antes de implementarlas.
Hoy mostraré un ejemplo de cómo puedes utilizar Compute para distribuir un sitio web con y sin una modificación concreta, y utilizar WebPageTest, una herramienta de rendimiento web que usa navegadores reales, para comparar el rendimiento de las dos versiones.
Ejemplo de recomendación de optimización
Para este ejemplo, analizaremos un sitio público sin clientes, web.dev, que es uno de mis favoritos para aprender. Hoy examinaremos la página Web Vitals Metrics.
Esta página incluye dos imágenes SVG que se cargan desde un tercero, lo que significa que se debe configurar una nueva conexión HTTPS para enviar las peticiones. Al realizar una prueba con WebPageTest, podemos ver las peticiones que componen la carga de la página en el gráfico en cascada:
Gráfico en cascada con los resultados de la prueba de rendimiento de la página web https://web.dev/learn-web-vitals/
La raya azul, naranja y morada de la línea 8 es el retraso que se produce al establecer la nueva conexión HTTPS. La petición de la línea 9 también espera esta conexión. Asimismo, la nueva conexión HTTPS es visible en el gráfico de conexiones de WebPageTest, donde la raya azul, naranja y morada de la línea 3 muestra el retraso a la hora de crear la nueva conexión:
Gráfico de conexiones con los resultados de la prueba de rendimiento de la página web https://web.dev/learn-web-vitals/
Abrir una nueva conexión puede llevar su tiempo en una red congestionada y de gran latencia. El tiempo necesario para enviar los archivos SVG pequeños es insignificante comparado con el tiempo que lleva establecer la nueva conexión. Si estuviéramos ante un análisis de rendimiento de un cliente, mi recomendación sería enviar todos los activos por la misma conexión que el contenido HTML, para evitar la latencia adicional provocada al crear cada nueva conexión. Pero ¿hasta qué punto serviría? Vamos a averiguarlo.
Prueba de la recomendación con Compute
Para realizar esta prueba comparativa, escribí una aplicación de Computeusando Rust. Esta aplicación transmite contenido al origen real de web.dev y modifica las respuestas HTML utilizando lol_html, una caja de Rust diseñada para modificar HTML sobre la marcha que tiene una API intuitiva basada en selectores CSS.
Las imágenes SVG también se encuentran en el origen, por lo que el navegador podría cargarlas directamente desde allí, reutilizando la conexión abierta que ya se haya utilizado para cargar el HTML y otros activos. Apunté en qué parte del HTML hacía referencia el código a estos archivos SVG y escribí el siguiente código:
let html = rewrite_str(
&beresp.into_body_str(),
RewriteStrSettings {
element_content_handlers: vec![
// <img alt="web.dev" class="web-header__logo" src="https://webdev.imgix.net/images/lockup.svg">
// <img alt class="w-masthead-path__image" src="https://webdev.imgix.net/images/collections/web-vitals.svg">
element!(r#"img[src^="https://webdev.imgix.net/"]"#, |el| {
let src = el
.get_attribute("src")
.expect("img src is required")
.replace("https://webdev.imgix.net", "");
el.set_attribute("src", &src)
.expect("unable to set img src");
Ok(())
}),
// <web-side-nav class="unresolved" logo="https://webdev.imgix.net/images/lockup.svg>"
element!(r#"web-side-nav[logo^="https://webdev.imgix.net/"]"#, |el| {
let logo = el
.get_attribute("logo")
.expect("web-side-nav logo is required")
.replace("https://webdev.imgix.net", "");
el.set_attribute("logo", &logo)
.expect("unable to set web-side-nav logo");
Ok(())
}),
],
..RewriteStrSettings::default()
},
)
.unwrap();
Desplegué la aplicación de Compute en la edge cloud de Fastly. La aplicación se cuida de ordenar a los rastreadores web que no indexen ninguna página y además les impide el acceso a menos que haya un encabezado especial x-host, que envía WebPageTest.
Probé la optimización en la línea de comandos con curl:
# web.dev using multiple connections
❯ curl -s https://instantly-striking-martin.edgecompute.app/learn-web-vitals/ -Hx-host:1 -Hx-bypass-transform:true | egrep -o 'src=[^=]+?\.svg'
src=https://webdev.imgix.net/images/lockup.svg
src=https://webdev.imgix.net/images/collections/web-vitals.svg
# web.dev using reduced connections
❯ curl -s https://instantly-striking-martin.edgecompute.app/learn-web-vitals/ -Hx-host:1 | egrep -o 'src=[^=]+?\.svg'
src="/images/lockup.svg
src="/images/collections/web-vitals.svg
¡Funciona! A continuación, probé las optimizaciones con WebPageTest configurando una prueba desde la ubicación de WebPageTest de Londres, Reino Unido (EC2), utilizando Chrome en la red 3G Fast simulada de WebPageTest. Elegí el perfil de red 3G Fast para imitar un dispositivo móvil de baja potencia en una red móvil; se trata del valor predeterminado tanto para el modo fácil de WebPageTest como para PageSpeed Insights de Google. Lo etiqueté «web.dev using multiple connections» y configuré un script avanzado:
overrideHost web.dev instantly-striking-martin.edgecompute.app
addHeader x-bypass-transform:true
navigate https://web.dev/learn-web-vitals/
Además, bloqueé los siguientes dominios para poder centrarme en el rendimiento del sitio web principal:
www.google-analytics.com www.gstatic.com
firebaseinstallations.googleapis.com
Este es el resultado de la prueba sin la transformación.
A continuación, configuré otra prueba de manera similar y la etiqueté «web.dev using reduced connections». Creé un script avanzado:
overrideHost web.dev instantly-striking-martin.edgecompute.app
navigate https://web.dev/learn-web-vitals/
Y bloqueé los mismos dominios:
www.google-analytics.com www.gstatic.com
firebaseinstallations.googleapis.com
Este es el resultado de la prueba con la transformación y esta página comparativa de pruebas muestra una comparación entre las dos.
En el gráfico en cascada sin la transformación, la línea verde discontinua representa el Largest Contentful Paint, una de las imágenes SVG, en torno a 1,75 s:
En el gráfico en cascada con la transformación, vemos que los archivos SVG se están cargando desde el mismo origen y que esta vez el Largest Contentful Paint ocurre mucho más temprano, en torno a 1,2 s:
La comparación arroja más gráficos, como el progreso visual a lo largo del tiempo, donde podemos ver que la prueba con conexiones reducidas se muestra antes:
En este vídeo comparativo de ambas pruebas en plena carga, se observa cómo la imagen de la parte superior derecha se carga mucho antes y la página termina de cargarse en 1,6 segundos en lugar de en 1,8 segundos.
Así, en este caso, hemos comprobado que la transformación sí sirve para esta página. De este modo, es posible probar una única optimización del rendimiento web con Compute para asegurarnos de que los cambios redundan en optimizaciones de verdad.