Optimización de rendimiento en Drupal: cachés, imágenes y lazy loading

Web cache
Solucionex
12
Nov 26

El rendimiento es uno de los aspectos que debemos tener en cuenta cuando desarrollamos y mantenemos una página web. Una web puede tener un diseño cuidado y funcionar correctamente, pero si tarda demasiado en mostrar sus contenidos, la experiencia de los usuarios se resiente.

Además, la velocidad de carga influye en el posicionamiento en buscadores. Google tiene en cuenta diferentes métricas relacionadas con la experiencia de usuario, como las Core Web Vitals, por lo que optimizar una web no consiste únicamente en conseguir que cargue rápido, sino también en que responda correctamente y muestre sus contenidos sin retrasos innecesarios.

En Drupal contamos con diferentes herramientas para mejorar el rendimiento sin necesidad de recurrir siempre a soluciones externas. En este artículo vamos a centrarnos en tres aspectos que podemos trabajar directamente desde el CMS:

  • Sistemas de caché: reducir el trabajo que Drupal necesita realizar para generar una página.
  • Optimización de imágenes: adaptar el tamaño, el formato y la calidad de los recursos gráficos.
  • Lazy Loading: evitar cargar recursos que todavía no necesita visualizar el usuario.

1. Caché en Drupal: evitar generar continuamente el mismo contenido

Drupal dispone de un sistema de caché bastante completo. Su objetivo es sencillo: almacenar resultados que ya se han calculado para evitar tener que repetir determinadas operaciones cada vez que alguien visita una página.

Por ejemplo, cuando un usuario accede a una página de una web corporativa, Drupal puede necesitar consultar información de diferentes entidades, ejecutar consultas a la base de datos, procesar bloques, aplicar permisos y construir el HTML final.

Si esa misma página recibe muchas visitas, repetir todas estas operaciones constantemente supone un trabajo innecesario. La caché permite reutilizar resultados siempre que sigan siendo válidos.

Tipos de caché disponibles en Drupal

Es importante conocer las diferencias entre los principales sistemas de caché, porque no todos trabajan sobre el mismo contenido ni resuelven los mismos problemas.

Internal Page Cache

El módulo page_cache almacena respuestas completas de páginas para usuarios anónimos. Cuando otro visitante solicita una página que puede reutilizarse, Drupal puede devolver la respuesta almacenada sin tener que reconstruirla completamente.

Es especialmente útil en webs corporativas, portales informativos y sitios donde buena parte del contenido es público y cambia con poca frecuencia.

Dynamic Page Cache

El módulo dynamic_page_cache permite almacenar partes de las páginas incluso cuando contienen elementos dinámicos o se muestran a usuarios autenticados.

Por ejemplo, podemos tener una página cuyo contenido principal es el mismo para todos los visitantes, pero que incluye un bloque personalizado con información del usuario conectado.

Drupal puede reutilizar las partes que no cambian y procesar únicamente los elementos que necesitan personalizarse. Para ello utiliza mecanismos como los placeholders y el sistema de caché del renderizado.

Render Cache

Drupal también dispone de una caché de renderizado que almacena los resultados de los elementos que genera su sistema de renderizado.

Esto permite reutilizar el resultado de bloques, entidades, campos y otros elementos sin tener que volver a procesarlos en cada petición.

Es especialmente importante en proyectos con estructuras complejas, donde una misma página puede contener numerosos bloques, vistas y componentes.

Caché de datos y backends externos

Además de las cachés anteriores, Drupal dispone de diferentes bins para almacenar datos y resultados de operaciones internas.

Por defecto, el backend habitual utiliza la base de datos, aunque podemos configurar otros sistemas según las necesidades del proyecto.

En instalaciones con bastante tráfico puede tener sentido estudiar soluciones como Redis, que permite almacenar datos en memoria, o incorporar una caché externa como Varnish para reducir las peticiones que llegan directamente a Drupal.

También podemos utilizar una CDN, como Cloudflare, para distribuir determinados recursos estáticos y servirlos desde ubicaciones más cercanas a los visitantes.

Cómo comprobar y configurar la caché en Drupal

Antes de modificar nada, conviene comprobar que los módulos de caché están habilitados. Podemos hacerlo desde la interfaz de administración o mediante Drush:

drush pml --status=enabled | grep -E 'page_cache|dynamic_page_cache'

Los dos módulos principales que debemos revisar son:

  • page_cache
  • dynamic_page_cache

Si alguno no está habilitado y queremos utilizarlo, podemos activarlo mediante:

drush en page_cache dynamic_page_cache -y

También podemos revisar la configuración de rendimiento desde:

/admin/config/development/performance

En esta pantalla encontramos opciones para configurar los tiempos de expiración de la caché y la agregación de archivos CSS y JavaScript.

