Conoce cómo funciona el browser y optimiza tu código frontend

26/Nov/2014 1027

Hace no más de 2 años que la tendencia de los usuarios de internet han visto cómo han crecido de manera indirecta las siguientes afirmaciones:

  • Los sitios han crecido en peso de sus archivos (CSS, JS, imágenes, tipografías).
  • La cantidad de usuarios que utilizan redes móviles (2G, 3G y 4G) ha crecido mucho, pero muuuucho.

Por ende:

Hay poca consciencia de que sitios pesados y redes móviles limitadas no son buenos coeficientes de una misma ecuación.

Esto debe llevarnos a una nueva manera de pensar sobre la optimización de sitios relativos al front-end. Y no sólo por los usuarios y las experiencias que puedan llevar un lento desempeño de tus sitios en sus dispositivos; recuerda que Google considera dentro de su algoritmo de posicionamiento que el tiempo de renderizado sea menor a 1 segundo, suponiendo que con 3 segundos el usuario ya se fue de tu sitio y esperando 10 segundos lo más probable es que nunca más vuelva.

En este artículo mostraré cómo funciona un browser desde que inicia el render del código de una página y con esa información algunas técnicas para aumentar la optimización de los elementos que la componen.

Tramo crítico de renderizado

Por años se consideró como velocidad de carga como la rapidez en que vemos la estructura, diseño y contenido de la página cargada. Pero luego Google definió el tramo crítico de renderizado (critical rendering path) como la secuencia de pasos que el browser toma de convertir código y recursos asociados en la vista inicial de una página web. Esto cambia la noción completamente, orientándola hacia lo esencial, lo fundamental en tu esa página para después cargar lo secundario. ¿El foco? Contenido más rápido, mayor pagerank.

A continuación mostraré los procesos que suceden cuando ingresas una URL en el browser y el servidor resuelve lo que esa URL contiene:

De nada a contenido

Básicamente lo primero que entregará un servidor será código HTML como el siguiente:

<!DOCTYPE html>
<html lang="es">
  <head>
    <title>Título</title>
    <link href="style.css" rel="stylesheet">
  </head>
  <body>
      <p>Texto <b>en negrita</b>.
      <img src="imagen.jpg">
    </p>
  </body>
</html>

Lo que hace el navegador es parsear este código dentro del DOM (Document Object Model), el que corresponde a la representación en forma de árbol del lenguaje HTML. El browser construye el DOM incrementalmente, o sea, comienza a parsear el HTML apenas el primer trozo de código es recibido y agrega nodos a la estructura del árbol tanto como sea necesario:

img1

En este punto la ventana del navegador aún no muestra nada, pero se está referenciando a un archivo style.css dentro de <head /> Nótese que los estilos de un sitio son parte crítica del renderizado dado que tienen que ser descargados apenas el parser HTML pase por <link />. Si tenemos definido como estilos básicos:

p { font-weight: normal; }
p b { display: none; }

Éstos son parseados dentro de CSSOM ó CSS Object Model, el que desafortunadamente no puede ser construido incrementalmente como el DOM debido al efecto cascada que determina la naturaleza de CSS; imagina que después de la declaración CSS anterior definieras:

p { font-weight: bold; }

Lo que causaría que sobre-escribieras la primera declaración de p {}, demostrando que se debe esperar que todo el CSS sea descargado y procesado antes podamos renderizarlo. Por ende, CSS bloquea el render hasta que la representación de CSS y HTML sean entendidos por el browser, construyendo recién en ese momento el árbol de renderizado (render tree). Esta estructura combina el DOM y CSSOM pero considerando sólo los elementos visibles:

img2

Como habrán notado, el <b> dentro de <p> no está considerado debido a que no es visible para el DOM (display: none;) mediante CSS.

