Core Web Vitals de WordPress: soluciones reales para LCP/INP/CLS

¿Te fue útil?

Los Core Web Vitals no fallan educadamente. Fallan el día del lanzamiento, durante una campaña o justo después de que firmaste un «SLA de rendimiento» que no negociaste. Y, por alguna razón, siempre es culpa de WordPress—hasta que mides la pila y descubres que en realidad es tu tema, tus plugins, tu servidor, tu CDN y las 14 etiquetas de marketing que te dijeron que eran «no negociables».

Si quieres que LCP, INP y CLS se comporten, deja de perseguir consejos aleatorios de «velocidad» y empieza a tratar tu sitio como un sistema de producción: instrumentarlo, perfilarlo, eliminar incertidumbres y enviar cambios que aguanten tráfico real.

Qué significan realmente LCP/INP/CLS en una pila WordPress

LCP: “¿Qué tan rápido apareció lo principal?”

LCP (Largest Contentful Paint) suele ser la imagen hero, la imagen destacada o un gran bloque de titular por encima del pliegue. Para WordPress, LCP rara vez es “solo la red”. Típicamente es una reacción en cadena:

  • Latencia de respuesta del servidor (TTFB): PHP, base de datos, fallos de caché, almacenamiento lento, CPU con steal, upstream deficientes.
  • Recursos que bloquean el render: CSS, fuentes y a veces JS que impide el renderizado.
  • Decisiones sobre medios: imágenes sin optimizar, dimensiones incorrectas, lazy-loading en la imagen LCP, preloads faltantes.
  • Comportamiento del CDN/caché: reglas de bypass, cookies, fragmentación de caché, explosiones de “Vary”.

Si tu LCP es malo, la peor solución es “instalar otro plugin de rendimiento”. Así es como terminas con seis capas de caché discutiendo sobre cabeceras.

INP: “¿Cuánto tiempo tardó la página en responder a un humano?”

INP (Interaction to Next Paint) reemplazó a FID como la métrica de “capacidad de respuesta”. No fue Google por aburrimiento; fue Google admitiendo que una sola interacción inicial es demasiado fácil de manipular. INP castiga tareas largas en el hilo principal, JS pesado y pesadillas de hidratación.

En WordPress, el dolor de INP suele venir de:

  • Bundles de JS inyectados por plugins (sliders, page builders, analítica, widgets de chat).
  • Frameworks de temas que envían un camión de JS para un problema que requería una bicicleta CSS.
  • Demasiado DOM, demasiados manejadores de eventos y scripts de terceros que hacen “cosas útiles” en cada clic.
  • Realidad de la CPU móvil: tu portátil no es la referencia de rendimiento; es un privilegio.

CLS: “¿La página se mantuvo donde estaba?”

CLS (Cumulative Layout Shift) es, en su mayor parte, autoinfligido. Es lo que ocurre cuando el navegador empieza a pintar y luego mueves los muebles: imágenes sin dimensiones, fuentes que cargan tarde, anuncios que cambian de tamaño, banners que empujan contenido, avisos de cookies que aparecen de la nada.

WordPress facilita causar CLS porque los temas a menudo emiten marcado “flexible”, los plugins inyectan DOM después de la carga y a los editores les encanta subir imágenes sin reglas de tamaño consistentes. La solución no es “desactivar animaciones”. La solución es reservar espacio y controlar las llegadas tardías.

Una idea para tener en el monitor parafraseada de Werner Vogels (Amazon): Todo falla; la fiabilidad viene de diseñar para el fallo, no de asumir que no ocurrirá.

Guion rápido de diagnóstico (primero/segundo/tercero)

Este es el orden que encuentra el cuello de botella rápidamente en producción sin convertir tu semana en un proyecto especulativo de arte.

Primero: Determina si tienes un problema de servidor o de front-end

  • Comprueba TTFB y la tasa de aciertos de caché. Si estás perdiendo caché y PHP trabaja mucho, nunca “optimizar CSS” te salvará.
  • Compara frío vs caliente. Si en caliente va rápido y en frío va lento, tienes brechas de caché o rutas costosas sin cachear (cookies, query strings, variantes para usuarios conectados).

Segundo: Identifica el elemento LCP y qué lo bloquea

  • ¿El elemento LCP es una imagen, un bloque, un titular?
  • ¿Se retrasa por CSS que bloquea el render o por fuentes?
  • ¿Se está lazy-loadeando el recurso LCP (no debería)?