Es recomendable revisar estos ajustes antes de instalar módulos adicionales. Drupal ya incorpora un sistema de caché bastante potente y, en muchos proyectos, una configuración correcta de sus funcionalidades nativas es suficiente para conseguir mejoras importantes.

Etiquetas, contextos y tiempos de vida: la parte más importante de la caché de Drupal

Una de las características que hacen especialmente interesante el sistema de caché de Drupal es que no se limita a guardar una página durante un tiempo determinado. También permite definir cuándo debe considerarse obsoleto un resultado y de qué depende su contenido.

Para ello utiliza tres conceptos fundamentales:

  • Cache Tags: identifican los datos de los que depende un elemento. Cuando esos datos cambian, Drupal puede invalidar las cachés relacionadas.
  • Cache Contexts: indican qué condiciones pueden hacer que el resultado sea diferente, como el idioma, los permisos o el usuario.
  • Cache Max-Age: establece durante cuánto tiempo puede considerarse válido un resultado.

Por ejemplo, imaginemos que desarrollamos un módulo personalizado que muestra información de un nodo. Podemos añadir metadatos de caché al render array para indicar que el resultado depende de ese contenido:

$build['content'] = [
  '#markup' => $node->label(),
  '#cache' => [
    'tags' => $node->getCacheTags(),
    'contexts' => ['languages:language_interface'],
    'max-age' => Cache::PERMANENT,
  ],
];

En este ejemplo estamos indicando que el resultado depende de las etiquetas de caché del nodo y del idioma de la interfaz. Cuando el contenido se actualice, Drupal podrá invalidar los resultados relacionados.

En un desarrollo real también debemos tener en cuenta los metadatos de caché de los elementos que utilizamos para construir el resultado. Drupal proporciona mecanismos para propagar estas dependencias, por lo que conviene evitar soluciones manuales que puedan dejar información obsoleta.

Por ejemplo, si desarrollamos un bloque que muestra información diferente según el usuario conectado, tendremos que declarar el contexto adecuado:

$build['content'] = [
  '#markup' => $message,
  '#cache' => [
    'contexts' => ['user'],
    'max-age' => Cache::PERMANENT,
  ],
];

Sin ese contexto, podríamos terminar mostrando a un usuario información que se ha generado para otro. Es uno de los errores que debemos evitar cuando desarrollamos funcionalidades personalizadas que utilizan caché.

Hay que tener en cuenta que los nodos y otros elementos de Drupal ya incorporan mecanismos de caché. Por eso, antes de añadir etiquetas manualmente, debemos comprobar si las dependencias se están propagando correctamente.

¿Cuándo tiene sentido utilizar Redis o Varnish?

No todos los proyectos necesitan incorporar sistemas externos de caché. Si tenemos una web corporativa con un volumen de tráfico moderado, probablemente podamos obtener buenos resultados utilizando las herramientas que ya proporciona Drupal.

Sin embargo, cuando el tráfico aumenta o la base de datos empieza a soportar demasiadas operaciones, podemos estudiar otras alternativas.

  • Redis: permite almacenar datos de caché en memoria y reducir determinadas operaciones sobre la base de datos.
  • Varnish: funciona como proxy inverso de caché y puede servir respuestas HTTP sin que cada petición tenga que llegar a Drupal.
  • CDN: permite distribuir recursos estáticos y, si se configura correctamente, también determinadas respuestas cacheables.

Si utilizamos un proxy inverso, también debemos configurar correctamente los ajustes de confianza en settings.php. Por ejemplo:

$settings['reverse_proxy'] = TRUE;

$settings['reverse_proxy_addresses'] = [
  '192.0.2.10',
];

La dirección del ejemplo debe sustituirse por la IP real del proxy de confianza. No debemos habilitar esta configuración a ciegas ni confiar en cualquier dirección, ya que Drupal utiliza las cabeceras recibidas para interpretar información como la IP del visitante o el protocolo de conexión.

2. Optimización de imágenes: menos peso sin perder calidad

Las imágenes suelen ser uno de los recursos que más peso aportan a una página web. Podemos tener un Drupal perfectamente optimizado a nivel de caché y seguir obteniendo malos resultados si estamos sirviendo fotografías de varios megabytes para mostrarlas en espacios de apenas unos cientos de píxeles.

El objetivo no es eliminar calidad indiscriminadamente, sino servir cada imagen con unas dimensiones y un formato adecuados al espacio donde se va a visualizar.

Utiliza Image Styles para generar imágenes adaptadas

Drupal incorpora un sistema de estilos de imagen que permite generar automáticamente diferentes versiones de una misma imagen.

Por ejemplo, imaginemos que un usuario sube una fotografía de 3000 píxeles de ancho para utilizarla como imagen de una noticia. No tiene mucho sentido servir siempre el archivo original, especialmente si en una lista de noticias vamos a mostrar una miniatura de 400 píxeles.

