Volver a las notas

Medir Core Web Vitals reales en Next.js con web-vitals

10 de agosto de 2026·
nextjscorewebvitalsrumperformance

Nota revisada y reescrita el 18 de octubre de 2026: la versión original tenía errores y datos sin fuente.

Lighthouse te da una nota con una carga simulada, en una máquina y una red concretas. Google valora tu web con otra cosa: lo que miden los navegadores de usuarios reales (datos de campo), en el percentil 75. Las dos cifras pueden no parecerse en nada. Si quieres saber qué pasa de verdad, tienes que medir en el navegador de tus visitas.

Las tres métricas y sus umbrales

| Métrica | Mide | Bueno | |---|---|---| | LCP | Cuándo se pinta el elemento principal | ≤ 2,5 s | | INP | Lo que tarda la página en responder a clics y teclas | ≤ 200 ms | | CLS | Cuánto se mueve el contenido mientras cargas | ≤ 0,1 |

INP sustituyó a FID como Core Web Vital en marzo de 2024.

Recogerlas en Next.js

Pages Router: exporta reportWebVitals desde pages/_app.js:

export function reportWebVitals(metric) {
  const body = JSON.stringify({
    name: metric.name,      // LCP, INP, CLS, FCP, TTFB...
    value: metric.value,
    rating: metric.rating,  // good | needs-improvement | poor
    id: metric.id,
    page: window.location.pathname,
  });
  navigator.sendBeacon?.('/api/vitals', body) ||
    fetch('/api/vitals', { body, method: 'POST', keepalive: true });
}

App Router: el hook useReportWebVitals de next/web-vitals, dentro de un Client Component que montas en el layout:

'use client';
import { useReportWebVitals } from 'next/web-vitals';

export function WebVitals() {
  useReportWebVitals((metric) => {
    navigator.sendBeacon('/api/vitals', JSON.stringify(metric));
  });
  return null;
}

Fuera de Next (o si quieres la atribución detallada), la librería web-vitals de Google hace lo mismo con onLCP, onINP y onCLS. Su build attribution te dice, además, qué elemento fue el LCP o qué interacción provocó el peor INP.

Por qué sendBeacon

INP y CLS no tienen un valor final hasta que el usuario se va de la página: la librería los reporta cuando la pestaña pasa a segundo plano. En ese momento, un fetch normal puede cancelarse. navigator.sendBeacon (o fetch con keepalive: true) está pensado justo para enviar datos mientras la página se cierra.

Leer los datos

  • Percentil 75, no media. Es el mismo criterio que usa Google, y la media esconde la cola lenta.
  • Separa por tipo de página y por dispositivo. La home en escritorio y una ficha de producto en móvil son problemas distintos.
  • Guarda rating y id. Una misma vista puede reportar CLS varias veces mientras crece. Quédate con el último valor de cada id.

Para empezar no hace falta montar nada: el informe de Core Web Vitals de Search Console y la sección de datos de campo de PageSpeed Insights (CrUX) ya tienen el p75 de tu dominio, siempre que tenga tráfico suficiente. La medición propia sirve para ver páginas concretas y para comprobar un cambio en días en lugar de esperar los 28 días que agrega CrUX.

Fuentes