Tercero: Audita el trabajo del hilo principal para INP

  • Busca tareas largas y bundles grandes de JS.
  • Desactiva temporalmente scripts de terceros para medir su impacto.
  • Reduce el DOM y evita widgets pesados de page builders por encima del pliegue.

Luego: Arregla CLS reservando espacio

  • Añade width/height o aspect-ratio a imágenes e incrustaciones.
  • Usa font-display correctamente y preload para las fuentes que realmente usas.
  • Deja de inyectar banners que empujan contenido después del paint.

Regla de decisión: Si TTFB es consistentemente alto, empieza por servidor/caché. Si TTFB está bien pero LCP es alto, arregla la ruta de render crítico y la entrega del elemento LCP. Si INP es alto, caza tareas largas y scripts de terceros. Si CLS es alto, reserva espacio y estabiliza fuentes/anuncios.

Datos y contexto histórico interesantes (por qué esto se complicó)

  • Década de 2010: La industria adoraba el «tiempo de carga de página» como un único número. Era conveniente y en su mayor parte inútil.
  • Era HTTP/2: Agrupar todo en un solo archivo dejó de ser automáticamente bueno; demasiado bundling puede retrasar el primer render.
  • WordPress 5.5: Se incluyó lazy-loading nativo para imágenes por defecto, lo que mejoró muchas páginas—y también rompió LCP en algunos sitios que lazy-loadearon la imagen hero sin excepciones.
  • Lanzamiento de Core Web Vitals: Google pasó de métricas solo de laboratorio a énfasis en datos de campo (CrUX). Tu “Lighthouse perfecto” aún puede perder en condiciones reales de usuario.
  • FID → INP: FID podía verse bien mientras la página seguía siendo torpe tras la interacción. INP mide la capacidad de respuesta a lo largo de interacciones, volviendo más difícil ocultar la «deuda de JS».
  • Se introdujo CLS: Fue en parte una reacción al caos de diseño impulsado por la web publicitaria—los usuarios pulsaban lo incorrecto porque el contenido se movía.
  • Explosión de fuentes web: Las fuentes personalizadas se normalizaron y luego se volvieron un gran contribuyente a CLS/LCP cuando cargaban tarde o intercambiaban mal.
  • Los page builders se masificaron: Aceleraron la publicación pero a menudo aumentaron el tamaño del DOM y enviaron JS/CSS extra, lo que se refleja en INP y LCP.

Dos verdades: el rendimiento es una característica de negocio, y WordPress es la forma más popular del mundo de desplegar errores de rendimiento a escala.

LCP: soluciones reales (no sensaciones)

1) Haz que TTFB sea aburrido: aciertos de caché, variantes predecibles

El LCP muchas veces empieza en el servidor. Si tu HTML llega tarde, nada más importa.

  • Caché de página para usuarios anónimos: fastcgi_cache de NGINX, Varnish, caché HTML en CDN o caché gestionada del host.
  • Caché de objetos para rutas dinámicas y usuarios conectados: Redis o Memcached.
  • Sensatez en la clave de caché: evita la fragmentación causada por cookies, query strings y variantes basadas en dispositivo a menos que realmente las necesites.

2) Deja de lazy-loadear tu imagen LCP

El elemento LCP debe cargarse temprano, con prioridad. Si tu tema añade loading="lazy" a la imagen hero, está saboteando la métrica que intentas mejorar.

Opciones de corrección:

  • Excluye las imágenes por encima del pliegue de la lógica de lazy-load.
  • Añade fetchpriority="high" a la imagen LCP cuando esté soportado.
  • Preload la variante exacta de la imagen hero (cuidado: preload la que realmente se usa).

3) Entrega la imagen correcta, no un error heroico

Fallo común en WordPress: servir un JPEG de 2400px a una vista móvil de 390px porque “retina”. Retina no es una licencia para la hinchazón.

  • Usa srcset y sizes correctamente (WordPress hace parte de esto; los temas pueden romperlo).
  • Prefiere AVIF/WebP cuando sea posible.
  • Comprime agresivamente la imagen hero; los usuarios recuerdan lo rápido más que la micro-textura.

4) Elimina CSS que bloquea el render de la manera correcta

«Inlinear critical CSS» no es una religión. Es un intercambio. El objetivo es renderizar el contenido por encima del pliegue rápido sin obligar al navegador a esperar una hoja de estilos gigante.

  • Minimiza la carga útil de CSS, elimina CSS no usado.
  • Divide el CSS de modo que los estilos por encima del pliegue estén disponibles inmediatamente.
  • No envíes cinco frameworks porque un plugin quiso Bootstrap.

