soy Kseso y esto EsCSS

Carga asíncrona de Css sin bloquear la composición de la página

Traslación al español del artículo original de Keith Clark "Loading CSS without blocking render"

Carga asíncrona de Css sin bloquear la composición de la página

✎ 10
COLABORACIÓN AUTOR INVITADO
Carga de archivos Css sin bloquear la composición de la página

Lo que te dispones a leer es una traslación no fidedigna al español del artículo de Keith Clark @keithclarkcouk [Loading CSS without blocking render] publicado en su página el 30 de Marzo de 2015.
Haz el favor de consultar el original para estar al tanto de las revisiones y las actualizaciones que pueda hacer su autor.

Este artículo presenta una técnica para mostrar el contenido web a los visitantes lo más rápidamente posible mediante la descarga de forma asíncrona de las hojas de estilo para evitar que haya bloqueos en la composición de la página.

Las bases que inspiran estas técnicas no son nuevas. Filament group, por ejemplo, ha publicado contenido de calidad sobre loading CSS y fonts. He escrito este artículo para documentar mis opiniones e sobre la carga de los recursos sin que causen bloqueos.

El truco para desencadenar una descarga de estilos asíncrona es utilizar un elemento link y establecer un valor no válido para el atributo media (yo uso media="none", pero cualquier otro valor sirve). Cuando una consulta de medios se evalúa como falsa, el navegador seguirá descargando la hoja de estilo, pero no va a esperar a que su contenido esté disponible antes de dibujar la página.

<link rel="stylesheet" href="css.css" media="none">

Una vez que la hoja de estilo ha terminado de descargarse el atributo media se debe restablecer a un valor válido para que las reglas de estilo se apliquen al documento. Utilizo el evento onLoad para cambiar el valor de media a all:

<link rel="stylesheet" href="css.css" media="none" onload="if(media!='all')media='all'">

Este método de carga del CSS mostará el contenido a los visitantes mucho más rápido que el método estándar. El CSS crítico se puede servir con el enfoque habitual de bloqueo (o puede ir en línea para un máximo rendimiento) y los estilos no críticos pueden ser descargados progresivamente y aplicados tras el proceso de carga y composición (render) de la página.

Esta técnica usa javascript, pero se puede prevenir su uso en los navegadores que no lo soporten o que el usuario lo tenga deshabilitado con el elemento noscript:

<link rel="stylesheet" href="css.css" media="none" onload="if(media!='all')media='all'"> <noscript><link rel="stylesheet" href="css.css"></noscript>

Hay un efecto secundario de esta técnica. Una vez que una hoja de estilo no-bloqueante ha terminado de descargarse, el documento será redibujado para reflejar las nuevas reglas que contiene. La inyección de nuevos estilos en la página puede desencadenar reordenación de contenido [n.e.: ver repain y reflow], pero esto realmente sólo es un problema en la primera carga de la página con un caché sin imprimación. Al igual que con todas los temas relacionadas con el rendimiento, tendrás que evaluar los efectos del reflow frente a la potencial velocidad de carga.

Uso de Css no bloqueante en la carga de tipografías

Las fuentes tipográficas son un problema en la carga inicial de la página. Son un recurso bloqueante y pueden causar la desaparición del texto momentáneamente [n.e.: ver font loading, render, FOIT]. Usando esta técnica es posible descargar la tipografía en segundo plano sin causar demoras y bloqueos en la composición de la página.

<link rel="stylesheet" href="main.css"> <link rel="stylesheet" href="font.css" media="none" onload="if(media!='all')media='all'">

font.css conttendría una tipografía WOFF codificada en base64 (versión Merriweather font).

@font-face { font-family: Merriweather; font-style: normal; font-weight: 400; src: local('Merriweather'), url('data:application/x-font-woff;charset=utf-8;base64,...') }

main.css contendría todas las reglas restantes para estilizar la página, incluidas las declaraciones font-family: ...;

body { font-family: Merriweather, "Lucida Grande", ...; }

Mientras que la tipografía inicial se está descargando, se utiliza la primera fuente de reserva declarada (Lucida Grande, en este caso) que logra que el contenido de la página se muestre. Una vez que se aplica la hoja de estilo que contiene las reglas @font-face, se utilizará Merriweather. Al usar familias tipográficas con características de diseño similares a la fuente preferida, el repintado inevitable del texto será tan sutil como sean las dos fuentes.

He confrontado en Google Analytics Debugger en Chrome los dos métodos de carga (el tradicional bloqueante y éste no-bloqueador) simulando una conexión 3G. Pruebas locales dan como resultado el siguiente gráfico de red.

Observa el valor de DOMContentLoaded, con este método no bloqueador hay una ganancia de 450ms al comenzar la descarga de los recursos.

Carga de archivos Css sin bloquear la composición de la página
Gráfico de red emulando una conexión 3G. Arriba método tradicional de carga con su bloqueo. Abajo usando el método no bloqueante del post.

Implementando este método en un servidor de prueba y usando webpagetest con conexión 3G produce el siguiente cronograma:

3G timeline. Arriba bloqueo por la tipografía. Abajo sin bloqueo.

A ambos métodos les lleva 2,8 segundos renderizar por completo la página, pero el método no-bloqueo hace que se comienze un segundo antes. La misma prueba con la hoja de estilo principal en línea muestra un aumento de 0,7s cuando se utiliza CSS sin bloqueo para servir la fuente:

Carga de archivos Css sin bloquear la composición de la página
3G timeline. Con el Css principal en línea. Arriba bloqueo por la tipografía. Abajo sin bloqueo.

Esta técnica funciona bien para las tipografías pero recomiendo echar un vistazo al nuevo módulo CSS Font Loading, que ofrece mucho mayor control sobre la carga de tipografías.

Conclusión

La cargando de fuentes es un ejemplo de aplicación de esta técnica de no bloqueo, pero también podría ser utilizada para otros fines, tales como la separación de los estilos Css básicos y fundamentales de los usados vía JavaScript para mejoras.

He empezado a experimentar con la idea de separar el CSS en módulos (layout básico) y presentación (todo lo demás), lo que impediría retrasos en la carga de los aspectos vitales de la página y aplicando efectos estéticos posteriormente.

Gracias a Mathias Bynens por facilitarme una versión simplificada del evento onLoad del link

Créditos y autoría del artículo original

Keith

Keith Clark es el autor de este artículo en su versión original en inglés:
Loading CSS without blocking render publicado inicialmente en su página keithclark.co.uk
@keithclarkcouk en Twitter.
Haz el favor de consultar el original para estar al tanto de las revisiones y actualizaciones que pueda hacer su autor.

Con mis disculpas por los posibles (seguros) fallos por mala comprensión o traslación al español. Hecha con las mejores intención y con el único propósito de su difusión y conocimiento entre los usuarios de este blog.

Una pequeña prueba propia

Tras la lectura de este artículo hice unas pequeñas y muy rápidas pruebas de esta técnica en este blog recuerda que es un Blogger y como Blogger incluye los estilos mediante el elemento <style> en el propio Html del blog yo introduje esta forma asíncrona en su carga en estos elementos, tanto en los generales que van en el head como el que uso aparte y al final del body para incluir las reglas @font-face de la tipografía.

Estas son las dos conclusiones principales:

  1. En Firefox sí noté cierta mejoría tanto en el inspector del navegador como en los datos facilitados por herramientas online que evalúan estos aspectos.
  2. En Chrome el uso de esta técnica en el elemento <style> supone que no se carguen los estilos incluidos en él.