Podemos crear diferentes estilos de imagen desde:

/admin/config/media/image-styles

Algunos ejemplos habituales serían:

  • Thumbnail: miniaturas para listados y resultados de búsqueda.
  • Card: imágenes para tarjetas de contenido.
  • Article: imágenes para el cuerpo de una noticia o artículo.
  • Hero: imágenes principales de gran tamaño.

Al crear cada estilo podemos añadir efectos como redimensionar, recortar o ajustar las dimensiones de la imagen.

Por ejemplo, para una tarjeta de noticias podemos crear un estilo de 600 × 400 píxeles. Drupal generará una versión adaptada cuando se solicite y podrá reutilizarla posteriormente.

Después podemos seleccionar ese estilo desde el formato de visualización del campo de imagen correspondiente, en la gestión de visualización del tipo de contenido.

Es importante recordar que los estilos de imagen no modifican el archivo original subido por el usuario. Generan versiones derivadas, por lo que podemos utilizar una misma fotografía en diferentes partes de la web sin tener que subir varias copias manualmente.

Imágenes adaptables con Responsive Image

Además del tamaño, debemos tener en cuenta el dispositivo desde el que se visita nuestra web.

Una imagen de 1600 píxeles puede tener sentido en una pantalla grande, pero resulta innecesario descargarla completa en un móvil si vamos a mostrarla a 350 píxeles.

Para resolver este problema Drupal incluye el módulo responsive_image, que permite asociar diferentes estilos de imagen a un mismo campo según las condiciones de visualización.

Podemos habilitarlo mediante Drush:

drush en responsive_image -y

Después podemos acceder a:

/admin/config/media/responsive-image-style

Desde ahí creamos un estilo de imagen adaptable y definimos los estilos que se utilizarán según los diferentes breakpoints del diseño.

Por ejemplo:

  • Móviles: imagen de 480 píxeles.
  • Tablets: imagen de 768 píxeles.
  • Escritorios: imagen de 1200 píxeles.

Una vez creado, podemos utilizarlo como formato de visualización del campo de imagen correspondiente.

Drupal se encarga de generar el marcado HTML necesario para que el navegador seleccione el recurso más adecuado. Entre otras cosas, puede utilizar los atributos srcset y sizes.

Esto es especialmente útil en webs con muchas noticias, galerías, publicaciones o páginas que utilizan imágenes de gran tamaño.

WebP y AVIF: utilizar formatos de imagen más eficientes

Otro aspecto importante es el formato de las imágenes.

Durante mucho tiempo hemos utilizado principalmente JPEG para fotografías y PNG para imágenes que necesitaban transparencia. Sin embargo, actualmente existen formatos como WebP y AVIF que permiten conseguir archivos de menor tamaño manteniendo una calidad visual bastante buena.

WebP ofrece una compresión eficiente y una amplia compatibilidad con los navegadores actuales. AVIF puede conseguir reducciones de tamaño todavía mayores en determinados escenarios, aunque su codificación puede requerir más recursos.

Para incorporarlos a Drupal podemos utilizar módulos contribuidos o soluciones de optimización de imágenes integradas con el servidor.

Por ejemplo, el proyecto WebP para Drupal permite trabajar con la generación y entrega de imágenes en este formato.

También podemos utilizar herramientas externas como:

  • Squoosh, para comparar formatos, calidad y niveles de compresión.
  • CloudConvert, para convertir imágenes entre diferentes formatos.

Antes de implementar una solución debemos comprobar que el servidor dispone de las bibliotecas necesarias para procesar los formatos elegidos. En PHP, por ejemplo, la disponibilidad de WebP o AVIF depende del soporte de la biblioteca de imágenes utilizada, como GD o Imagick.

También debemos tener en cuenta que instalar soporte para WebP o AVIF no significa que Drupal vaya a convertir automáticamente todas las imágenes. Es necesario configurar el proceso de generación y entrega de los formatos correspondientes.

3. Lazy Loading: cargar las imágenes cuando realmente se necesitan

Otra técnica que podemos utilizar para mejorar el rendimiento es el Lazy Loading o carga diferida.

La idea es sencilla: si una página contiene veinte imágenes y el usuario solamente puede ver las primeras tres al entrar, no necesitamos cargar inmediatamente las otras diecisiete.

Podemos indicar al navegador que determinadas imágenes se carguen cuando se aproximen a la zona visible de la pantalla.

Esto reduce la cantidad de recursos que se descargan inicialmente y puede mejorar el tiempo de carga percibido, especialmente en páginas largas con muchas imágenes.

Utilizar loading="lazy"