5) Fuentes: o las cargas intencionalmente o no las uses

La carga de fuentes puede afectar LCP (render tardío) y CLS (swap). Si usas fuentes personalizadas:

  • Hospeda las fuentes localmente para reducir latencia de terceros y mejorar el cacheo.
  • Preload solo las fuentes usadas por encima del pliegue.
  • Usa font-display: swap u optional según la tolerancia de marca y la sensibilidad al CLS.

Broma #1: Un «tema ligero» es como la «mayonesa ligera»: existe, pero sigue siendo principalmente aceite y remordimiento.

INP: soluciones reales (tu JS probablemente miente)

1) Elimina JavaScript antes de optimizarlo

INP es implacable con el trabajo del hilo principal. La victoria más limpia es la eliminación: menos scripts, menos widgets, menos manejadores de eventos. Empieza por etiquetas de terceros y funciones de page builders.

2) Deferir scripts no críticos, pero sin romper la interactividad

«Deferir todo el JS» puede salir mal cuando scripts esenciales son necesarios para navegación, búsqueda o menús. La idea es:

  • Cargar el JS crítico para la interacción temprano (pequeño).
  • Deferir todo lo demás.
  • Usar callbacks de idle para trabajo no urgente cuando corresponda.

3) Reducir tareas largas: dividir bundles, reducir trabajo por evento

Si un clic lanza una tarea de 400ms, el usuario lo percibe aunque la página “cargó rápido”. Culpables típicos:

  • Manipulación masiva del DOM al hacer clic.
  • Analítica pesada que se ejecuta «on interaction».
  • Carruseles y librerías de animación que re-renderizan el mundo.

4) Domar scripts de terceros con límites estrictos

Los scripts de terceros son como contratistas: útiles, caros y a veces dejan un desastre. Pónles un presupuesto.

  • Cárgalos solo en las páginas donde se necesitan (un widget de chat no pertenece al archivo de blog).
  • Retrasa hasta intención del usuario (por ejemplo, después de hacer scroll o al hacer clic en «abrir chat»).
  • Audítalos regularmente; las pilas de marketing se acumulan como percebes.

CLS: soluciones reales (evita los saltos de diseño)

1) Reserva siempre espacio para imágenes, incrustaciones y anuncios

CLS suele ser «dimensiones faltantes». WordPress puede generar width/height para imágenes, pero temas y builders a veces los eliminan. Arréglalo en la fuente.

  • Asegura que las etiquetas img incluyan atributos width y height, o usa CSS aspect-ratio.
  • Para embeds (YouTube, iframes), envuelve en una caja con aspect-ratio.
  • Para anuncios: define ranuras fijas, no «lo que aparezca».

2) Fuentes: reduce el desplazamiento por swap

El intercambio de fuentes puede cambiar métricas de texto. Estrategias:

  • Usa una fuente de fallback con métricas similares.
  • Considera font-display: optional en fuentes secundarias.
  • Preload las fuentes primarias usadas por encima del pliegue.

3) No inyectes banners que empujen contenido después del paint

Avisos de cookies, barras promocionales, overlays de suscripción—si empujan contenido hacia abajo después del primer paint, estás literalmente fabricando CLS. Usa overlays que no refluyaan o reserva espacio desde el inicio.

Broma #2: CLS es lo que ocurre cuando tu página redecorra a mitad del tour. A nadie le gusta mobiliario sorpresa.

Tareas prácticas con comandos, salidas y decisiones

Estos son los chequeos que realizo antes de permitir que alguien «optimice» algo. Cada tarea incluye un comando, salida de ejemplo, qué significa y la decisión a tomar.

Task 1: Check cache effectiveness from the edge (HTML)

cr0x@server:~$ curl -sI https://example.com/ | egrep -i 'cache|age|x-cache|cf-cache-status|via|server|vary'
server: nginx
cache-control: public, max-age=60
age: 0
vary: Accept-Encoding, Cookie
x-cache: MISS

Qué significa: Estás variando por Cookie, lo que probablemente rompe tu clave de caché, y estás fallando en caché.

Decisión: Asegura que los usuarios anónimos no reciban cookies innecesarias; ajusta Vary; configura CDN/caché de página para ignorar cookies irrelevantes.

Task 2: Measure TTFB and total time

