Arreglando un sitio lento de forma iterativa

El rendimiento del sitio es potencialmente la métrica más importante . Cuanto mejor sea el rendimiento, mayores serán las posibilidades de que los usuarios permanezcan en una página, lean contenido, realicen compras o simplemente cualquier cosa que necesiten hacer. Un estudio de Akamai de 2017 dice lo mismo cuando descubrió que incluso un retraso de 100 ms en la carga de la página puede disminuir las conversiones en un 7 % y perder el 1 % de sus ventas por cada 100 ms que tarda su sitio en cargarse. , lo cual, en el momento del estudio. , equivalía a 1.600 millones de dólares si el sitio se ralentizara tan solo un segundo. Los puntos de referencia de la industria de Google de 2018 también brindan un desglose sorprendente de cómo cada segundo de carga afecta las tasas de rebote.

Por otro lado, Firefox hizo que sus páginas web se cargaran 2,2 segundos más rápido en promedio y generó 60 millones más de descargas de Firefox por año. La velocidad también es algo que Google considera al clasificar la ubicación de su sitio web en dispositivos móviles. Tener un sitio lento puede dejarlo en la página 452 de los resultados de búsqueda, independientemente de cualquier otra métrica.

Con todo esto en mente, pensé que mejorar la velocidad de mi propia versión de un sitio lento sería un ejercicio divertido. El código del sitio está disponible en GitHub como referencia.

Este es un sitio muy básico creado con HTML, CSS y JavaScript simples. He tratado intencionalmente de mantener esto lo más simple posible, lo que significa que la razón por la que es lento no tiene nada que ver con la complejidad del sitio en sí o con algún marco que utilice. La parte más compleja son algunos botones de redes sociales para que las personas compartan la página.

Aquí está la cuestión: el rendimiento es más que una tarea única. Está inherentemente ligado a todo lo que construimos y desarrollamos. Entonces, si bien es tentador resolver todo de una sola vez, el mejor enfoque para mejorar el rendimiento podría ser iterativo. Determine si hay algún fruto al alcance de la mano y averigüe que podrían ser esfuerzos mayores o de largo plazo. En otras palabras, las mejoras incrementales son una excelente manera de lograr mejoras en el rendimiento. Una vez más, cada milisegundo cuenta.

En ese espíritu, lo que veremos en este artículo se centra más en los logros incrementales y menos en proporcionar una lista exhaustiva o una lista de verificación de estrategias de desempeño.

Faraón

Vamos a trabajar con Lighthouse. Es posible que muchos de vosotros ya estéis muy familiarizados con él. Incluso se ha cubierto mucho aquí en CSS-Tricks. Es un servicio de Google que audita el rendimiento, la accesibilidad, el SEO y las mejores prácticas. Voy a auditar el rendimiento de mi sitio lento antes y después de las cosas que abordamos en este artículo. Se puede acceder a los informes de Lighthouse directamente en DevTools de Chrome.

Continúe, observe brevemente las cosas que Lighthouse dice que están mal en el sitio web. Es bueno saber qué hay que resolver antes de sumergirse de lleno.

Podemos solucionar este problema por completo, ¡así que comencemos!

Mejora nº 1: redirecciones

Antes de hacer cualquier otra cosa, veamos qué sucede cuando accedemos por primera vez al sitio web. Se redirige. El sitio solía estar en una URL y ahora se encuentra en otra. Eso significa que cualquier enlace que haga referencia a la URL anterior redirigirá a la nueva URL.

Los redireccionamientos suelen ser bastante ligeros en términos de latencia que añaden a un sitio web, pero son lo primero que son fáciles de comprobar y, por lo general, se pueden eliminar con poco esfuerzo.

Podemos intentar eliminarlos actualizando donde usamos la URL anterior del sitio y apuntando a la URL actualizada para que los usuarios sean llevados allí directamente en lugar de redirigidos. Usando un inspector de solicitudes de red, veré si hay algo que podemos eliminar a través del panel Red en DevTools. También podríamos usar una herramienta, como Postman, si es necesario, pero limitaremos nuestro trabajo a DevTools tanto como sea posible en pocas ocasiones.

