Por Qué Tu Sitio Lento Te Está Costando Dinero (Y Cómo Arreglarlo)
En 2025, Google no solo mira el contenido de tu sitio. Mira cómo se siente usarlo.
Un sitio que carga en 5 segundos tiene 90% más probabilidad de que el usuario se vaya sin comprar. Cada segundo de delay = 7% menos conversiones (datos de Amazon).
Pero no necesitas adivinar si tu sitio es "rápido". Google definió 3 métricas exactas que determinan si pasas o repruebas: los Core Web Vitals.
Esta guía te enseña exactamente cómo optimizar cada una hasta lograr 100/100 en Lighthouse. Con ejemplos reales de código Next.js.
Los 3 Core Web Vitals Explicados (Sin Jerga Técnica)
1. LCP (Largest Contentful Paint) - "¿Cuánto tarda en verse algo?"
Qué mide: Tiempo hasta que el contenido principal se vuelve visible.
Objetivo: < 2.5 segundos
En español: Si tu hero image tarda 5 segundos en aparecer, tu LCP es 5 segundos. Google dice que eso es inaceptable.
Ejemplo práctico:
// ❌ MAL: Imagen sin optimizar (LCP 4.5s)
<img src="/hero.jpg" alt="Hero" />
// ✅ BIEN: Next.js Image con priority (LCP 1.2s)
import Image from 'next/image';
<Image
src="/hero.jpg"
alt="Hero"
width={1200}
height={600}
priority // ⭐ Esto es clave para LCP
placeholder="blur"
blurDataURL="data:image/..." // Placeholder mientras carga
/>
2. FID (First Input Delay) → INP en 2024+
Qué mide: Tiempo que tarda el sitio en responder a tu primer click/tap.
Objetivo: < 100ms (ahora reemplazado por INP < 200ms)
En español: Haces click en un botón. ¿Cuánto tarda en pasar algo? Si tarda más de 100ms, se siente "pegajoso".
Causas comunes:
- JavaScript bloqueando el thread principal
- Renders pesados en React
- Hydration lenta
Solución:
// ❌ MAL: Bundle gigante cargado de una
import Chart from 'chart.js'; // 180kb
import Lodash from 'lodash'; // 70kb
import Moment from 'moment'; // 67kb
// ✅ BIEN: Dynamic imports + code splitting
const Chart = dynamic(() => import('chart.js'), {
loading: () => <Skeleton />,
ssr: false // No lo necesitas en server
});
// Usa date-fns en lugar de moment (2kb vs 67kb)
import { format } from 'date-fns';
3. CLS (Cumulative Layout Shift) - "¿Por qué se mueve todo?"
Qué mide: Cuánto "salta" el contenido mientras carga.
Objetivo: < 0.1
En español: Estás leyendo. De repente una imagen carga y el texto salta 200px abajo. Acabas clickeando un ad por accidente. Eso es CLS.
Ejemplo del problema:
// ❌ MAL: Sin dimensiones definidas
<img src="/product.jpg" alt="Product" />
// El espacio se reserva solo cuando la imagen carga = SHIFT
// ✅ BIEN: Con aspect ratio reservado
<Image
src="/product.jpg"
width={800}
height={600}
alt="Product"
// Next.js reserva el espacio antes de cargar
/>
Cómo Medir tus Core Web Vitals (3 Herramientas)
1. PageSpeed Insights (Datos Reales de Usuarios)
URL: https://pagespeed.web.dev/
Pega tu URL. Google te muestra:
- Field Data: Métricas reales de usuarios en los últimos 28 días
- Lab Data: Test sintético en ese momento
Lo que importa: Field Data. Es lo que Google usa para rankear.
2. Lighthouse (Local)
En Chrome DevTools:
- Abre DevTools (F12)
- Tab "Lighthouse"
- Generate Report
Ventaja: Puedes testearlo antes de hacer deploy.
3. Web Vitals Chrome Extension
Descarga: https://chrome.google.com/webstore (busca "Web Vitals")
Muestra LCP, FID, CLS en tiempo real mientras navegas tu sitio.
Optimizando LCP: De 4.5s a 1.2s (Caso Real)
Problema Común: Hero Image Lenta
Antes:
- Hero image: 2.4MB PNG
- Sin lazy loading
- Sin prioridad
- LCP: 4.5 segundos ❌
Solución paso a paso:
Paso 1: Comprimir la imagen
# Usa squoosh.app o sharp
npm install sharp
node -e "
const sharp = require('sharp');
sharp('hero.png')
.resize(1920, 1080, { fit: 'cover' })
.webp({ quality: 80 })
.toFile('hero.webp');
"
Resultado: 2.4MB → 180KB
Paso 2: Usar Next.js Image con priority
<Image
src="/hero.webp"
width={1920}
height={1080}
priority // Dile a Next.js que esto es lo más importante
alt="Hero banner"
/>
Paso 3: Preload fonts (si usas custom fonts)
// app/layout.tsx
export const metadata = {
// ...
icons: {
// Preload critical font
preload: [
{
href: '/fonts/inter-var.woff2',
as: 'font',
type: 'font/woff2',
crossOrigin: 'anonymous',
},
],
},
};
Después:
- Hero: 180KB WebP
- Prioridad máxima
- Font preloaded
- LCP: 1.2 segundos ✅
Optimizando FID/INP: JavaScript que No Bloquea
Problema: Dashboard Lento al Interactuar
Síntomas:
- Click en botón tarda 300ms en responder
- Typing en input se siente laggy
- INP: 450ms ❌
Causa: Todo el JavaScript carga de una en el bundle principal.
Solución: Code Splitting Estratégico
// ❌ ANTES: Todo en el bundle principal
import DataTable from '@/components/DataTable'; // 45kb
import ChartComponent from '@/components/Chart'; // 180kb
import PDFViewer from '@/components/PDFViewer'; // 210kb
export default function Dashboard() {
return (
<div>
<DataTable />
<ChartComponent />
<PDFViewer />
</div>
);
}
// ✅ DESPUÉS: Solo lo crítico en main bundle
import dynamic from 'next/dynamic';
// Lazy load componentes pesados
const DataTable = dynamic(() => import('@/components/DataTable'));
const ChartComponent = dynamic(() => import('@/components/Chart'), {
loading: () => <Skeleton height={400} />,
ssr: false, // No lo necesitas en server
});
const PDFViewer = dynamic(() => import('@/components/PDFViewer'), {
ssr: false,
});
export default function Dashboard() {
return (
<div>
<DataTable />
<ChartComponent />
<PDFViewer />
</div>
);
}
Resultado:
- Bundle principal: 340KB → 95KB
- INP: 450ms → 120ms ✅
Bonus: Usar React.memo para evitar re-renders
// ❌ ANTES: Se re-renderiza en cada keystroke
function UserCard({ user }) {
return <div>{user.name}</div>;
}
// ✅ DESPUÉS: Solo re-renderiza si user cambió
const UserCard = React.memo(function UserCard({ user }) {
return <div>{user.name}</div>;
}, (prevProps, nextProps) => {
// Custom comparator
return prevProps.user.id === nextProps.user.id;
});
Optimizando CLS: Reserva el Espacio
Problema 1: Imágenes sin dimensiones
// ❌ CLS Score: 0.25
<img src="/product.jpg" alt="Product" />
// ✅ CLS Score: 0.01
<Image
src="/product.jpg"
width={600}
height={400}
alt="Product"
/>
Problema 2: Ads o embeds que pushean contenido
// ❌ El ad carga y pushea todo 300px abajo
<div>
<h1>Artículo</h1>
<Ad /> {/* Sin height definido */}
<p>Contenido...</p>
</div>
// ✅ Reserva el espacio
<div>
<h1>Artículo</h1>
<div style={{ minHeight: '250px' }}>
<Ad />
</div>
<p>Contenido...</p>
</div>
Problema 3: Fonts causando FOIT/FOUT
FOIT (Flash of Invisible Text): El texto es invisible hasta que la font carga. FOUT (Flash of Unstyled Text): El texto aparece con font default, luego cambia.
Ambos causan CLS.
Solución:
/* globals.css */
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-var.woff2') format('woff2');
font-display: swap; /* ⭐ Muestra fallback inmediatamente */
font-weight: 100 900;
}
Checklist: Cómo Llegar a 100/100 en Lighthouse
Optimización de Imágenes
- Todas las imágenes en WebP o AVIF
- Imágenes above-the-fold con
priority - Lazy loading en imágenes below-the-fold
- Width y height definidos en TODAS las imágenes
- Compresión (usa squoosh.app o sharp)
JavaScript & Rendering
- Code splitting (dynamic imports)
- Bundle < 200KB (main chunk)
- React.memo en componentes que re-renderizan mucho
- Evita
useEffectinnecesarios - No bloquees el main thread (usa Web Workers para cómputo pesado)
Fonts
- Preload fonts críticas
-
font-display: swapen todas las fonts - Subset de fonts (solo los caracteres que usas)
- Máximo 2 font families
Server & Delivery
- CDN (Vercel, Cloudflare)
- Compresión gzip/brotli
- HTTP/2 o HTTP/3
- Cache headers correctos
Next.js Específico
- Usar
<Image>en lugar de<img> - Server Components cuando sea posible
-
generateStaticParamspara páginas dinámicas - Edge Runtime para APIs rápidas
Errores Comunes que Destruyen tus Métricas
Error 1: "Voy a usar una librería para TODO"
// ❌ 500KB de librerías para features simples
import _ from 'lodash';
import moment from 'moment';
import axios from 'axios';
// ✅ Usa lo mínimo necesario
import { debounce } from 'lodash-es/debounce'; // Solo lo que necesitas
import { format } from 'date-fns'; // 2KB vs 67KB de moment
// fetch es nativo, no necesitas axios
Error 2: "Todas las imágenes son JPG"
JPG es 2010. WebP es 30% más pequeño. AVIF es 50% más pequeño.
# Convierte todo tu directorio
for img in *.jpg; do
cwebp -q 80 "$img" -o "${img%.jpg}.webp"
done
Error 3: "No sé qué está haciendo mi sitio lento"
Usa React DevTools Profiler:
- Install React DevTools extension
- Tab "Profiler"
- Record mientras interactúas
- Ve qué componentes tardan más
Usa Chrome DevTools Performance:
- Tab "Performance"
- Record
- Reload tu página
- Ve el flame chart - identifica bottlenecks
Caso de Éxito: E-commerce 3.2s → 0.9s LCP
Cliente: Tienda online de ropa (Colombia)
Problema inicial:
- LCP: 3.2s (homepage con 8 hero images)
- FID: 280ms (mucho JavaScript de analytics)
- CLS: 0.18 (productos sin dimensiones)
- Conversión: 1.8%
Optimizaciones aplicadas:
-
Imágenes:
- JPG → WebP (-65% tamaño)
- Hero image con priority
- Productos con lazy loading
- Dimensiones definidas en todos
-
JavaScript:
- Analytics movido a Google Tag Manager (async)
- Product slider: dynamic import
- Checkout form: code split
-
Fonts:
- Poppins subset (solo Latin)
- Preload + font-display: swap
Resultados:
- LCP: 3.2s → 0.9s ✅
- FID: 280ms → 45ms ✅
- CLS: 0.18 → 0.02 ✅
- Conversión: 1.8% → 2.7% (+50%!)
- Revenue adicional: ~$18k/mes
Conclusión: Performance es UX, UX es Negocio
En resumen, los Core Web Vitals no son solo una métrica más. Son la representación cuantificable de la experiencia de tus usuarios. Y en un mundo donde cada milisegundo cuenta, optimizarlos es optimizar tu negocio.
Para una configuración SEO completa que incluya Core Web Vitals, consulta nuestra guía de SEO para lanzamiento web.
Si tu sitio actual tiene un LCP > 3s o Lighthouse score < 80, estás dejando dinero en la mesa.
¿Tu Sitio Necesita Optimización?
En Nandark optimizamos Core Web Vitals con resultados medibles. Nuestros clientes típicamente ven:
- +30-50 puntos en Lighthouse score
- 2x-3x mejora en velocidad de carga
- Mejor posicionamiento en Google (Core Web Vitals son factor de ranking)
Servicios relacionados
- Optimización Web y Core Web Vitals: Auditoría completa + implementación
- Desarrollo Web con Next.js: Sitios rápidos desde el código
Solicita una auditoría gratis: Te mostramos exactamente dónde están los cuellos de botella.
Recursos útiles:
- PageSpeed Insights
- web.dev - Core Web Vitals
- Next.js Image Optimization
- Cómo optimizamos nandark.com
Más contenido: Ver todos los artículos