cr0x@server:~$ curl -o /dev/null -s -w 'namelookup=%{time_namelookup} connect=%{time_connect} ttfb=%{time_starttransfer} total=%{time_total}\n' https://example.com/
namelookup=0.004 connect=0.012 ttfb=0.680 total=1.102

Qué significa: La red está bien; la respuesta del servidor es lenta (TTFB ~680ms).

Decisión: Prioriza caché del lado servidor, ajuste de PHP-FPM y caché de objetos antes de micro-optimizaciones front-end.

Task 3: Compare warm-cache vs cold-cache (repeat request)

cr0x@server:~$ for i in 1 2 3; do curl -o /dev/null -s -w "run=$i ttfb=%{time_starttransfer} total=%{time_total}\n" https://example.com/; done
run=1 ttfb=0.690 total=1.110
run=2 ttfb=0.180 total=0.410
run=3 ttfb=0.175 total=0.402

Qué significa: La ruta fría es costosa; la caliente es aceptable. Tienes caché, pero no se golpea consistentemente (o la caché es demasiado pequeña/se está evictando).

Decisión: Aumenta la cobertura de caché, reduce la fragmentación (cookies/query strings) y verifica TTL/evicción de la caché.

Task 4: Identify the LCP candidate quickly (rough field heuristic)

cr0x@server:~$ curl -s https://example.com/ | sed -n '1,220p' | egrep -n 'wp-post-image|hero|featured|sizes=|srcset=|fetchpriority|preload'
42:<img class="wp-post-image" src="https://example.com/wp-content/uploads/2025/hero.jpg" loading="lazy" decoding="async">

Qué significa: La probable imagen LCP está marcada explícitamente para lazy-load. Eso puede retrasar LCP.

Decisión: Exenta la imagen hero/LCP del lazy-loading y considera fetchpriority=high y srcset adecuado.

Task 5: Confirm image dimensions exist (CLS prevention)

cr0x@server:~$ curl -s https://example.com/ | grep -oE '<img[^>]+>' | head -n 3
<img src="https://example.com/wp-content/uploads/2025/hero.jpg" class="wp-post-image">
<img src="https://example.com/wp-content/uploads/2025/logo.png" class="custom-logo" width="180" height="48">
<img src="https://example.com/wp-content/uploads/2025/thumb.jpg" loading="lazy" width="768" height="512">

Qué significa: La primera imagen no tiene width/height. Eso es un contribuyente clásico de CLS.

Decisión: Arregla la salida del tema (añade dimensiones), o aplica CSS aspect-ratio para contenedores conocidos.

Task 6: Check PHP-FPM saturation and slow requests

cr0x@server:~$ sudo systemctl status php8.2-fpm --no-pager
● php8.2-fpm.service - The PHP 8.2 FastCGI Process Manager
     Loaded: loaded (/lib/systemd/system/php8.2-fpm.service; enabled)
     Active: active (running)
     Status: "Processes active: 48, idle: 2, Requests: 310, slow: 17, Traffic: 2.1req/sec"

Qué significa: Estás cerca del máximo de procesos activos; existen solicitudes lentas.

Decisión: Inspecciona slowlog, aumenta pm.max_children solo si CPU/RAM lo permiten, y reduce trabajo de PHP vía caché y limpieza de plugins.

Task 7: Read PHP-FPM slowlog to find offenders

cr0x@server:~$ sudo tail -n 25 /var/log/php8.2-fpm/www-slow.log
[27-Dec-2025 09:14:02]  [pool www] pid 21432
script_filename = /var/www/html/index.php
[0x00007f3a7c1a2a30] mysqli_query() /var/www/html/wp-includes/wp-db.php:2056
[0x00007f3a7c1a2910] query() /var/www/html/wp-includes/wp-db.php:1918
[0x00007f3a7c1a2800] get_results() /var/www/html/wp-includes/wp-db.php:3193
[0x00007f3a7c1a26e0] get_posts() /var/www/html/wp-includes/post.php:2543
[0x00007f3a7c1a25c0] Elementor\Plugin->init() /var/www/html/wp-content/plugins/elementor/includes/plugin.php:699

Qué significa: La ruta lenta incluye inicialización pesada de plugins y consultas a la BD.

Decisión: Perfila el impacto de plugins, añade caché de objetos, reduce consultas costosas (o funcionalidades del plugin) y asegura caché de página para tráfico anónimo.

Task 8: Check MySQL/MariaDB for slow queries