Primero, veamos si hay redireccionamientos HTTP o HTML. Me gusta usar Fiddler, y cuando inspecciono las solicitudes de red veo que, de hecho, hay algunas URL y redirecciones antiguas flotando.

Recientemente cambié el nombre de mi GitHub de anonrobot a kealanparr , por lo que todo es igual excepto el nombre de dominio.

Parece que la primera solicitud que atendemos es https://anonrobot.github.io/redirect-to-slow-site/antes de que HTML redirija a https://anonrobot.github.io/slow-site/. Podemos redirigir todas nuestras redirect-to-slow-siteURL a la URL actualizada. En DevTools, el inspector de red también nos ayuda a ver qué está haciendo la primera página web. Desde mi punto de vista en Fiddler se ve así:

Esto nos indica que el sitio está utilizando una redirección HTML al siguiente sitio. Voy a actualizar mi URL de referencia al nuevo sitio para ayudar a disminuir la latencia que agrega resistencia a la carga inicial de la página.

Mejora n.° 2: la ruta crítica de renderizado

A continuación, crearé un perfil del sitio con el panel Rendimiento en DevTools. Lo que más me interesa es desbloquear el sitio para que no reproduzca contenido lo más rápido posible. Este es el proceso de convertir HTML, CSS y JavaScript en un sitio web interactivo completamente desarrollado.

Comienza recuperando el HTML del servidor y convirtiéndolo en el Modelo de objetos de documento (DOM). Ejecutaremos cualquier JavaScript en línea tal como lo vemos, o lo descargaremos si es un activo externo a medida que analizamos el HTML línea por línea. También integraremos el CSS en el modelo de objetos CSS (CSSOM). El CSSOM y el DOM se combinan para crear el árbol de renderizado. A partir de ahí, ejecutamos el diseño que coloca todo lo que aparece en la pantalla en el lugar correcto antes de ejecutar finalmente Paint.

Este proceso se puede “bloquear” si tiene que esperar a que se carguen los recursos antes de ejecutarse. Eso es lo que llamamos Ruta Crítica de Renderizado , y las cosas que bloquean la ruta son recursos críticos .

Los recursos críticos más comunes son:

  • Una scriptetiqueta que está en heady no contiene un atributo async, defero.module
  • Uno link rel="stylesheet"que no tiene el disabledatributo para informar al navegador que no descargue el CSS y no tiene un mediaatributo que coincida con el dispositivo del usuario.

Hay algunos tipos más de recursos que podrían bloquear la ruta crítica de renderizado, como las fuentes, pero los dos anteriores son, con diferencia, los más comunes. Estos recursos bloquean la representación porque el navegador piensa que la página está “inacabada” y no tiene idea de qué recursos necesita o tiene. Por lo que el navegador sabe, el sitio podría descargar algo que espera que el navegador haga aún más trabajo, como cambios de estilo o color; por tanto, el sitio está incompleto para el navegador, por lo que supone lo peor y bloquea la representación.

Un archivo CSS de ejemplo que no bloquearía la representación sería:

link href="printing.css" rel="stylesheet" media="print"

El "media="print"atributo solo descarga la hoja de estilo cuando el usuario imprime la página web (porque tal vez desee darle un estilo diferente a las cosas impresas), lo que significa que el archivo en sí no bloquea la representación anterior.

Como le gusta decir a Chris, un desarrollador front-end lo sabe. Y ser consciente de lo que una página necesita descargar antes de que comience la renderización es de vital importancia para mejorar las evaluaciones de las auditorías de rendimiento.

Mejora n.º 3: desbloquear el análisis

Bloquear la ruta de renderizado es algo que podemos acelerar inmediatamente y también podemos bloquear el análisis si no tenemos cuidado con nuestro JavaScript. El análisis es lo que hace que los elementos HTML formen parte del DOM, y cada vez que encontramos JavaScript que necesita ejecutarse ahora, bloqueamos ese análisis HTML.

Parte del JavaScript de mi página web lenta no necesita bloquear el análisis. En otras palabras, podemos descargar los scripts de forma asincrónica y continuar analizando el HTML en el DOM sin demora.

