Publicado
- 6 min read
Qué es el Critical Rendering Path y cómo optimizarlo
¿Qué es el Critical Rendering Path?
El Critical Rendering Path es la secuencia de fases por las que pasa el navegador para convertir el HTML, CSS y JavaScript en píxeles en la pantalla:
- Parsea el HTML en el DOM (Document Object Model).
- Parsea el CSS en el CSSOM (CSS Object Model).
- Ejecuta scripts.
- Calcula el tamaño y posición de los elementos en la pantalla.
- Renderiza la página.
Estos pasos afectan directamente al rendimiento de nuestra web, por lo que habrá cosas que tenemos que tener en cuenta si queremos optimizar este proceso.
Construyendo el DOM
El navegador recibe el HTML a través de una llamada HTTP. En cuanto lo recibe empieza a construir el DOM con esos datos.
Este DOM se construye a base de nodos, cada etiqueta de HTML equivaldría a un nodo, y elementos hijos en el HTML también serían nodos hijos en el árbol del DOM.
A mayor número de nodos, más tardará en completarse el proceso de renderizado de la página.
CSS Object Model
Mientras el DOM contiene toda la información del contenido de la página, el CSSOM contiene toda la información sobre cómo se va a ver ese contenido.
El procesado de CSS bloquea el renderizado. Es decir, que hasta que no se procese por completo no se puede continuar con futuros pasos para mostrar finalmente el contenido en la pantalla. Esto se debe a que puede darse el caso de que en un archivo de CSS se sobreescriban los estilos que se han aplicado unas líneas más arriba.
Render tree
Una vez tenemos el DOM y el CSSOM listos, estos se combinan dando como resultado el “Render tree”, que tendrá toda la información necesaria de los elementos que aparecerán en pantalla. En este árbol quedarán excluidos aquellos elementos como todo lo que tenga display: none; y sus descendientes o todo aquello que se encuentre en la etiqueta <head>.
Layout
En la fase de “Layout” se define el tamaño de los elementos del render tree y su relación con otros elementos. Este proceso es dependiente de la pantalla en la que se esté visitando la página web.
Si no se especifica, los elementos ocuparán por defecto el 100% del ancho del padre, que en algunos navegadores es un ancho fijo. Es por eso que es necesario incluir este elemento en la etiqueta <head> de nuestro documento:
<head>
<meta name="viewport" content="width=device-width" />
</head>
Cada vez que un usuario rota su dispositivo móvil, el proceso de Layout se vuelve a ejecutar, ya que los elementos y su disposición en la pantalla pueden potencialmente cambiar.
El Layout puede afectar al rendimiento de una web, ya que a mayor número de nodos, más tardará este proceso en finalizar. Un proceso de Layout lento puede ocasionar que algunas animaciones no se vean bien, además de provocar que la primera carga de la página sea más lenta.
El pintado de la página
El pintado de los píxeles en la pantalla es el último paso del proceso de renderizado. Es un paso rápido, ya que después de la primera carga (onload) ya solo se repintarán aquellas zonas de la página que hayan sufrido cambios, los navegadores ya están optimizados para evitar realizar este proceso de manera innecesaria.
Optimización del CRP
Este proceso puede optimizarse de distintas maneras, pero cada caso es único y al final lo importante es que apliques en tu proyecto aquellas medidas que mejor le vengan.
Carga de recursos críticos tan pronto como puedas
La idea es que el navegador descargue recursos como imágenes, estilos, scripts, etc que sean cruciales para la página tan rápido como sea posible, por lo que convendría poner esos elementos lo más arriba posible en el <head>.
Incluso si son scripts o estilos más pequeños pueden ir en etiquetas en línea.
<head>
<style>
.foo {
color: red;
}
</style>
</head>
Por otra parte, si lo que estás cargando es un script que modifica algún elemento del DOM, la idea sería cargarlo una vez ya se ha construido el árbol con todos sus nodos. Es en esos casos en los que sería necesario cargar ese script al final del todo en la etiqueta body.
<html>
<body>
<!-- My content -->
<script src="./path/to/my/script.js"></script>
</body>
</html>
Posponer carga de scripts
Posponer la carga de scripts que no modifican el DOM es una muy buena práctica para reducir el tiempo de carga de la web. Esto se puede hacer a través de los atributos “async” y “defer”.
Poniendo un script como async hará que este script se descargue y ejecute de manera independiente, por lo que no bloquearía el proceso de renderizado y el momento de la ejecución es arbitrario.
Un script con el atributo defer se descargará de manera asíncrona, pero respeta el orden en el que se ubica en el documento. Es también una buena forma de controlar que un script pequeño se ejecute después de un script más grande.
<html>
<body>
<script src="./very-big-file.js" async></script>
<script src="./big-file.js" defer></script>
<script src="./small-file.js" defer></script>
</body>
</html>
En el ejemplo de arriba los tres scripts se descargarán de manera asíncrona. Asumimos que el último script se descargará primero, ya que es más pequeño. El primer script se descargará y ejecutará de manera totalmente independiente, ni espera a otros elementos para que estén listos ni bloquea el proceso de renderizado. En cualquier caso, el último script se ejecutará después del segundo, ya que el atributo defer respeta el orden.
Separación de estilos con media queries
La idea sería cargar únicamente los estilos que se vayan a necesitar en pantalla, por lo que una técnica que podría ayudar a la optimización del rendimiento sería separar los estilos de la página en distintos archivos en función de si van a aplicar a móviles, tablets, escritorio, etc. En el HTML se cargarían estos archivos con media queries, evitando la carga innecesaria de estilos.
<html>
<head>
<link rel="stylesheet" type="text/css" media="screen" href="sans-serif.css" />
<link rel="stylesheet" type="text/css" media="print" href="serif.css" />
</head>
</html>
Minificar recursos
Aunque parezca una tontería, minificar los archivos puede ayudar considerablemente a la mejora del rendimiento de una página, ya que eliminando espacios en blanco, comentarios, etc puede reducir el trabajo que tiene que hacer el navegador para construir el render tree.
Conclusiones
Esto son solamente unas pocas cosas que se deben tener en cuenta para optimizar este proceso. Teniendo esto en mente es más viable poder escribir código de calidad que ya esté pensado para optimizar el Critical Rendering Path.