cr0x@server:~$ sudo mysql -e "SHOW GLOBAL STATUS LIKE 'Slow_queries'; SHOW VARIABLES LIKE 'slow_query_log';"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Slow_queries  | 128   |
+---------------+-------+
+----------------+-------+
| Variable_name  | Value |
+----------------+-------+
| slow_query_log | ON    |
+----------------+-------+

Qué significa: Hay consultas lentas y el logging está activado.

Decisión: Inspecciona el log de consultas lentas; arregla índices y consultas de plugins antes de escalar hardware.

Task 9: Find the top slow queries (by time)

cr0x@server:~$ sudo mysqldumpslow -s t -t 5 /var/log/mysql/mysql-slow.log
Count: 12  Time=1.24s (14s)  Lock=0.00s (0s)  Rows=1200.0 (14400), root[root]@localhost
  SELECT option_value FROM wp_options WHERE option_name = 'autoloaded_options'

Count: 9  Time=0.88s (7s)  Lock=0.01s (0s)  Rows=1.0 (9), root[root]@localhost
  SELECT * FROM wp_posts WHERE post_type='product' AND post_status='publish' ORDER BY post_date DESC LIMIT N

Qué significa: Options/autoload y consultas de contenido son lentas; la sobrecarga de autoload es un clásico de WP.

Decisión: Reduce opciones autoload (limpieza de plugins), considera caché de objetos persistente, añade/verifica índices para consultas frecuentes.

Task 10: Check Redis object cache health

cr0x@server:~$ redis-cli info stats | egrep 'keyspace_hits|keyspace_misses|evicted_keys'
keyspace_hits:481230
keyspace_misses:220114
evicted_keys:9231

Qué significa: Los misses y las evicciones son significativos. La caché puede estar subdimensionada o los TTLs incorrectos.

Decisión: Aumenta maxmemory de Redis, ajusta la política de evicción y reduce la fragmentación de claves (agrupar claves, evitar cachéar objetos enormes).

Task 11: Confirm compression and content types (LCP payload control)

cr0x@server:~$ curl -sI https://example.com/wp-content/themes/site/style.css | egrep -i 'content-encoding|content-type|cache-control'
content-type: text/css; charset=UTF-8
cache-control: public, max-age=31536000
content-encoding: br

Qué significa: Brotli está activado y TTL de caché largo. Bueno para vistas repetidas y reduce tamaño de transferencia.

Decisión: Si falta codificación, activa gzip/br y verifica la configuración del CDN; si cache-control es corto, arregla cabeceras de cacheo de assets estáticos.

Task 12: Detect render-blocking CSS/JS from HTML (quick-and-dirty)

cr0x@server:~$ curl -s https://example.com/ | egrep -n '<link[^>]+rel="stylesheet"|<script[^>]+src=' | head -n 12
18:<link rel="stylesheet" href="https://example.com/wp-content/plugins/elementor/assets/css/frontend.min.css">
19:<link rel="stylesheet" href="https://example.com/wp-content/themes/site/style.css">
61:<script src="https://example.com/wp-includes/js/jquery/jquery.min.js"></script>
62:<script src="https://example.com/wp-content/plugins/contact-form-7/includes/js/index.js"></script>

Qué significa: Múltiples hojas de estilo y scripts cargan temprano. Algunos pueden ser innecesarios por encima del pliegue.

Decisión: Retrasa scripts no críticos, elimina assets de plugins no usados en páginas que no los utilizan y considera critical CSS para lo que está por encima del pliegue.

Task 13: Find heavy assets by size

cr0x@server:~$ curl -s https://example.com/ | grep -oE 'https://example.com[^"]+\.(js|css)' | sort -u | while read -r u; do s=$(curl -sI "$u" | awk -F': ' 'tolower($1)=="content-length"{print $2}' | tr -d '\r'); printf "%10s %s\n" "${s:-0}" "$u"; done | sort -nr | head
    842112 https://example.com/wp-content/plugins/pagebuilder/assets/app.js
    238900 https://example.com/wp-content/themes/site/style.css
    121104 https://example.com/wp-content/plugins/slider/assets/slider.js

Qué significa: Un plugin envía un archivo JS de 800KB. Eso es un problema de INP esperando a ocurrir en una CPU móvil.

Decisión: Elimina/reemplaza el plugin, cárgalo solo donde se necesite, o divídelo y deferlo. No trates de «minificar» un problema de 800KB.

Task 14: Check NGINX upstream timing to separate PHP vs network

cr0x@server:~$ sudo awk '$9 ~ /200|301|302/ {print $NF}' /var/log/nginx/access.log | tail -n 5
rt=0.412 uct=0.000 uht=0.410 urt=0.410
rt=1.122 uct=0.001 uht=1.120 urt=1.120
rt=0.398 uct=0.000 uht=0.396 urt=0.396
rt=0.905 uct=0.000 uht=0.904 urt=0.904
rt=0.401 uct=0.000 uht=0.399 urt=0.399

Qué significa: El tiempo de header upstream (uht) coincide con el tiempo de la solicitud (rt). PHP/aplicación es el cuello de botella, no la red del cliente.

Decisión: Enfócate en tiempo de ejecución de PHP, tasa de aciertos de caché, consultas a BD y sobrecarga de plugins.

Errores comunes: síntoma → causa raíz → reparación

1) Síntoma: LCP es malo en móviles, pero en escritorio está bien

Causa raíz: Imagen hero sobredimensionada + demasiado JS compitiendo por ancho de banda/CPU; el throttling móvil lo expone.

Reparación: Sirve imágenes responsivas con el tamaño adecuado, prioriza la imagen LCP (sin lazy-load) y reduce JS/CSS por encima del pliegue.

2) Síntoma: LCP fluctúa salvajemente entre ejecuciones

Causa raíz: Fallos de caché por cookies/query strings, capas de caché mezcladas o variabilidad en el origen (vecinos ruidosos, CPU steal).

Reparación: Normaliza claves de caché, elimina cookies innecesarias, verifica coherencia CDN/origen y estabiliza rendimiento del origen (dimensionado FPM, salud de BD).

3) Síntoma: INP es malo solo después de añadir analítica/chat/testing A/B

Causa raíz: Scripts de terceros ejecutan tareas largas o adjuntan manejadores de eventos costosos.

Reparación: Retrasa o carga condicionalmente scripts de terceros, elimina duplicados y aplica un presupuesto de scripts. Sí, puedes decirle que no al equipo de marketing.

4) Síntoma: CLS se dispara en artículos con imágenes

Causa raíz: El tema/builder elimina atributos width/height o usa CSS que causa reflow de imágenes.

Reparación: Asegura dimensiones intrínsecas, usa contenedores aspect-ratio y evita wrappers de lazy-loading que cambian el tamaño tarde.

5) Síntoma: CLS se dispara en la parte superior de la página

Causa raíz: Banner de cookies/barra promo inyectado después del primer paint, empujando el contenido hacia abajo.

Reparación: Reserva espacio desde el render inicial o usa overlays que no afectan el layout. Prefiere render del lado servidor de placeholders de consentimiento.

6) Síntoma: La página se siente responsiva en dev, pero usuarios reportan lag

Causa raíz: Pruebas en dispositivos rápidos y redes limpias; los usuarios reales tienen CPUs más lentas y pestañas en segundo plano.

Reparación: Prueba con throttling móvil, mide datos de campo y optimiza para dispositivos de gama baja (menos JS, menos nodos DOM, menos tareas en hilo principal).

7) Síntoma: “Plugin de optimización” mejora Lighthouse pero perjudica usuarios reales

Causa raíz: Defer agresivo que rompe scripts críticos, causa cambios de diseño tardíos o introduce condiciones de carrera e problemas de hidratación.

Reparación: Desactiva optimizaciones globales; implementa cambios dirigidos: critical CSS, defer selectivo y carga de assets por página.

Tres micro-historias corporativas desde la trinchera

Micro-historia 1: El incidente causado por una suposición equivocada

Asumieron que “las páginas WordPress son mayormente estáticas”. El sitio parecía estático: páginas de marketing, posts, un puñado de plantillas. Así que el equipo habilitó un CDN y declaró la victoria. No comprobaron cookies. No comprobaron cabeceras Vary. No confirmaron qué emitía realmente el origen.

Luego desplegaron un plugin de personalización. Estableció una cookie para cada visitante, incluidos anónimos, “por si convierten después”. El CDN respetó Vary: Cookie, porque fue educado y conforme a estándares. La tasa de aciertos de caché colapsó. TTFB subió. LCP lo siguió desde un precipicio.

La primera pista del on-call no fue un informe de Core Web Vitals. Fue la gráfica de CPU del origen y la longitud de la cola de PHP-FPM. Todo estaba «bien» ayer, salvo que ayer no se estaba estableciendo esa cookie. El cambio no fue malicioso, solo no medido.

La solución fue mundana: eliminar la cookie para usuarios anónimos, normalizar reglas de cache para ignorar cookies irrelevantes y asegurar que Vary no pueda ser reescrito silenciosamente por un plugin. El rendimiento volvió. El equipo también aprendió la diferencia entre «funciona en staging» y «funciona detrás de un CDN con tráfico real».

Micro-historia 2: La optimización que salió mal

Una organización distinta tenía un problema de INP y decidió “arreglar JavaScript” con un plugin de rendimiento que defería y retrasaba casi todo. Hizo a Lighthouse más feliz, lo que puso contenta a la dirección, y por eso se lanzó rápido. Ya puedes imaginar lo que pasó después.

En ciertas plantillas, el script diferido controlaba el menú de navegación. En dispositivos lentos, los usuarios pulsaban el icono hamburger y no pasaba nada por un rato. A veces dos latidos. A veces el menú se abría y se cerraba inmediatamente porque los event listeners se adjuntaban tarde y disparaban en el orden incorrecto. Los tickets de soporte lo llamaron «navegación rota». La analítica lo llamó «tasa de rebote». Ingeniería lo llamó «un viernes divertido».

La revisión post-incidente fue dolorosa porque nadie había hecho una prueba básica de interacción con un perfil móvil throttled. La “optimización” creó una carrera entre paint del HTML, aplicación de CSS y la hidratación tardía de JS. INP no mejoró significativamente; la confianza del usuario empeoró.

La corrección correcta fue más pequeña y quirúrgica: mantener scripts esenciales de interacción temprano, eliminar una librería de slider pesada y retrasar etiquetas de terceros hasta después del primer scroll o interacción. El rendimiento mejoró y, lo importante, el sitio dejó de engañar a los usuarios.

Micro-historia 3: La práctica aburrida pero correcta que salvó el día

Un equipo al que respeto hace un «censo de assets» semanal. No es glamuroso. Es un evento recurrente en el calendario donde comparan el número de scripts, bytes totales de JS, bytes de CSS y dominios terceros principales en páginas clave. Lo tratan como control presupuestario, no como auditoría única.

Durante una campaña mayor, una nueva versión del contenedor del tag manager introdujo por error librerías de analítica duplicadas y una herramienta de heatmap en cada página, incluido el checkout. Nada se cayó. Pero INP se degradó en los días siguientes y sus datos de campo empezaron a tender a peor.

Porque tenían esa línea base aburrida, detectaron la regresión rápido. Revirtieron la versión del contenedor y restauraron reglas de carga por página. Sin drama, sin heroísmos, sin reunión nocturna de «por qué el checkout está lento».

La lección: no puedes gestionar lo que no inventarías. El rendimiento no es un proyecto; es higiene.

Listas de verificación / plan paso a paso

Paso a paso: estabiliza LCP primero

  1. Mide TTFB en páginas clave (home, una landing principal, un artículo, página de producto). Si está lento, arregla origen/caché antes de tocar CSS.
  2. Confirma comportamiento de aciertos de caché (CDN y origen). Elimina la fragmentación inducida por cookies.
  3. Identifica el elemento LCP (usualmente imagen hero/bloque de titular). Asegúrate de que no tenga lazy-load y use tamaño responsivo correcto.
  4. Reduce bloqueo de render: elimina CSS no usado, inline critical CSS si está justificado y minimiza fuentes.
  5. Valida en condiciones de campo: throttling móvil y caché fría.

Paso a paso: arregla INP sin romper el sitio

  1. Lista todos los scripts de terceros y decide qué páginas los necesitan. «Todas las páginas» rara vez es cierto.
  2. Elimina plugins y funcionalidades redundantes. Reemplaza widgets pesados por alternativas más simples.
  3. Defera JS no crítico, pero mantiene el código esencial de interacción temprano.
  4. Reduce la complejidad del DOM por encima del pliegue: los page builders pueden producir 10x marcado para el mismo layout.
  5. Vuelve a probar interacciones (abrir menú, añadir al carrito, validación de formularios) en perfiles Android de gama media.

Paso a paso: elimina regresiones de CLS permanentemente

  1. Aplica dimensiones para imágenes e embeds en las plantillas del tema.
  2. Estabiliza fuentes: preload lo necesario, evita swaps tardíos y elige fallbacks sensatos.
  3. Controla banners: reserva espacio o usa overlays que no re-fluyan el contenido.
  4. Audita anuncios y espacios patrocinados: define contenedores fijos y evita redimensionar tras la carga.
  5. Añade comprobaciones de regresión: cada nuevo plugin/cambio de tema debe pasar una verificación de CLS en plantillas clave.

