JASoft.org

El blog de José Manuel Alarcón Aguín. Programación web y mucho más...

MENÚ - JASoft: JM Alarcón

Carga diferida de imágenes en el navegador (lazy loading) de manera nativa

El tamaño y la cantidad de los recursos asociados a las páginas (imágenes, hojas de estilo, scripts...) influye mucho sobre diversos factores de nuestro sitio web. Desde la velocidad de carga de la página, hasta el ancho de banda consumido. Cuanto más rápido cargue una página mejor, y puede tener un efecto muy importante sobre el factor de conversión de la misma (cada segundo de espera adicional hace que se vaya mucha gente). El ancho de banda puede ser también dinero, tanto para nosotros, puesto que muchos servicios cloud cobran por tráfico transferido aparte de otros indicadores, como para nuestros usuarios/visitantes que pueden estar accediendo a través de un móvil o de una conexión "medida" (y al final de mes, todo lo que no necesiten pero se descargue igual, influye en la factura o le puede acabar con la tarifa plana).

Por eso,  muchos sitios web, especialmente los que hacen uso intensivo de imágenes, implementan técnicas para que sólo se cargue lo estrictamente necesario en cada momento. A estas técnicas se les suele denominar de "lazy loading", es decir, de "carga perezosa" ya que en lugar de, por ejemplo, cargar todas las imágenes sólo se cargan las estrictamente necesarias a medida que se van necesitando. Así, por ejemplo, si estamos en un post en un blog que tiene muchas imágenes, si el usuario no pasa de los primeros párrafos, las imágenes que están mucho más abajo, ocultas, no se cargan mientras no haga scroll y empiecen a ser necesarias. Con esto se ahorra mucho ancho de banda y se gana en velocidad aparente de carga.

Hasta ahora, para conseguir esto era necesario hacer programación. Existen multitud de bibliotecas JavaScript para hacer lazy loading, por ejemplo Lazysizes o muchas otras.

Google implementó en Chrome 76, este verano de 2019, un nuevo atributo para imágenes llamado loading que nos permite controlar el comportamiento de la carga de imágenes (img) y marcos internos (iframe) en las páginas. Este atributo puede tomar tres valores:

  • auto: es el comportamiento por defecto. En realidad no significa que todas las imágenes se carguen inmediatamente en el orden en el que estén en la página, sino que el navegador decide las prioridades para cargarlas en función de dónde estén colocadas en el documento, aunque las carga todas lo antes posible. Poner este valor es como no poner nada ya que, como digo, es el comportamiento por omisión.
  • lazy: ese valor es el que hace que se comporten con "carga perezosa". Es decir, sólo se cargarán si están visibles o si se acercan al área visible. ¿Qué quiere decir esto?. Pues que dependiendo del tipo de recurso que se vaya a cargar, de la velocidad de la conexión y otros factores, el navegador decide cuándo va a empezar la descarga del recurso para que esté totalmente cargado cuando llegue a la parte visible. A veces puede acertar y otras no (de modo que lleguemos a ver cómo carga alguna), pero no tenemos control sobre ello. Hay que tenerlo en cuenta, pero siempre es más acertado que lo que haga una determinada biblioteca JavaScript de las que se han usado tradicionalmente.
  • eager: es justo lo contrario a lo anterior: carga "ansiosa". Este valor lo que hace es que la imagen (o iframe) se cargue tan pronto como sea posible, aunque esté en la parte no visible de la página. ¿Pero este no es el comportamiento por defecto? Sí, en el escritorio, pero en Chrome para móviles existe un modo especial llamado "Lite Mode" que antes se llamaba "De ahorro de datos" que entre otras optimizaciones descarga algunas imágenes en diferido, y no de inmediato. Por eso, si recurso es muy importante para nosotros y queremos que esté disponible de inmediato por el motivo que sea, usando este valor lo estamos garantizando.

Por ejemplo, en una página de prueba he metido 50 imágenes aleatorias (de Lorem Picsum) de la manera convencional, sin usar el nuevo atributo. Podemos observar cómo, aunque solo hay 3 visibles, cargan todas, una detrás de otra (los text/html son redirecciones a la imagen real que se carga):

Ahora, a la misma página de prueba (ZIP, 730 bytes) le añado simplemente el atributo loading="lazy" y vemos cómo se comporta:

Observamos que sólo carga unas cuantas imágenes (más de las que están visibles, pero ni de lejos todas ellas), y a medida que empiezo a hacer scroll hacia abajo y se acercan al área visible, se van cargando las demás, que es el comportamiento que queremos.

Es importante que si la carga de las imágenes va a provocar que se haga un repintado de la página y se pueden producir efectos no deseados en el aspecto de la página, que le indiquemos las dimensiones de las imágenes con un estilo. De este modo ocuparán el espacio que les corresponde y al cargar no se modificará el flujo de la página.

Cómo digo, esto no es solo para imágenes y los iframes pueden sacar partido también al atributo. Así, si por ejemplo embebemos el típico vídeo de YouTube o Vimeo que usan un iframe para mostrarse podremos aplicarle el atributo y que sólo se cargue la vista previa de los vídeos cuando vayan a entrar en el área visible.

El soporte de este atributo por parte de los navegadores se reduce ahora mismo a los que usan Chromium como motor de renderizado, es decir, Chrome (tanto en escritorio como en móviles), Opera, Brave... y en breve también.

Microsoft Edge. Firefox, Safari (ni por supuesto Internet Explorer), y otros navegadores móviles de momento no lo soportan. Pero tampoco es un problema grave porque simplemente cargarán las imágenes de la manera convencional. Firefox tiene intención de implementarlo, pero en el momento de escribir esto no lo soporta.

Si necesitamos imperiosamente cargar de manera perezosa las imágenes en estos navegadores podemos usar un polyfill para la misma funcionalidad, o podemos utilizar alguna de las bibliotecas tradicionales (comentadas arriba) comprobando antes el soporte con un código similar a este:

if ('loading' in HTMLImageElement.prototype) {
  // Está soportado
} else {
  // NO está soportado, llamar al polyfill
}

Aunque yo me quedaría con el polyfill por ser transparente.

Se trata de un interesante añadido al arsenal del programador Web Front-End y esperemos que los demás navegadores lo incorporen pronto para que el soporte sea universal.

¡Espero que te resulte útil!

José Manuel Alarcón José Manuel Alarcón
Fundador de campusMVP.es, el proyecto de referencia en formación on-line para programadores en lengua española. Autor de varios libros y cientos de artículos. Galardonado como MVP de Microsoft desde 2004. Gallego de Vigo, amante de la ciencia y la tecnología, la música y la lectura. Ayudando a la gente en Internet desde 1996.
Descarga GRATIS mi último libro (no técnico): "Tres Monos, Diez Minutos".
Banner

Agregar comentario