Los navegadores actuales permiten implementar esta funcionalidad de forma nativa mediante el atributo loading="lazy".

Por ejemplo:

<img
  src="/sites/default/files/styles/card/public/2026-01/noticia.jpg"
  alt="Descripción de la imagen"
  loading="lazy"
  width="600"
  height="400"
>

Drupal incorpora soporte para los atributos de carga de imágenes en sus renderizados y formatos de imagen. Podemos revisar la configuración del formato de visualización del campo y las plantillas Twig utilizadas en el proyecto para comprobar cómo se está aplicando.

Si necesitamos personalizar el comportamiento desde Twig, podemos hacerlo utilizando los atributos del elemento de imagen, siempre que la plantilla esté construyendo directamente ese marcado.

No utilizar Lazy Loading en todas las imágenes

Aunque pueda parecer que aplicar loading="lazy" a todas las imágenes es una buena idea, no siempre es así.

Las imágenes principales que aparecen nada más entrar en una página deberían cargarse cuanto antes. Si aplicamos carga diferida a la imagen principal de una noticia o a una imagen destacada que ocupa buena parte de la pantalla, podemos retrasar su visualización y empeorar el LCP (Largest Contentful Paint).

Por eso, una configuración habitual sería:

  • Imagen principal o destacada: carga normal, sin Lazy Loading. Si es el elemento principal de la página, podemos estudiar el uso de fetchpriority="high".
  • Imágenes de contenido que aparecen más abajo: carga diferida mediante loading="lazy".
  • Miniaturas y galerías: carga diferida cuando no están dentro de la zona inicial visible.

También es recomendable especificar las dimensiones de las imágenes mediante los atributos width y height, o utilizar una relación de aspecto reservada mediante CSS. De esta manera, el navegador puede reservar el espacio antes de descargar el recurso y evitamos movimientos inesperados del contenido durante la carga (CLS).

Lazy Loading en iframes y otros elementos

La carga diferida no se limita a las imágenes. También podemos aplicarla a determinados elementos incrustados, como vídeos o mapas.

Por ejemplo, si tenemos un mapa de Google Maps integrado en una página, podemos añadir:

<iframe
  src="URL_DEL_MAPA"
  loading="lazy"
  title="Ubicación de nuestras instalaciones"
  width="600"
  height="450"
></iframe>

Esto evita que el navegador tenga que cargar inmediatamente el contenido del iframe cuando todavía está fuera de la zona visible.

Si necesitamos una gestión más avanzada de imágenes, galerías o elementos multimedia, podemos valorar módulos contribuidos como Blazy. Antes de instalarlos conviene comprobar qué funcionalidades necesitamos realmente y si Drupal ya ofrece una solución suficiente para nuestro proyecto.

4. Cómo comprobar si nuestra web Drupal ha mejorado

Optimizar una web sin medir los resultados es trabajar un poco a ciegas. Podemos realizar muchos cambios y, sin embargo, no conseguir una mejora apreciable en la experiencia de los usuarios.

Por eso, antes de empezar conviene medir el estado inicial de la página y repetir las pruebas después de aplicar las optimizaciones.

PageSpeed Insights

PageSpeed Insights permite analizar una URL y obtener información sobre su rendimiento tanto en dispositivos móviles como en escritorio.

Entre otras métricas, podemos consultar las Core Web Vitals:

  • LCP (Largest Contentful Paint): mide cuánto tarda en mostrarse el elemento de contenido principal.
  • INP (Interaction to Next Paint): mide la capacidad de respuesta de la página ante las interacciones del usuario.
  • CLS (Cumulative Layout Shift): mide los movimientos inesperados de los elementos durante la carga.

Lighthouse

Lighthouse permite realizar auditorías de rendimiento, accesibilidad, buenas prácticas y SEO desde las herramientas de desarrollo de Chrome.

Es especialmente útil durante el desarrollo, ya que podemos repetir las pruebas después de realizar cambios y comprobar qué aspectos siguen necesitando mejoras.

WebPageTest

WebPageTest permite analizar con más detalle cómo se carga una página, qué recursos se descargan, cuánto pesan y en qué momento aparecen.

Es una herramienta interesante cuando necesitamos investigar problemas concretos de rendimiento y no basta con consultar una puntuación general.

Herramientas de diagnóstico de Drupal

Desde Drupal también podemos consultar las opciones de rendimiento disponibles en:

/admin/config/development/performance

Y utilizar Drush para limpiar las cachés cuando sea necesario:

drush cr

Este comando reconstruye las cachés de Drupal. Es útil después de determinados cambios de configuración o desarrollo, pero no debe utilizarse como solución habitual a problemas de rendimiento: limpiar la caché obliga a regenerar los elementos almacenados y puede aumentar temporalmente el trabajo del servidor.

Drupal
Caché
Desarrollo