Vicen Moreno

Pro Googler

Follow me on GitHub

Optimizando WordPress para alto tráfico - Guía práctica desde trincheras

Cómo pasé un sitio WordPress de 2s a 300ms de carga sin cambiar de hosting

El problema 🔥

Hace unas semanas me llegó un proyecto de rescate: un WordPress recibiendo ~100k visitas/día con tiempos de carga de 2-3 segundos. El cliente estaba considerando migrar a una solución custom, pero el presupuesto no acompañaba.

Spoiler: Lo solucionamos sin cambiar el hosting ni reescribir nada.

Metodología de optimización

No se optimiza lo que no se mide. Empecé con estas herramientas:

  1. Query Monitor - Para identificar queries lentas
  2. New Relic - Para profiling de PHP
  3. GTmetrix - Para métricas del navegador
  4. Chrome DevTools - Para análisis detallado

Problema 1: Queries N+1 ❌

El culpable más común. Un bucle cargando posts que para cada uno hace queries adicionales:

// ❌ ANTES - N+1 queries
$posts = get_posts(['numberposts' => 20]);
foreach ($posts as $post) {
    $author = get_user_by('id', $post->post_author); // Query por post
    $thumbnail = get_the_post_thumbnail($post->ID); // Otra query
}
// ✅ DESPUÉS - 1 query
$posts = get_posts([
    'numberposts' => 20,
    'update_post_meta_cache' => true,
    'update_post_term_cache' => true,
]);

// Precargamos thumbnails
if ($posts) {
    $post_ids = wp_list_pluck($posts, 'ID');
    _prime_post_caches($post_ids, true, true);
}

foreach ($posts as $post) {
    // Todo está en caché ahora
    $author = get_user_by('id', $post->post_author);
    $thumbnail = get_the_post_thumbnail($post->ID);
}

Resultado: De 45 queries a 3 queries. Tiempo reducido en 400ms.

Problema 2: Object Cache inexistente 🗄️

WordPress sin object cache persistente es como conducir con el freno de mano puesto.

Instalando Redis

# En el servidor (Ubuntu)
sudo apt-get install redis-server php-redis
sudo systemctl enable redis-server
sudo systemctl start redis-server
// wp-config.php
define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);
define('WP_REDIS_TIMEOUT', 1);
define('WP_REDIS_READ_TIMEOUT', 1);
define('WP_REDIS_DATABASE', 0);

Plugin recomendado: Redis Object Cache

Resultado: Tiempo de respuesta reducido en 800ms.

Problema 3: Imágenes sin optimizar 🖼️

El sitio servía JPEGs de 3MB directamente desde uploads. Imperdonable en 2024.

Solución en múltiples frentes:

1. Conversión automática a WebP

// functions.php
add_filter('wp_generate_attachment_metadata', 'generate_webp_versions');

function generate_webp_versions($metadata) {
    $upload_dir = wp_upload_dir();
    $file_path = $upload_dir['basedir'] . '/' . $metadata['file'];

    if (file_exists($file_path)) {
        $webp_path = preg_replace('/\.(jpg|jpeg|png)$/i', '.webp', $file_path);

        $image = imagecreatefromstring(file_get_contents($file_path));
        imagewebp($image, $webp_path, 80);
        imagedestroy($image);
    }

    return $metadata;
}

2. Lazy loading nativo

WordPress 5.5+ lo incluye por defecto, pero hay que asegurarse:

add_filter('wp_lazy_loading_enabled', '__return_true');

3. CDN con Cloudflare

Configuración crítica en Cloudflare:

  • Polish: Lossless
  • Mirage: Activado
  • Auto Minify: JS, CSS, HTML
  • Brotli: Activado

Resultado: Peso de página reducido de 4.5MB a 800KB.

Problema 4: Plugins innecesarios 🔌

Auditoría de plugins instalados:

Antes: 34 plugins activos
Después: 12 plugins activos

Plugins que eliminé y cómo los reemplacé:

Plugin eliminado Reemplazo
Contact Form 7 Formulario HTML + PHP custom
WP Super Cache Redis + Nginx caching
Smush CLI optimization + imagemagick
Broken Link Checker Script cron custom

Cada plugin inactivo o innecesario añade overhead. Menos es más.

Problema 5: PHP 7.4 🐌

El servidor corría PHP 7.4. Actualizar a PHP 8.2 fue un cambio masivo.

Proceso de actualización:

# Backup primero
sudo mysqldump -u root -p wordpress > backup.sql
sudo tar -czf wordpress-backup.tar.gz /var/www/html

# Actualizar PHP
sudo add-apt-repository ppa:ondrej/php
sudo apt-get update
sudo apt-get install php8.2-fpm php8.2-mysql php8.2-redis

# Actualizar Nginx config
# Cambiar fastcgi_pass unix:/var/run/php/php7.4-fpm.sock
# Por: unix:/var/run/php/php8.2-fpm.sock

sudo systemctl restart nginx
sudo systemctl restart php8.2-fpm

Resultado: Mejora del 35% en tiempo de ejecución PHP.

Configuración Nginx optimizada 🚀

Mi config final de Nginx para WordPress:

# Cache para assets estáticos
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|webp)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

# Cache FastCGI para páginas
fastcgi_cache_path /var/cache/nginx levels=1:2
    keys_zone=WORDPRESS:100m
    inactive=60m
    max_size=1g;

location ~ \.php$ {
    fastcgi_cache WORDPRESS;
    fastcgi_cache_valid 200 60m;
    fastcgi_cache_bypass $skip_cache;
    fastcgi_no_cache $skip_cache;

    # Headers para debugging
    add_header X-Cache-Status $upstream_cache_status;
}

Resultados finales 📊

Métrica Antes Después Mejora
Time to First Byte 1.8s 180ms 90%
Fully Loaded 3.2s 1.1s 65%
Total Page Size 4.5MB 780KB 82%
Requests 127 34 73%
Database Queries 89 12 86%

Lecciones aprendidas 💡

  1. Redis es no-negociable para WordPress con tráfico real
  2. PHP 8.2 debería ser el mínimo hoy día
  3. Mide antes de optimizar - No asumas dónde está el problema
  4. Los plugins son convenientes, no gratuitos - Cada uno tiene un coste
  5. WebP es el presente, no el futuro

Herramientas recomendadas

  • Query Monitor: Debug de queries
  • Redis Object Cache: Object caching persistente
  • WP-CLI: Automatización de tareas
  • New Relic / Blackfire: Profiling avanzado
  • Cloudflare: CDN y optimización

Conclusión

WordPress puede ser rápido. Muy rápido. Pero requiere conocer cómo funciona bajo el capó y no tener miedo de optimizar.

Este proyecto pasó de estar al borde de una reescritura completa a ser perfectamente viable con WordPress. Total invertido: 3 días de trabajo.

¿Tienes un WordPress lento? Empieza por medir con Query Monitor. Te sorprenderás de lo que encuentres.

¿Preguntas? ¿Tu propia experiencia optimizando WordPress? Me encantaría conocerla.

¡Hasta la próxima! ⚡


 Anterior      Posterior

Por Vicente José Moreno Escobar el 7 de marzo de 2024
Archivado en: WordPress   PHP   Performance



Puedes disfrutar de otros artículos como éste en el archivo del sitio.