La asyncetiqueta es lo que permite al navegador descargar el recurso JavaScript de forma asincrónica. La deferetiqueta solo ejecuta JavaScript una vez que se completa la construcción de la página.

Aquí existe una compensación entre incorporar JavaScript (por lo que ejecutarlo no requiere una solicitud de red) versus colocarlo en su propio archivo JavaScript (para modularidad y reutilización de código). Siéntase libre de tomar su propia decisión aquí, ya que la mejor ruta dependerá del caso de uso. El rendimiento real de aplicar CSS y JavaScript a una página web será el mismo ya sea que se trate de un activo externo o integrado, una vez que haya llegado. Lo único que eliminamos cuando estamos en línea es el tiempo de solicitud de red para obtener los activos externos (lo que a veces hace una gran diferencia).

Lo principal que pretendemos es hacer lo menos que podamos. Queremos aplazar la carga de activos y hacerlos lo más pequeños posibles al mismo tiempo. Todo esto se traducirá en un mejor resultado de desempeño.

Mi sitio lento está encadenando múltiples solicitudes críticas, donde el navegador tiene que leer la siguiente línea de HTML, esperar, luego leer la siguiente para buscar otro activo y luego esperar. El tamaño de los recursos, cuándo se descargan y si se bloquean influirán enormemente en la velocidad a la que se puede cargar nuestra página web.

Abordé esto perfilando el sitio en el panel Rendimiento de DevTools, que simplemente registra la forma en que se carga el sitio con el tiempo. Escaneé brevemente mi HTML y lo que estaba descargando, luego agregue asynccualquier script JavaScript externo que estuviera bloqueando cosas (como las redes sociales script, que no es necesario cargar antes de renderizar).

Es interesante que Chrome tiene un límite de navegador en el que solo puede manejar seis conexiones HTTP en vuelo por nombre de dominio, y esperará a que regrese un activo antes de solicitar otro una vez que esos seis estén en vuelo. Eso hace que la solicitud de múltiples activos críticos sea aún peor para el análisis de HTML. Permitir que el navegador continúe analizando acelerará el tiempo necesario para mostrar algo al usuario y mejorará nuestro análisis de rendimiento.

Mejora n.º 4: reducir el tamaño de la carga útil

El tamaño total de un sitio es un factor determinante enorme en cuanto a qué tan rápido se cargará. Según web.dev, los sitios deben aspirar a tener menos de 1.600 KB interactivos en 10 segundos. Las cargas útiles grandes están fuertemente correlacionadas con tiempos de carga prolongados. Incluso puedes considerar una carga útil grande como un gasto para el usuario final, ya que las descargas grandes pueden requerir planos de datos más grandes que cuestan más dinero.

En este momento exacto, mi sitio lento tiene la friolera de 9.701 KB, más de seis veces el tamaño ideal. Recortemos eso.

Identificar dependencias no utilizadas

Al comienzo de mi desarrollo, pensé que podría necesitar ciertos activos o marcos. Los descargué en mi página y ahora ni siquiera recuerdo cuáles se están usando realmente. Definitivamente tengo algunos activos que no hacen más que perder tiempo y espacio.

Usando el inspector de red en DevTools (o una herramienta con la que se siente cómoda), podemos ver algunas cosas que definitivamente se pueden eliminar del sitio sin cambiar su comportamiento subyacente. Encontré mucho valor en el panel Cobertura en DevTools porque mostrará cuánto código se está utilizando después de descargar todo.

Como ya hemos comentado, siempre existe un buen equilibrio cuando se trata de incorporar CSS y JavaScript frente al uso de un activo externo. Pero, en este mismo momento, ciertamente parece que el sitio está descargando más de lo que realmente necesita.

Otra forma rápida de recortar cosas es descubrir si alguno de los activos del sitio está intentando cargar 404. Esas solicitudes definitivamente se pueden eliminar sin ningún impacto negativo para el sitio, ya que de todos los modos no se cargan. Esto es lo que me muestra Fiddler:

Mirando nuevamente el informe de Cobertura, sabemos que hay cosas que se descargan pero que aún tienen una cantidad significativa de código no utilizado en camino a la página. En otras palabras, estos activos están haciendo algo, pero también están listos para hacer cosas que ni siquiera necesitamos que hagan. Eso incluye React, jQuery y Vue, por lo que se pueden eliminar de mi sitio lentamente sin ningún impacto real.

¿Por qué tantas bibliotecas de JavaScript? Bueno, sabemos que hay escenarios de la vida real en los que buscamos algo porque cumple con nuestros requisitos; pero luego esos requisitos cambian y necesitamos buscar algo más. Nuevamente, como desarrolladores front-end debemos ser conscientes y estar atentos continuamente a qué recursos son relevantes para el sitio es parte de esa conciencia general.

Comprimir, minimizar y almacenar en caché activos

El hecho de que necesitemos ofrecer un recurso no significa que tengamos que ofrecerlo en su tamaño completo, o incluso volver a ofrecer ese recurso la próxima vez que el usuario visite el sitio. Podemos comprimir nuestros activos, minimizar nuestros estilos y secuencias de comandos, y almacenar en caché los elementos de manera responsable para atender lo que el usuario necesita de la manera más eficiente posible.

  • Comprimir significa optimizar un archivo, como una imagen, a su tamaño más pequeño sin afectar su calidad visual. Por ejemplo, gzip es un algoritmo de compresión común que reduce el tamaño de los activos.
  • La minificación mejora el tamaño de los recursos basados ​​en texto, como archivos de script externos, al eliminar elementos innecesarios del código, como comentarios y espacios en blanco, con el fin de enviar menos bytes por cable.
  • El almacenamiento en caché nos permite almacenar un recurso en la memoria del navegador durante un período de tiempo para que esté inmediatamente disponible para los usuarios en cargas de páginas posteriores. Entonces, cárgalo una vez y disfrútalo muchas veces.

Veamos tres tipos diferentes de activos y cómo aprovecharlos con estas tácticas.

Activos basados ​​en texto

Estos incluyen archivos de texto, como HTML, CSS y JavaScript. Queremos hacer todo lo que esté a nuestro alcance para que sean lo más livianos posibles, por lo que los comprimimos, minimizamos y almacenamos en caché siempre que sea posible.

En un nivel muy alto, gzip funciona encontrando partes comunes y repetidas en el contenido, almacena estas secuencias una vez y luego las elimina del texto fuente. Mantiene una búsqueda similar a un diccionario para poder hacer referencia rápidamente a las piezas guardadas y colocarlas nuevamente en el lugar al que pertenecen, en un proceso conocido como gunzipping. Mira estos ejemplos comprimidos con gzip de un archivo que contiene poesía.

Estamos haciendo esto para que las descargas basadas en texto sean lo más pequeñas posible. Ya estamos haciendo uso de gzip. Lo verifiqué usando esta herramienta de GIDNetwork. Muestra que el contenido del sitio lento está comprimido en un 59,9%. Probablemente eso signifique que hay más oportunidades para hacer las cosas aún más pequeñas.

Decidí consolidar los múltiples archivos CSS en un solo archivo llamado styles.css. De esta manera, estamos limitando la cantidad de solicitudes de red necesarias. Además, si abrimos los tres archivos, cada uno contenía una cantidad tan pequeña de CSS que las tres solicitudes de red simplemente no están justificadas.

Y, mientras hacía esto, me dio la oportunidad de eliminar selectores CSS innecesarios que no se estaban aplicando en el DOM en ninguna parte, reduciendo nuevamente la cantidad de bytes enviados al usuario.

Ilya Grigorik escribió un excelente artículo con estrategias para comprimir recursos basados ​​en texto.

Imágenes

También podemos optimizar las imágenes en el sitio lento. Como muestran constantemente los informes, las imágenes son la solicitud de activos más común. De hecho, la transferencia de datos media para imágenes es de 948,1 KB para computadoras de escritorio y 902 KB para dispositivos móviles de 2016 a 2021. Eso ya es más de la mitad del tamaño ideal de 1600 KB para una carga de página completa.

