vruz.dev
Notas
Performance8 min

Core Web Vitals: cómo conseguir Lighthouse 100 en Next.js

Las optimizaciones concretas que aplico en cada proyecto Next.js para conseguir Lighthouse 100: fonts, images, layout shifts y rendering.

  • #performance
  • #lighthouse
  • #core-web-vitals
  • #next.js

Lighthouse 100 no es un número de vanidad. Es la validación de que tu web carga rápido, no se mueve mientras carga, responde al input del usuario y es accesible. Cada punto que pierdes es un usuario que espera más o un potencial cliente que se va.

Estas son las optimizaciones concretas que aplico en cada proyecto Next.js para conseguir ese 100.

Fonts: la trampa más común

Las fuentes de Google son el primer lugar donde se pierde performance. Cada fuente externa bloquea el renderizado hasta que se descarga. La solución en Next.js: usar next/font.

next/font descarga la fuente en build time, la sirve como archivo estático y genera CSS con font-display: swap. Cero bloqueo de renderizado, cero layout shift por cambio de fuente.

El combo que uso: preconnect a Google Fonts en el head y la fuente cargada con next/font para tener lo mejor de ambos mundos.

Imágenes: next/image siempre

El componente Image de Next.js no es opcional. Hace tres cosas que tu no hace: lazy loading automático, generación de srcset responsive y optimización de formato (WebP/AVIF automático).

Reglas que sigo: siempre definir width y height para evitar layout shift, usar priority solo para imágenes above the fold, y nunca servir imágenes más grandes de lo que se muestran.

Layout Shift: el enemigo silencioso

CLS (Cumulative Layout Shift) mide cuánto se mueven los elementos mientras la página carga. Los culpables habituales: imágenes sin dimensiones, fuentes que cambian de tamaño al cargar, y contenido dinámico que empuja el layout.

La solución para imágenes: siempre width y height. Para fuentes: font-display swap con métricas de fallback similares. Para contenido dinámico: reservar espacio con skeleton states o min-height.

Server Components por defecto

Next.js App Router renderiza componentes en el servidor por defecto. Eso significa menos JavaScript en el cliente, hidratación más rápida y mejor Time to Interactive.

Mi regla: solo uso 'use client' cuando necesito estado, efectos o event handlers. Todo lo demás es Server Component. Cada componente que no necesita JavaScript en el cliente es un componente que no necesita hidratarse.

CSS mínimo

Tailwind CSS genera solo las clases que usas. Eso ya es una optimización considerable. Pero además: evito animaciones CSS pesadas en el render inicial, uso will-change solo donde hay animación real, y evito box-shadows enormes que fuerzan composición.

Metadata y accesibilidad

Lighthouse también evalúa accesibilidad y mejores prácticas. Lo que siempre incluyo: lang en html, alt en todas las imágenes, aria-labels en botones icon-only, focus-visible consistente, contraste de colores suficiente y heading hierarchy correcta.

Preload de recursos críticos

Los assets críticos para el primer render deben precargarse. En Next.js: preconnect a fonts, priority en imágenes hero, y prefetch en links de navegación principal.

Medición continua

Un Lighthouse 100 en desarrollo no garantiza 100 en producción. Las diferencias de red, CDN y contenido dinámico pueden cambiar los números. Mi checklist: medir en producción después de cada deploy, usar PageSpeed Insights además de Lighthouse local, y monitorizar Core Web Vitals en Google Search Console.

Conclusión

Lighthouse 100 es alcanzable en Next.js si cada decisión tiene performance en mente. No es un objetivo de una sola vez: es un estándar que mantienes con disciplina en cada feature que añades.

¿Construyendo algo?

Si esto te ha resonado, podemos hablar. Contactar →