lazy load

Lazy load en WordPress para mejorar la velocidad de carga de tu web

Lazy load, carga diferida o carga perezosa es una técnica que consiste en retrasar la carga de ciertos tipos de contenido como imágenes, vídeos y frames.

Evita la carga de objetos que podrían no llegar a utilizarse. Es decir, todo este contenido que se encuentre fuera del viewport o área visible de la web cuando iniciamos la navegación, no será cargado. Sólo se cargará cuando lleguemos a él haciendo scroll.

Si tenemos mucho contenido o por ejemplo una landing page con mucho scroll, aplicar lazy load supondrá una ganancia considerable en el tiempo de carga de nuestra web.

Esta mejora es todavía más notable en dispositivos móviles, ya que el viewport o área visible inicial es menor, por lo tanto más imágenes, vídeos o frames se quedarán fuera en la carga inicial y no serán cargadas a menos que hagamos scroll.

Hace poco he utilizado ésta técnica en este blog y he pasado de estos datos antes de aplicar lazy load (según pingdom tools)

antes de lazy load

a estos otros después de aplicar lazy load:

después de lazy load

Como verás la ganancia ha sido considerable. La home de mi blog ha pasado de cargarse en 979ms, que ya era un gran tiempo, a hacerlo tan sólo en 375ms. Es decir, un pestañeo. Se ha reducido casi a un tercio el tiempo de carga después de aplicar Lazy Load.

La siguiente pregunta es ¿cómo aplico lazy load a mi WordPress? Pues hay dos respuestas: a través de plugins o incorporándolo como funcionalidad imprescindible en tu tema o plugin de utilidades.

Si te decantas por utilizar un plugin te recomiendo que pruebes Lazy Load, Rocket Lazy Load ó a3 Lazy Load.

En caso de querer incorporarlo a mano en la base de tu tema o en tu plugin de utilidades, a continuación te explicaré como lo he hecho yo.

Incorporar Lazy Load como funcionalidad imprescindible en tu tema o plugin de utilidades

Lo primero que te diré es que tuve problemas con la librería oficial de jQuery escrita por Mika Tuupola. El problema concreto es que como utilizo bootstrap y tengo un sidebar, ésta librería no me detectaba las imágenes en el sidebar (col-md-3) hasta que llegaba con el scroll hasta el final del contenido principal (col-md-9), porque realmente el sidebar se encuentra por debajo del contenido principal y es con CSS cómo se muestra en un lateral.

Así que hablando con David Navia me recomendó utilizar otra librería, concretamente esta otra de Vincent Voyer. Pero me arrojaba mensajes de error de JavaScript en consola ya que cargo todos los JS en el footer. Funcionar funciona pero no quería ver esos mensajes y tampoco cargar los scripts en el header. Así que indagando un poco más di con LazyLoad – vanilla-lazyload, que me pareció bastante sencilla de implementar y cumplía con los requisitos que buscaba.

Esta librería es JavaScript puro, la ventaja de no ser jQuery es que no es necesario esperar al document ready, por lo tanto actúa más rápidamente cuando hay que mostrar las imágenes que están dentro del área visible de la pantalla en la carga inicial.

En mi caso incorporé Lazy Load a la funcionalidad nativa de mi tema. Para conseguir esto añadí estas líneas en mi functions.php:

<?php

function my_lazyload_js() {
    wp_enqueue_script( 'my_lazy_load', get_stylesheet_directory_uri() . '/js/lazyload.min.js', array('jquery'), '' );
}
add_action( 'wp_enqueue_scripts', 'my_lazyload_js' );

function my_filter_lazyload( $content ) {
    // Don't LazyLoad if the thumbnail is in admin, a feed or a post preview.
    if ( is_admin() || is_feed() || is_preview() || empty( $content ) ) {
        return $content;
    }

    return preg_replace_callback('/(<\s*img[^>]+)(src\s*=\s*"[^"]+")([^>]+>)/i', 'my_preg_lazyload', $content);
}
add_filter( 'the_content', 'my_filter_lazyload', PHP_INT_MAX );
add_filter( 'get_avatar', 'my_filter_lazyload', PHP_INT_MAX );
add_filter( 'widget_text', 'my_filter_lazyload', PHP_INT_MAX );
add_filter( 'get_image_tag', 'my_filter_lazyload', PHP_INT_MAX );
add_filter( 'post_thumbnail_html', 'my_filter_lazyload', PHP_INT_MAX );