Mi sitio lento no muestra tantas imágenes, pero las imágenes que sí muestra pueden ser más pequeñas. Ejecuté las imágenes a través de una herramienta en línea llamada Squoosh y logré un ahorro del 40 % (18,6 KB a 11,2 KB). ¡Eso es una victoria! Por supuesto, esto es algo que puede hacer antes de cargarlo usando una aplicación de escritorio, como ImageOptim, o incluso como parte de su proceso de compilación.

No pude ver ninguna diferencia visual entre las imágenes originales y las versiones optimizadas (¡lo cual es genial!) e incluso pude reducir aún más el tamaño cambiando el tamaño del archivo real, reduciendo la calidad de la imagen e incluso cambiando el color. paleta. Pero esas son cosas que hice en el software de edición de imágenes. Idealmente, eso es algo que usted o un diseñador harían al crear inicialmente los recursos.

Almacenamiento en caché

Hemos tocado la minificación y la compresión y lo que podemos hacer para intentar utilizarlas en nuestro beneficio. Lo último que podemos comprobar es el almacenamiento en caché.

He estado solicitando el sitio lento una y otra vez y, hasta ahora, puedo ver que siempre parece que se solicita nuevo cada vez sin ningún tipo de almacenamiento en caché. Revisé el HTML y vi que el almacenamiento en caché estaba deshabilitado aquí:

meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"

Eliminé esa línea, por lo que ahora debería poder realizarse el almacenamiento en caché del navegador, lo que ayudará a publicar el contenido aún más rápido.

Mejora n.º 5: utilice una CDN

Otra gran mejora que podemos hacer en cualquier sitio web es ofrecer todo lo posible desde una red de entrega de contenido (CDN). David Attard tiene un artículo muy completo sobre cómo agregar y aprovechar una CDN. La ruta tradicional para entregar contenido es acceder al servidor, solicitar datos y esperar a que regrese. Pero si el usuario solicita datos desde el otro lado del mundo desde donde se entregan sus datos, bueno, eso agrega tiempo. Hacer que los bytes viajen más lejos en la respuesta del servidor puede generar grandes pérdidas de velocidad, incluso si todo lo demás es increíblemente rápido.

Una CDN es un conjunto de servidores distribuidos en todo el mundo que son capaces de entregar contenido de forma inteligente más cerca del usuario porque tiene múltiples ubicaciones desde las que elegir para servirlo.

Anteriormente discutimos cómo hacía que el usuario descargara jQuery cuando en realidad no utiliza el código descargado, y lo eliminamos. Una solución fácil aquí, si realmente necesitara jQuery, es solicitar el activo desde una CDN. ¿Por qué?

  • Es posible que un usuario ya haya descargado el activo al visitar otro sitio, por lo que podemos ofrecer una respuesta en caché para la CDN. Después de todo, el 75,49% del millón de sitios principales todavía utilizan jQuery. En 2020, los navegadores (Safari, Chrome) comenzaron a realizar una “partición de caché”, lo que significa que los activos no se almacenan en caché entre diferentes sitios, por lo que se elimina este beneficio potencial. El archivo aún se almacenará en caché por sitio web.
  • No es necesario que se aleje tanto del usuario que solicita los datos.

Podemos hacer algo tan simple como tomar jQuery del CDN de Google, que ponen a disposición de cualquiera para consultarlo en sus propios sitios:

head  script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"/script/head

Eso sirve a jQuery significativamente más rápido que una solicitud estándar de mi servidor, eso es seguro.

¿Están mejor las cosas?

Si ha implementado conmigo hasta ahora, o simplemente ha leído, es hora de volver a perfilar y ver si se ha realizado alguna mejora en lo que hemos hecho hasta ahora.

Recuerde dónde empezamos:

Después de nuestros cambios:


Espero que esto haya sido útil y le anime a buscar mejoras de rendimiento incrementales en su propio sitio. Al solicitar activos de manera óptima, diferir la carga de algunos activos y reducir el tamaño general del sitio, se obtendrá un sitio funcional y completamente interactivo frente al usuario lo más rápido posible.

¿Quieres mantener la conversación? Comparto mis escritos en Twitter si quieres ver más o conectarte.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir