Medir o Core Web Vitals no Next.js: Guia de Configuração de RUM
Configure Real User Monitoring (RUM) para o Core Web Vitals no Next.js (App Router e Pages Router)

Medir o Core Web Vitals no Next.js
O Next.js é um framework JavaScript baseado em React que permite construir sites super-rápidos e extremamente amigáveis. Isso é verdade, o Next.js é bastante rápido e possui muitos recursos integrados para garantir que ele permaneça rápido. Pelo menos, na teoria. Com o tempo, à medida que seu site cresce, mais recursos são adicionados e, talvez, quando nem todas as melhores práticas são seguidas, as páginas do Next.js ficarão cada vez mais lentas. É provavelmente por isso que você está visitando esta página :-)
Última revisão por Arjen Karel em março de 2026
Para medir e evitar páginas lentas, é importante medir o Core Web Vitals e agir quando uma métrica estiver abaixo do seu limite. Os três Core Web Vitals são Largest Contentful Paint (LCP) para carregamento (limite: 2,5 segundos), Interaction to Next Paint (INP) para interatividade (limite: 200ms) e Cumulative Layout Shift (CLS) para estabilidade visual (limite: 0,1). Apenas 48% das origens mobile passam em todos os três, de acordo com o Web Almanac de 2025. Para sites Next.js especificamente, o relatório de frameworks Astro de 2023 descobriu que apenas cerca de 25% das origens Next.js foram aprovadas. Server Components e o App Router no Next.js 14 e 15 melhoraram isso, mas medir seus próprios dados de campo é a única maneira de saber qual é a sua situação.
Esqueça o Lighthouse (mais ou menos)
O Lighthouse é uma ferramenta de testes para o Core Web Vitals. Quase todos os clientes com os quais trabalho começarão, em algum momento, a falar sobre suas pontuações do Lighthouse e como elas não condizem com as pontuações do Search Console. A primeira coisa que eu digo a eles é a seguinte: esqueça o Lighthouse. Eu explico:

O Lighthouse é uma ferramenta muito útil que coleta 'dados de laboratório' (lab data) para uma visita inicial sem cache em condições reguladas. Infelizmente, os dados coletados não refletem necessariamente os dados de campo (field data). Os dados de campo são coletados pelo navegador toda vez que um usuário carrega uma de suas páginas. Esses dados são então enviados ao Google e usados para determinar as suas pontuações reais do Core Web Vitals. Este processo também é chamado de Real User Monitoring (RUM).
Aqui está o detalhe que a maioria dos desenvolvedores deixa passar: o INP não pode ser medido em ferramentas de laboratório. O Lighthouse não interage com o seu site, então ele não tem dados de interação. Ele usa o Total Blocking Time como um proxy, mas TBT e INP não são a mesma coisa. O CLS em ferramentas de laboratório também mostra pontuações artificialmente baixas porque o Lighthouse não rola a página ou clica em elementos. A única maneira de obter números reais de INP e CLS é a partir de usuários reais.
Não me entenda mal: eu adoro o Lighthouse. É uma peça de software magistral e vai te dar ótimas sugestões que você provavelmente deveria implementar. O que eu estou dizendo é que as métricas de RUM em um site Next.js não são formadas apenas por visualizações de primeira vez sem cache. Não, o Core Web Vitals em um site Next.js é mais complicado. É por isso que uma das primeiras coisas que implemento para os meus clientes é o Real User Monitoring (RUM) em tempo real. O Google ranqueia com base nos dados de campo do CrUX, não nas pontuações do Lighthouse.
Medir o Core Web Vitals no Next.js (App Router)
Se você estiver usando o App Router (Next.js 13+), a forma recomendada de coletar o Core Web Vitals é o hook useReportWebVitals do next/web-vitals. Este hook já vem com o próprio Next.js, então não há nada extra para instalar.
Como o hook requer a diretiva 'use client', a melhor prática é isolá-lo em um pequeno componente. Isso mantém a fronteira do cliente (client boundary) enxuta e evita tornar todo o seu layout um client component:
// app/_components/web-vitals.js
'use client'
import { useReportWebVitals } from 'next/web-vitals'
export function WebVitals() {
useReportWebVitals((metric) => {
console.log(metric)
})
return null
}
Em seguida, importe-o no seu layout raiz (root layout):
// app/layout.js
import { WebVitals } from './_components/web-vitals'
export default function Layout({ children }) {
return (
<html>
<body>
<WebVitals />
{children}
</body>
</html>
)
}
É isso. Cada carregamento de página agora vai relatar o LCP, INP, CLS, FCP e o TTFB no console. Claro, registrar no console não é muito útil em produção. Deixe-me mostrar como enviar os dados para algum lugar útil.
Enviar o Core Web Vitals para um endpoint customizado
A forma mais confiável de enviar dados de desempenho é com o navigator.sendBeacon(). Ele foi projetado exatamente para isso: enviar pequenos payloads quando o usuário sai da página, sem bloquear a navegação.
// app/_components/web-vitals.js
'use client'
import { useReportWebVitals } from 'next/web-vitals'
export function WebVitals() {
useReportWebVitals((metric) => {
const url = 'https://example.com/analytics'
const body = JSON.stringify(metric)
if (navigator.sendBeacon) {
navigator.sendBeacon(url, body)
} else {
fetch(url, { body: body, method: 'POST', keepalive: true })
}
})
return null
}
Enviar o Core Web Vitals para o Google Analytics (GA4)
Se você usa o Google Analytics 4 com o snippet do gtag, pode enviar o Core Web Vitals como eventos customizados:
// app/_components/web-vitals.js
'use client'
import { useReportWebVitals } from 'next/web-vitals'
export function WebVitals() {
useReportWebVitals((metric) => {
window.gtag('event', metric.name, {
event_category: 'Web Vitals',
value: Math.round(metric.name === 'CLS' ? metric.value * 1000 : metric.value),
event_label: metric.id,
non_interaction: true,
})
})
return null
}
Lembre-se: ao ler os dados do Core Web Vitals de qualquer fonte de RUM, você deve usar o percentil 75. Esse é o limite que o Google utiliza. Não é a média, nem a mediana. É o p75.
Amostragem (Sampling) em sites de alto tráfego
Em sites de alto tráfego, fará pouco sentido coletar dados de todos os usuários. Você pode fazer uma amostragem de 50% ou menos desta forma:
// app/_components/web-vitals.js
'use client'
import { useReportWebVitals } from 'next/web-vitals'
const inSample = Math.random() >= 0.5
export function WebVitals() {
useReportWebVitals((metric) => {
if (inSample) {
const body = JSON.stringify(metric)
navigator.sendBeacon('/analytics', body)
}
})
return null
}
Medir o Core Web Vitals no Next.js (Pages Router)
Se você ainda está no Pages Router, o Next.js fornece uma função nativa reportWebVitals que você exporta de pages/_app.js. Esta é a abordagem mais antiga, mas ainda funciona:
// pages/_app.js
export function reportWebVitals(metric) {
if (metric.label === 'web-vital') {
console.log(metric)
}
}
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />
}
Os mesmos padrões para enviar dados para um endpoint customizado ou Google Analytics se aplicam aqui. Basta colocar a chamada do sendBeacon ou gtag dentro da função reportWebVitals, em vez de no callback do hook.
Um ponto a ser observado: o Pages Router também relata métricas customizadas do Next.js, como Next.js-hydration e Next.js-route-change-to-render. Elas informam quanto tempo levam a hidratação e as navegações do lado do cliente (client-side navigations). A versão do App Router ainda não relata essas métricas customizadas.
Ferramentas de monitoramento de terceiros
Existem algumas ferramentas de terceiros que coletam o Core Web Vitals no Next.js. A Vercel possui o @vercel/speed-insights, que funciona de forma imediata se você fizer o deploy na Vercel. Ele é bom para uma visão geral rápida, mas não divide as métricas em subpartes, os dashboards são básicos e você fica preso ao ecossistema da Vercel.
O NewRelic e o Sentry também coletam o Core Web Vitals, mas não são ferramentas de desempenho. Eles são ferramentas de rastreamento de erros e APM que adicionaram o Core Web Vitals como um recurso extra. Ambos injetam scripts que competem por recursos iniciais de rede e pelo tempo da thread principal (main thread). Já vi o Sentry adicionar 200ms de tempo de bloqueio (blocking time) no mobile. Isso é irônico para uma ferramenta que deveria ajudar você a monitorar o desempenho.
O CoreDash é o que eu uso e recomendo. Ele foi desenvolvido especificamente para o Core Web Vitals. Cada métrica é dividida em subpartes para que você saiba exatamente para onde vai o tempo. Os dashboards mostram tendências, regressões e análises em nível de página sem a necessidade de clicar em cinco menus. E a integração MCP permite que você conecte seus dados de campo em ferramentas de IA e faça perguntas sobre o seu desempenho em linguagem natural. Basta perguntar "o que está causando layout shifts no mobile" e obter a resposta a partir dos seus próprios dados.
Se você quiser corrigir problemas com scripts de terceiros ou remover o CSS que bloqueia a renderização no Next.js, eu também escrevi guias dedicados para isso.
The RUM tool I built for my own clients.
CoreDash is what I use to audit enterprise platforms. Under 1KB tracking script, EU hosted, no consent banner. AI with MCP support built in. The same tool, available to everyone.
Create Free Account
