"El buen diseño es obvio. El gran diseño es transparente"
- Joe Sparano

Lazy loading nativo

4 minutos de lectura
Fecha: 9/4/2019

Haciéndome eco de la reciente publicación de Addy Osmani en su blog, nos encontramos con que dentro de poco el Chrome va a implementar una manera de conseguir hacer lazy loading nativo.

Esta es una noticia fantástica. Pero el notición sería que el atributo que van a usar fuera recogido por el estándar de HTML y lo implementaran el resto de navegadores.

Porque aunque es cierto que Chrome es el más usado, hay muchos que aun somos más de Firefox, hay otros muchos usuarios de Apple que irán con Safari, y otros que usarán Explorer o Edge.

Sin embargo bien por Google, ya que el lazy loading sobretodo cuando usas dispositivos móviles (donde el ancho de banda es algo más limitado y los datos se facturan) es muy necesario.

¿Cuándo podemos empezar a usarlo?

Según la información esperan que salga con la Versión 75 de Chrome. Hoy por hoy estamos en la 73, de manera que no vamos a tardar mucho en verlo en acción.

¿Cómo se usa?

Únicamente debemos usar un nuevo atributo llamado loading.

Este atributo lo podemos usar en los tags img e iframe, que son las etiquetas que usamos para cargar tanto las imágenes como los iframes donde incrustamos recursos externos como por ejemplo otras webs.

En el caso de las imágenes las usamos de forma masiva en las webs. De hecho normalmente suponen más del 70% de la información que el navegador necesita descargar para que veamos una pagina web.

Los iframes es menos común verlos pero son bastante críticos por el peso que pueden llegar a generar.

El ejemplo de uso que nos proporcionan es este.

<img src="celebration.jpg" loading="lazy" alt="..." />
<iframe src="video-player.html" loading="lazy"></iframe>

Como se observa asignando al atributo loading el valor lazy, ya tenemos cargado ese recurso usando lazy loading nativo.

Los valores que se propone que tenga son los siguientes:

  • lazy – para que cargue de forma diferida el recurso
  • eager – para que lo cargue inmediatamente
  • auto – para delegar la responsabilidad de determinar que es lo más adecuado en el navegador

¿Porqué usarlo?

Ya hemos hablado antes de la importancia que tienen estos recursos a la hora de cargar una web. Pero ya que en la web de referencia ponen un ejemplo lo voy a copiar aquí.

De entrada nos menciona que lo que conseguimos usando el lazy loading nativo, es lo mismo que conseguimos usando librerías Javascript como lazysizes que podeis ver aquí.

Claro si usamos esta librería nos va a funcionar en todos los navegadores, pero por contra tenemos que cargar la librería, cosa que ralentiza la página y además nos atamos a ella.

Usando el lazy loading nativo nos olvidamos de cargar ‘extras’.

Por cierto para aquellos que penséis que cargar unos cuantos kb de JS no impacta, hay otro artículo muy bueno del señor Osmani donde habla del coste de cargar Javascript.

Allí explica que no es lo mismo cargar 200kb de una imagen que 200kb de JS (No se procesan igual). Para haceros una idea.

Descripción de la imagen

Por eso tener el lazy loading nativo y poder olvidarnos de librerías de terceros supone una ventaja.

Y una vez dicho esto el ejemplo es el siguiente, tenemos una página con 211 imágenes (pensemos por ejemplo en un e-commerce).

Descripción de la imagen

En este caso ha usado lazysizes, para ver la diferencia de rendimiento, pero cuando lo hagamos en nativo será muy similar.

Sin el lazy loading hubo que descargar 10 mb de imágenes, mientras que con él, el tamaño se redujo a 250kb que es aproximadamente (40 veces menos).

En la imagen se aprecia que eso pasó porque solo hubo que cargar 2 imágenes para disponer del primer pantallazo de la página, después a medida que haces scroll se irán cargando el resto.

Cada segundo que tu página se tarda en cargar pierdes usuarios. Que en el caso de un e-commerce se traduce en ventas o en el caso de un blog en visitas.

Combinarlo para que funcione en todos los navegadores

Si bien el lazy loading nativo solo esta disponible en Chrome, en la entrada se explica como combinarlo para dar soporte al resto de navegadores.

La manera de hacerlo es preguntándole al navegador si tiene esa capacidad y en caso de no tenerla usar una librería.

<script>
if ('loading' in HTMLImageElement.prototype) { 
    // El navegador soporta 'loading'..
} else {
   // Cargamos y aplicamos un polyfill/librería de lazy-loading
}
</script>

De esta manera podemos hacer que el comportamiento sea homogéneo aunque estemos utilizando dos maneras distintas de hacerlo. Este sería el ejemplo completo:

<!-- En este caso la carga es inmediata -->
<img src="hero.jpg" alt=".."/>

<!-- Estas otras imágenes cargan de forma diferida -->
<img data-src="unicorn.jpg" loading="lazy" alt=".." class="lazyload"/>
<img data-src="cats.jpg" loading="lazy" alt=".." class="lazyload"/>
<img data-src="dogs.jpg" loading="lazy" alt=".." class="lazyload"/>

<script>
(async () => {
    const images = document.querySelectorAll("img.lazyload");
    if ('loading' in HTMLImageElement.prototype) {
        images.forEach(img => {
            img.src = img.dataset.src;
        });
    } else {
        // Importamos de forma dinámica la librería LazySizes
        const lazySizesLib = await import('/lazysizes.min.js');
        // La inicializamos (reads data-src & class=lazyload)
        lazySizes.init();
    }
})();
</script>