function my_preg_lazyload( $html ) {
    // Reemplazamos src por un pixel en blanco, y la imagen original en un data-attribute
    $img_replace = $html[1] . ' src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-original' . substr($html[2], 3) . $html[3];

    // Para imágenes responsive reemplazamos srcset por un data-attribute
    $img_replace = preg_replace('/srcset\s*=\s*"/i', 'data-original-set="', $img_replace);

    // Añadimos una etiqueta noscript con la imagen original para usuarios que tengan desactivado JavaScript
    $img_replace .= '<noscript>' . $html[0] . '</noscript>';

    return $img_replace;
}

Haremos la llamada a esta librería de la siguiente manera:

<script type="text/javascript">
    var myLazyLoad = new LazyLoad();
</script>

La primera función my_lazyload_js() sirve para encolar el JS que previamente me he descargado de github.

La segunda función, my_filter_lazyload(), es la que utilizo para añadir a los filtros the_content, get_avatar, widget_text, get_image_tag y post_thumbnail_html. Estos filtros devuelven contenidos para mostrar en pantalla.

En función my_filter_lazyload() en un primer paso pregunto si estoy en el admin, en el feed o si el contenido es vacío. En cualquiera de estos escenarios no hacemos nada, en cualquier otro caso utilizo la función preg_replace_callback que llama a my_preg_lazyload() donde se realiza una búsqueda para encontrar las etiquetas <img> y se ejecutan las siguientes acciones:

  • El atributo src de la etiqueta imagen es data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==, o lo que es lo mismo, un pixel en blanco, para que la imagen no pese nada.
  • Añadimos un atributo data-original con la URL de la imagen real.
  • Buscamos si la imagen es responsive y tiene el atributo srcset. En caso afirmativo los sustituimos por data-original-set.
  • Añadimos una etiqueta <noscript> con la imagen original para compatibilizar con navegadores que no tengan activo JavaScript.

Resumiendo, lo que hacemos es modificar todas las imágenes, sustituyendo su src por un pixel en blanco, de este modo no pesan nada. El script lo que hace es que todas aquellas imágenes que vayan apareciendo dentro del área visible por el navegador, a través de jQuery sustituye el src por el data-original, que contiene la URL de la imagen. Lo mismo con el atributo data-original-set si la imagen es responsive.

Así sólo cargaremos las imágenes si las utilizamos o dicho de otro modo, sólo si llegamos a ellas haciendo scroll, evitando cargarlas y reducir el peso de la web para el usuario si no llega a ellas.

En la página oficial de esta librería podrás encontrar multitud de ejemplos de integración, así como funcionalidades extras como definir un preloader, aplicar un efecto fadeIn, y extensiones adicionales…

Espero haberme explicado de forma clara, ¿utilizarás LazyLoad a partir de ahora en tus desarrollos?

¿Te ha resultado útil esta información? 🍺

Si este post te ha resuelto un problema, invítame a un café o a una cerveza. Con este pequeño gesto me animas a seguir escribiendo.

Comentarios

6 comentarios en Lazy load en WordPress para mejorar la velocidad de carga de tu web

  1. Hola Pablo. Gracias de antemano por el post.

    Cuando introduzco el código en el php me reduce el tiempo de caga, pero me bloque el menú y alguna que otra cosa…. supongo que será por el theme y temas de incompatibilidad, no?

  2. Hola Pablo!
    Me pregunto dónde voy a meter el JavaScript, supongo que creando una carpeta llamada js dentro del Child Theme y ahí poniendo el archivo .js y desde el functions.php llamar el archivo usando enqueue.

    Dónde va esto:
    var myLazyLoad = new LazyLoad();

    Hay algo más que me gustaría que revises.
    How to load CSS files asynchronously in WordPress (using Scott Jehl’s «loadCSS»)
    LINK: https://gist.github.com/schilke/02357d9263ed28fc1769

    He intentado usar LoadCSS como dice ese link pero no me funciona. Además hay muy pocos post acerca del correcto uso de eso con WP. Así que podrías ayudarnos si de algo sirve eso.

    1. El «var myLazyLoad = new LazyLoad();» debe ir siempre antes que el .js donde está la librería lazyload (a tu gusto si lo pones en línea, en un .js propio que cargues antes, o incluso en la misma librería en la primera línea)

      Si has tenido algún problema con la librería que comentas, mejor que preguntes directamente a su autor

      Saludos

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *:

  • El fin del tratamiento es únicamente la moderación de comentarios para evitar spam
  • La legitimación es tu consentimiento al comentar
  • No se comunicará ningún dato a terceros salvo por obligación legal
  • Tienes derecho al acceso, rectificación y eliminación de los comentarios