Los pixeles recién aparecen luego de 2 pasos: estructura (layout) y pintura (paint). La estructura se encarga de calcular las posiciones y dimensiones de cada elemento respecto al viewport actual; ya la pintura agrega los colores, formas, sombras y demás efectos de estilo terminando de mostrar la página renderizada. Cada vez que el árbol de render cambia (por ej. mediante JavaScript) o el viewport cambia (utilizando interfaces líquidas, adaptativas ó responsive) estructura y pintado vuelven a crearse.

Estructuras líquidos/responsive tienen mayor carga en el layout/paint que estructuras adaptativas

El tramo crítico de renderizado completo se ve en el siguiente diagrama:

img3

¿Y las imágenes?

No son considerados críticas para la construcción del DOM, por lo tanto, no bloquean el renderizado de una página. Pero sí influyen y bloquean el evento Load, el que corresponde a la carga y proceso de todos los elementos considerados dentro de un HTML adicionando CSS y JavaScript. Así vemos que las imágenes deben ser siempre optimizadas pero no bloquean el tramo crítico de renderizado.

No olvidemos a JavaScript

JavaScript es otro actor que influye directamente en nuestro tramo crítico de renderizado. A partir del primer código HTML entregado, lo expandiremos agregando JavaScript:

<!DOCTYPE html>
<html lang="es">
  <head>
    <title>Título</title>
    <link href="style.css" rel="stylesheet">
  </head>
  <body>
      <p>Texto <b>en negrita</b>.
      <script>
      document.write('<h1>olakease</h1>');
      var elem = document.querySelector('h1');
      elem.style.color = 'green';
	    </script>  
      <img src="imagen.jpg">
    </p>
  </body>
</html>

Este sencillo script demuestra que cambiar el DOM puede tambien influir en el CSSOM. Mientras JavaScript agrega un nuevo elemento al DOM <h1>olakease</h1>, el parser debe parar hasta que el script sea ejecutado por completo. Luego se determina el color del elemento recién creado, lo que hace que CSSOM esté presente antes de que el script sea ejecutado.

Ahora aislemos el script llevándolo a un llamado de un archivo externo .js:

<!DOCTYPE html>
<html lang="es">
  <head>
    <title>Título</title>
    <link href="style.css" rel="stylesheet">
  </head>
  <body>
      <p>Texto <b>en negrita</b>.
      <script src="app.js"></script>  
      <img src="imagen.jpg">
    </p>
  </body>
</html>

img4

El nuevo archivo externo realiza un request adicional, pero a pesar del lugar en que lo llames dentro del HTML, siempre CSS será parseado primero. Apenas CSSOM es interpretado, el contenido del script puede ser ejecutado y solo después de esto el parser del DOM puede terminar de ser ejecutado. Es un juego de parser-render-bloqueo-render-bloqueo-parser.

Quitémosle peso innecesario al browser

Técnicas de optimización

Ahora que conocemos los conceptos, es hora de anotar cómo podemos poner algo en práctica. Hay 3 puntos claves donde puedes optimizar el tramo crítico de renderizado y que permite que el browser produzca resultados visibles con mayor rapidez.

No olvides tener en cuenta que debes utilizar estos consejos con cautela y sabiduría; hazlo con cuidado, asesórate y recuerda que no existen recetas milagrosas ni fórmulas de éxito; cada situación es particular.

Minimiza los bytes que son llamados por el servidor

Regla simple: mientras más liviano tu sitio, más rápido carga y renderiza. Sencillo. Minifica, comprime y utiliza caché en tus assets estáticos y tu HTML. No temas comprimir el código HTML removiendo espacios blancos (whitespaces) y comentarios innecesarios cuando vayas a ambiente productivo.

Minimiza el CSS que bloquea el renderizado

Recuerda que CSS bloquea al renderizado y ejecución de JavaScript, así que entregar los estilos al usuario lo más rápido posible es imperativo. Asegúrate que todas las etiquetas <link> estén dentro del <head> de tu documento HTML para que el navegador las cargue y renderice de inmediato.

Otra estrategia es disminuir el CSS que bloquea el renderizado mediante media queries. Digamos que nuestro sitio de ejemplo tiene estilos para impresión y reglas declaradas para dispositivos móviles en orientación landscape. Puedes separar el CSS en varios archivos y dejar que el browser las parsee condicionalmente:

<head>
  <title>Sitio Ejemplo</title>
  <link href="style.css" rel="stylesheet">
  <link href="print.css" rel="stylesheet" media="print">
  <link href="landscape.css" rel="stylesheet" media="orientation:landscape">
</head>

Claramente el peso de nuestro style.css será menor debido al código removido y que repartimos entre los otros 2 archivos .css, los cuales serán utilizados sólo cuando realmente necesarios. Esto no quiere decir que no serán cargados; el navegador los descarga al inicio pero en menor prioridad que el principal y en paralelo al proceso de renderizado.

Otro recurso es agregar como estilo inline (dentro del <head> mediante <style></style>) evitando que el browser realice un request al servidor por un nuevo archivo. Esta técnica se utiliza para el primer render, el que se realiza above de fold. El CSS que comanda lo que primero está en el viewport del browser, para luego continuar con el resto de la estructura mediante archivos enlazados con <link>.

<head>
  <title>Sitio Ejemplo</title>
  <script>
  header { ... }
  header nav { ... }
  header .logo { ... }
  </script>
  <link href="style.css" rel="stylesheet">
</head>

Algunas herramientas que te ayudan a calcular el CSS crítico (above the fold) y separar los estilos para servir esta vista son:

Finalmente, ¿que tal llamar tus archivos .css de forma asíncrona? Suena descabellado pero se creó loadCSS, una función JavaScript que carga CSS de forma asíncrona, especial para esos pesados @font-face por ejemplo.

Minimiza el bloqueo del parser de JavaScript

Lo misma regla ocurre con JavaScript. Si necesitas unas pocas líneas de código en el render inicial, considera agregarlos dentro de tu HTML mediante <script></script> ahorrarás descargas al servidor y por ende tendrás una respuesta más rápida al usuario.

En un caso óptimo llamas todo tu JavaScript en un mismo archivo al final de tu documento HTML. Pero en otros pasos, escribiendo código modular, puedes separar tus archivos y llamarlos asincrónicamente siempre y cuando no interactúen con el DOM ni el CSSOM:

...
    <script src="retardo.js" async></script>
  </body>
</html>

Con esto le dices al navegador que no necesita ejecutar el script en el momento en que es llamado en documento HTML. Esto también permite que el browser continúe construyendo el DOM y ejecute scripts cuando el DOM esté completo. Imagina código de Analytics, redes sociales en este retardo.js, el que no interactúa con el DOM ni el CSSOM.

Finalmente, una técnica y herramienta interesante es basket.js donde en teoría, cargas tus script críticos y recurrentes y los guardas en el localstorage del browser (HTML5), para utilizarlo desde ahí mientras dure la navegación del usuario y cuando éste regrese.

Suena bien. Manos a la obra.

Links:

