Optimización de Imágenes con WordPress y Astro

Por ximo

Optimización de Imágenes con WordPress y Astro

¿Por qué optimizar imágenes?

Las imágenes suelen representar el 50-70% del peso total de una página web. Una optimización adecuada mejora dramáticamente el tiempo de carga, la experiencia del usuario y el posicionamiento SEO. Al combinar WordPress con Astro, puedes lograr un rendimiento excepcional aprovechando lo mejor de ambos mundos.

Configuración inicial

Primero, asegúrate de tener instalado el plugin WPGraphQL en WordPress y configura tu cliente GraphQL en Astro:

// src/lib/wordpress.js
import { ApolloClient, InMemoryCache } from '@apollo/client';

const client = new ApolloClient({
  uri: 'https://tu-sitio.com/graphql',
  cache: new InMemoryCache(),
});

export default client;

Consultar imágenes optimizadas desde WordPress

WordPress genera automáticamente múltiples tamaños de imagen. Aprovecha esto en tus queries GraphQL:

// src/queries/posts.js
import { gql } from '@apollo/client';

export const GET_POSTS_WITH_IMAGES = gql`
  query GetPostsWithImages {
    posts {
      nodes {
        id
        title
        slug
        featuredImage {
          node {
            sourceUrl
            altText
            mediaDetails {
              width
              height
              sizes {
                name
                sourceUrl
                width
                height
              }
            }
          }
        }
      }
    }
  }
`;

Usar el componente Image de Astro

El componente nativo de Astro optimiza automáticamente las imágenes:

---
// src/components/OptimizedImage.astro
import { Image } from 'astro:assets';

const { src, alt, width, height } = Astro.props;
---

<Image
  src={src}
  alt={alt}
  width={width}
  height={height}
  format="webp"
  quality={80}
  loading="lazy"
/>

Implementación completa en una página

Aquí está todo junto en acción:

---
// src/pages/blog.astro
import { Image } from 'astro:assets';
import client from '../lib/wordpress';
import { GET_POSTS_WITH_IMAGES } from '../queries/posts';

const { data } = await client.query({
  query: GET_POSTS_WITH_IMAGES,
});

const posts = data.posts.nodes;
---

<html lang="es">
  <head>
    <title>Blog Optimizado</title>
  </head>
  <body>
    <div class="posts-grid">
      {posts.map((post) => (
        <article class="post-card">
          {post.featuredImage && (
            <Image
              src={post.featuredImage.node.sourceUrl}
              alt={post.featuredImage.node.altText || post.title}
              width={post.featuredImage.node.mediaDetails.width}
              height={post.featuredImage.node.mediaDetails.height}
              format="webp"
              quality={80}
              loading="lazy"
            />
          )}
          <h2>{post.title}</h2>
          <a href={`/blog/${post.slug}`}>Leer más</a>
        </article>
      ))}
    </div>
  </body>
</html>

<style>
  .posts-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 2rem;
    padding: 2rem;
  }
  
  .post-card img {
    width: 100%;
    height: auto;
    border-radius: 8px;
  }
</style>

Responsive images con srcset

Para imágenes que se adapten a diferentes pantallas, crea un componente reutilizable:

---
// src/components/ResponsiveImage.astro
const { image, alt, sizes = "(max-width: 768px) 100vw, 50vw" } = Astro.props;

const imageSizes = image.mediaDetails.sizes.filter(size => 
  ['medium', 'large', 'full'].includes(size.name)
);
---

<img
  src={image.sourceUrl}
  alt={alt || image.altText}
  width={image.mediaDetails.width}
  height={image.mediaDetails.height}
  srcset={imageSizes.map(size => 
    `${size.sourceUrl} ${size.width}w`
  ).join(', ')}
  sizes={sizes}
  loading="lazy"
  decoding="async"
/>

Lazy loading avanzado con IntersectionObserver

Para un control más preciso del lazy loading:

---
// src/components/LazyImage.astro
const { src, alt, width, height } = Astro.props;
---

<img
  data-src={src}
  alt={alt}
  width={width}
  height={height}
  class="lazy-image"
  loading="lazy"
/>

<script>
  const images = document.querySelectorAll('.lazy-image');
  
  const imageObserver = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const img = entry.target;
        img.src = img.dataset.src;
        img.classList.add('loaded');
        imageObserver.unobserve(img);
      }
    });
  });
  
  images.forEach(img => imageObserver.observe(img));
</script>

<style>
  .lazy-image {
    opacity: 0;
    transition: opacity 0.3s;
  }
  
  .lazy-image.loaded {
    opacity: 1;
  }
</style>

Placeholder con blur-up effect

Mejora la experiencia con un efecto de desenfoque mientras carga la imagen:

---
// src/components/BlurImage.astro
import { Image } from 'astro:assets';

const { src, alt, width, height } = Astro.props;

// Genera un placeholder pequeño y borroso
const placeholderSrc = `${src}?w=20&blur=10`;
---

<div class="blur-container">
  <img
    src={placeholderSrc}
    alt=""
    class="placeholder"
    aria-hidden="true"
  />
  <Image
    src={src}
    alt={alt}
    width={width}
    height={height}
    format="webp"
    quality={85}
    loading="lazy"
    class="main-image"
  />
</div>

<style>
  .blur-container {
    position: relative;
    overflow: hidden;
  }
  
  .placeholder {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    filter: blur(20px);
    transform: scale(1.1);
  }
  
  .main-image {
    position: relative;
    z-index: 1;
  }
</style>

Optimización en WordPress (backend)

Instala y configura estos plugins en WordPress para mejorar aún más:

1. ShortPixel o Imagify: Compresión automática de imágenes 2. WebP Express: Genera versiones WebP de todas las imágenes 3. WP Offload Media: Sirve imágenes desde un CDN como Cloudflare o AWS S3

Configuración de Astro para producción

En tu archivo de configuración de Astro:

// astro.config.mjs
import { defineConfig } from 'astro/config';

export default defineConfig({
  image: {
    service: {
      entrypoint: 'astro/assets/services/sharp'
    },
    domains: ['tu-sitio-wordpress.com'],
    remotePatterns: [
      {
        protocol: 'https',
        hostname: '**.wp.com',
      },
    ],
  },
});

Resultados esperados

Con estas optimizaciones implementadas correctamente, deberías lograr:

  • Reducción del 60-80% en el tamaño de las imágenes
  • Mejora del 40-50% en el tiempo de carga de la página
  • Puntuación de 90+ en Google Lighthouse
  • Formatos modernos (WebP/AVIF) con fallbacks automáticos
  • Experiencia visual suave con lazy loading y blur-up effects

Mejores prácticas

  1. Dimensiona correctamente: Sube imágenes al tamaño máximo que necesites, no más grandes
  2. Usa alt text siempre: Mejora la accesibilidad y el SEO
  3. Prioriza above-the-fold: Usa loading="eager" solo para imágenes visibles inicialmente
  4. Monitorea el rendimiento: Usa herramientas como WebPageTest y Lighthouse
  5. Considera un CDN: Sirve imágenes desde ubicaciones geográficas cercanas a tus usuarios

La combinación de WordPress como gestor de contenido y Astro como generador de sitios estáticos te permite crear experiencias web increíblemente rápidas sin sacrificar la facilidad de uso para editores de contenido.

Categorías

Astro WordPress