Preguntas frecuentes

1) ¿Debo arreglar LCP, INP o CLS primero?

Arregla lo que falle en los datos de campo, pero comienza por el que esté claramente impulsado por infraestructura y caché si está roto. Un TTFB alto arrastra LCP y desperdicia tiempo si te concentras primero en CSS.

2) ¿Puede un CDN “resolver” Core Web Vitals para WordPress?

Un CDN puede mejorar dramáticamente TTFB y assets estáticos, pero no arreglará CSS que bloquea el render, JS en el hilo principal o cambios de layout. Es infraestructura necesaria, no una estrategia completa de rendimiento.

3) ¿Lazy-loading siempre es bueno?

No. Lazy-loadear imágenes debajo del pliegue sí. No lazy-loadear el elemento LCP. Ten cuidado con iframes cerca de la parte superior; aún pueden provocar saltos si no reservas espacio.

4) ¿Los plugins de rendimiento ayudan?

A veces. También generan comportamiento opaco y cambios «con un clic» que no puedes razonar. Úsalos solo si puedes medir lo que cambiaron: cabeceras, salida HTML, atributos de script y comportamiento de la caché.

5) ¿Por qué Lighthouse se ve bien pero Search Console dice «necesita mejoras»?

Lighthouse es datos de laboratorio. Search Console (vía CrUX) refleja usuarios reales. Los usuarios reales tienen dispositivos más lentos, redes peores y más variabilidad. Optimiza para rendimiento de campo, no para capturas hermosas.

6) ¿Actualizar PHP ayuda a Core Web Vitals?

Pueda mejorar TTFB reduciendo el tiempo de ejecución en servidor, lo que puede mejorar LCP. No arreglará INP causado por JS pesado en cliente, ni evitará CLS. Aun así: mantén PHP actualizado; runtimes viejos son más lentos y riesgosos.

7) ¿Cuál es la ganancia más rápida para CLS en WordPress?

Arreglar dimensiones de imágenes. Asegura que cada imagen por encima del pliegue tenga width/height o un contenedor aspect-ratio. Luego ataca banners y fuentes.

8) ¿Cómo manejo scripts de terceros sin empezar una guerra política?

Dales un presupuesto y un dashboard: «Esta etiqueta cuesta X ms de INP en móvil». Luego ofrece carga por página y ejecución retrasada como compromiso. Los datos hacen la conversación menos emocional.

9) ¿Necesito Redis si ya tengo caché de página?

Si la mayor parte del tráfico es anónimo y atendido por caché de página/CDN, la caché de objetos importa menos. Si tienes usuarios conectados, WooCommerce o páginas dinámicas, la caché de objetos puede reducir TTFB de forma material.

10) ¿Cambiar de tema arreglará todo?

Cambiar de un tema builder pesado a uno más ligero puede mejorar las tres métricas rápidamente. Pero si tu problema real es fragmentación de caché, consultas lentas a BD o scripts de terceros, el nuevo tema no te salvará.

Siguientes pasos que puedes lanzar esta semana

  1. Ejecuta el guion rápido de diagnóstico y decide: primero servidor o primero front-end. No hagas ambos a la vez a menos que disfrutes resultados ambiguos.
  2. Arregla la fragmentación de caché: elimina cookies innecesarias para usuarios anónimos; normaliza comportamiento de Vary; verifica aciertos de CDN y origen.
  3. Haz intencional el elemento LCP: no lazy-load para la hero, srcset/sizes correctos y priorízala.
  4. Poda JS sin piedad: elimina un plugin/widget pesado antes de “optimizar” bundling. Borrar vence a las soluciones ingeniosas.
  5. Reserva espacio del layout: añade dimensiones/aspect-ratio en todo lo que esté por encima del pliegue; estabiliza banners y fuentes.
  6. Añade una puerta de regresión: censo de assets semanal + una simple verificación de «¿añadimos scripts/bytes/DOM?» antes de releases.

Los Core Web Vitals no son un misterio. Son un espejo. Si tu sitio WordPress es lento o tambaleante, las métricas dirán la verdad—con rudeza, consistencia y frente a tus clientes.

← Anterior
Rendimiento de Ceph en Proxmox lento: 10 comprobaciones que realmente detectan el cuello de botella
Siguiente →
Subvoltaje en GPUs: el truco silencioso de rendimiento que nadie te cuenta

Deja un comentario