Apuntes sobre WPO — Optimizando el Critical Rendering Path

☞ Minguez
6 min readOct 19, 2023

--

Estas son las notas que curso de Web Performance Optimization de Udacity que ha sido publicado en Youtube y ahora forma parte del programa “Front-End Developer”. Para que no se atragante demasiado el articulo lo he dividido en dos post. Puedes leer el articulo previo en “Apuntes sobre WPO — Como trabaja el navegador

Fewer bytes… faster renders

Optimizando el DOM

La parte mas compleja de optimizar es la creación del DOM y del CSSOM porque son los que hacen que la renderización sea mas lenta. Hay que intentar que el HTML se sirva los mas rápido posible y que sea lo mas pequeño.

Para conseguirlo estos serian los pasos a seguir:
1. Minificamos
2. Comprimimos
3. Uso del cache

Estos son una serie de artículos sobre estos aspectos para que puedas profundizar.

Minificar recursos
Optimización de la codificación y el tamaño de transferencia de recursos basados en texto
Evita solicitudes de red innecesarias con la caché HTTP

Desbloqueando CSS

why wait on styles you don’t need?

Intentaremos no tener CSS innecesario o que no usemos porque una vez que se ha creado el CSSOM, la página se puede empezar a renderizar, recuerda que no se crea cuando este disponible el DOM.

Con la herramienta “coverage” de las devtools de Chrome puedes ver que CSS no se usa y por tanto, a priori, no seria necesario. Hay que tener cuidado cuando recortes CSS que no se use porque puede ser que parte de esos estilos esten a la espera, como por ejemplo los :hover de botones y enlaces. Para este proceso es necesario hacer un análisis manual dado que los script automáticos no pueden saber que se va a usar.

Puedes profundizar un poco mas en el articulo sobre Coverage: Find unused JavaScript and CSS

Desbloquear CSS con Media Queries

Una optimización sencilla para el CSS que no se usa es hacer una separación de media queries. Es decir, crear un archivo CSS para los estilos que se usan en la carga inicial y otros archivos CSS para los estilos que se usan en otros dispositivos o en otras situaciones bajo condiciones especiales, por ejemplo @media o @support. De esta forma el navegador solo cargara el CSS que necesita en cada momento.

Con esta diferenciación aunque el navegador se descargue todos los archivos solo usara los que están en el rango de la media query evitando bloqueos de CSS.

<link rel="stylesheet" href="style.css">
<link rel-"stylesheet" href="style-print.css" media = "print">

Si pensamos en el ejemplo de código anterior, aunque el navegador si se baja la hoja de medios para impresión “print” esta no bloqueara el renderizado. La hoja “style.css” al tener menos reglas, pesa menos y el navegador no procesara tantos elementos para crear los nodos. Es un ejemplo muy simple, pero podemos separa “landscape y portrait” o “max-device-width” como por ejemplo: media=”screen and (min-width: 80rem)”

Puedes profundizar con los artículos CSS que bloquea la representación, Prioritize Critical CSS y uso de media queries.

JavaScript y el Critical Rendering Path

Todas las cosas que pueden bloquear el renderizado de la página

Lo primero es como pasa con el HTML y el CSS esMinificar, Comprimir y Cachear JS no se iba a librar de esto pero ademas la ejecución del JS bloquea el proceso de Parser del DOM.

Captura del curso donde se ilustra el tiempo de bloqueo de la respuesta a la petición de un archivo JS

Al incluir un <script> en el HTML, este bloqueara la evaluación del HTML de manera que el navegador no podrá continuar con el DOM hasta que no se complete la petición del archivo, se evalúe y ejecute el JS por este motivo incluimos el JS al final de la página, antes del cierre del </body> para prevenir bloqueos previos en la creación del DOM.

Si incluimos el JS en linea “no bloqueamos” con la petición pero no podemos reutilizar el código entre páginas por lo cual no es practico por eso es recomendable usar un archivo externo.

Podemos incluir el JS especifico en cada página de esta manera podemos mejorar pero aun así podemos tener bloqueos.

Captura del curso donde ilustra el bloqueo de la ejecución del JS en la página hasta que no se construya el CSSOM.