Comentarios

  1. pendik evden eve nakliyat [#]

    pendik evden eve nakliyatt

    Evden eve nakliyat Pendik bölgesinde bulunan en köklü ve kaliteli nakliyat şirketleri.
    Kuşaklardan beri eşya taşıma işlemlerinde size destek sağlıyoruz.
    Sizde kaliteli bir taşıma istiyorsunuz hemen bize yazabilirsiniz.

    pendik evden eve nakliyat

  2. stromectolforte.com [#]

    ivermectin for humans for sale http://stromectolforte.com/ stromektol i̇ngiltere where to buy ivermectin

  3. cialis20walmart.com [#]

    what is the code for arthritis on both knees http://cialis20walmart.com – levitra cialis viagra

  4. ivermectin for body lice [#]

    Hi there! I know this is kind of off topic but I was wondering
    if you knew where I could get a captcha plugin for my comment form?
    I’m using the same blog platform as yours and I’m having difficulty
    finding one? Thanks a lot! http://harmonyhomesltd.com/Ivermectinum-during-pregnancy.html

  5. pendik evden eve nakliyat [#]

    pendik evden eve nakliyatt

    Evden eve nakliyat Pendik bölgesinde bulunan en köklü
    ve kaliteli nakliyat şirketleri. Kuşaklardan beri eşya taşıma
    işlemlerinde size destek sağlıyoruz. Sizde kaliteli
    bir taşıma istiyorsunuz hemen bize yazabilirsiniz.

    pendik evden eve nakliyat

  6. kyrie shoes [#]

    Thank you a lot for providing individuals with an extremely spectacular opportunity to read critical reviews from this website. It is often so nice and also stuffed with a great time for me personally and my office friends to search your site at a minimum thrice weekly to read through the newest guidance you will have. And lastly, we’re at all times satisfied for the mind-blowing opinions you give. Selected 1 points in this article are certainly the most impressive we have all had.

  7. supreme shirt [#]

    I needed to create you a little bit of remark in order to say thanks over again considering the fantastic information you have provided on this page. This has been really open-handed of you to make freely what exactly many of us would’ve supplied for an e book to get some cash for themselves, principally now that you might well have done it if you ever decided. The points additionally served as the easy way to be aware that other people online have similar keenness really like mine to know very much more with respect to this condition. I know there are many more fun situations ahead for folks who looked at your website.

  8. lebron james shoes [#]

    I intended to compose you the very little observation to help thank you very much as before just for the breathtaking knowledge you’ve shared on this website. It is so seriously open-handed with you to give unhampered what a number of people could possibly have supplied as an electronic book to get some dough on their own, most importantly considering that you might well have tried it in case you decided. Those strategies likewise worked like a fantastic way to be sure that most people have the same passion really like my very own to figure out a little more with respect to this matter. I’m certain there are many more pleasant sessions ahead for folks who scan your blog.

  9. kobe shoes [#]

    Thank you so much for providing individuals with such a terrific possiblity to read critical reviews from this site. It is usually very kind and also stuffed with fun for me and my office colleagues to visit your web site really three times per week to find out the latest secrets you have. Not to mention, I am always happy for the remarkable tips you give. Some 3 facts in this post are completely the finest I have had.

  10. curry 7 [#]

    I enjoy you because of each of your work on this site. Kim loves engaging in investigations and it’s really easy to see why. Many of us learn all of the powerful way you create powerful ideas on your web blog and even attract response from website visitors on the issue then our favorite girl is in fact understanding so much. Take pleasure in the rest of the year. You are always carrying out a glorious job.

  11. supreme clothing [#]

    I am glad for writing to let you know what a incredible encounter our girl undergone browsing your blog. She even learned such a lot of issues, which included how it is like to have a very effective giving character to let other folks easily fully grasp specified impossible subject areas. You actually did more than my desires. I appreciate you for displaying these invaluable, safe, informative and as well as cool thoughts on this topic to Emily.

  12. off white [#]

    I precisely wished to thank you very much all over again. I’m not certain what I might have sorted out in the absence of the techniques documented by you about such a subject. Completely was an absolute challenging concern for me, but finding out this well-written mode you handled it forced me to cry for fulfillment. Now i’m grateful for this support and then wish you comprehend what a great job you were doing instructing others through your site. Most likely you haven’t got to know all of us.

  13. Judyblabs [#]

    order sildenafil 100mg

  14. FritzPeerb [#]

    valium side effects 5 mg best generic viagra pharmacies reviews ed samples for free can you order cialis online does walgreens accept medi cal natural alternative for cialis

  15. modafinilvsadderall [#]

    modafinil mechanism of action https://modalertmodafinil.com/

  16. Judyblabs [#]

    ivermectin price canada

  17. GaloInvake [#]

    zithromax price in malaysia

CSSLab