La respuesta del CSS en este caso bloquea la ejecución del JS dado que necesitamos tener el CSSOM para que navegador ejecute el JS y aplicar cambios. Si ejecutara el JS antes de recibir el CSS las reglas introducidas en el JS quedarían invalidadas al evaluar el CSS y crear el CSSOM.

Async JavaScript

El JS que no modifique el DOM o el CSSOM y por tanto no debería bloquear el pintado de la página podemos usar un evento del navegador.

El navegador lanza un evento cuando completa la carga, entonces le podemos decir que ejecute los comandos JS en ese momento, de este modo optimizamos como con `Window: load event` código JS como puede ser por ejemplo el de las analíticas . Para mas información del evento Window: load event.

Otra opción es usar el parámetro “async” en la etiqueta, esta tiene dos características, la primera es que le indica al explorador que no debe bloquear la construcción del DOM y tampoco bloqueara el CSSOM miestras se descarga. La segunda es que con `async` una vez descargado si se ejecuta el JS.

También tenemos el atributo defer que se puede agregar a la etiqueta del script y le indica al analizador de JS que debe esperar para ejecutar el código hasta que se cargue el documento.

async & defe

  • <script> (sin parametros): el análisis HTML se detiene, se descarga el archivo (si es un script externo), se ejecuta el script y después se reanuda el análisis HTML.
  • <script async>: el script se descarga de forma asíncrona, es decir, sin detener el análisis HTML, pero una vez descargado, si se detiene para ejecutar el script. Tras la ejecución se reanuda el análisis HTML. Sigue existiendo un bloqueo en el renderizado pero menor que con el comportamiento normal. No se garantiza la ejecución de los scripts asíncronos en el mismo orden en el aparecen en el documento.
  • <script defer>: el script se descarga de forma asíncrona, en paralelo con el análisis HTML y además su ejecución es diferida hasta que termine el análisis HTML. No hay bloqueo en el renderizado HTML. La ejecución de todos los scripts diferidos se realiza en el mismo orden en el que aparecen en el documento.

Ademas tenemos el atributo type=”module” para cargar un módulo ES que se comporta como defer.

Captura donde ilustra la diferencia entre async y defer en una linea de tiempo

Analiza el rendimiento de la ruta de representación crítica — Patrones de rendimiento
El elemento SCRIPT

Estrategia general de optimización

Hay muchas reglas y factores a tener en cuenta pero en realidad hay tres puntos donde ubicar la mayoría de ellas.

  1. Reducir la cantidad de datos que hay que recibir. Para ello debemos de minificar, comprimir y cachear los archivos y esto es aplicable a HTML, CSS y JS
  2. Reducir el uso de recursos que bloqueen el renderizado, principalmente CSS. Para ello separaremos CSS según las media queries para reducir el bloqueo y/o usaremos CSS inline de lo mas significativo.
  3. Reducir los bloqueos en el proceso de parseado, principalmente JS. El uso de defer o de asign como atributos del script en los JS para reducir bloqueos.

Con estos tres factores, primero reduciremos los bytes a recibir para que sea mas rápida la transferencia y el navegador inicie antes el procesado de los datos. Y por otro lado intentamos eliminar los archivos de la ruta critica de renderización. Y por ultimo todo ello intenta acortar la longitud del CRP, esto lo hacemos midiendo las veces que el navegador hace solicitudes para recoger toda la información. Se recomienda tener menos de 14 kilobytes.

Captura del curso donde se analiza la longitud del CRP

Para mejorar este ejemplo simple, lo mejor seria incluir el JS y el CSS en linea y nos ahorrariamos las peticiones. Como esto no es recomendable si se usa en varias páginas, dado que no podremos cachear y reutilizar el código, lo que podemos hacer es dividir el CSS en diferentes archivos según las media queries para que tarde menos en descargar el CSS y construir el CSSOM y ademas usaremos async para el JS y que su descarga no bloquee la construcción.

How the Browser Pre-loader Makes Pages Load Faster

Siguientes pasos

Para seguir profundizando tenemos el libro online High Performance Browser Networking y desde hace poco tenemos disponible la propieaded CSS content-visibility: la nueva propiedad CSS que aumenta el rendimiento de renderizado.

--

--