- Fundamentos: O que é Performance e por que Importa
- Core Web Vitals: LCP, INP e CLS na Prática
- Entrega & Rendering: CDN, Lazy Loading e Estratégias de Render
- JavaScript: Seu Bundle Está Pesado Demais
- CSS: Critical Path e Layout Thrashing
- DevTools: Explorando a Performance no Navegador
- Monitoramento: Medindo o que Importa em Produção
Tudo que vimos até aqui — Core Web Vitals, code splitting, CSS crítico, DevTools — é sobre identificar e corrigir problemas. Mas como você sabe se as correções funcionaram em produção? Como detecta regressões antes que afetem usuários reais?
A resposta é Real User Monitoring (RUM) — coleta de métricas diretamente dos browsers dos seus usuários, em condições reais de rede, hardware e comportamento.
Dados de lab (Lighthouse) dizem o que pode estar lento. Dados de campo (RUM) dizem o que está lento para seus usuários de verdade.
A web-vitals Library
A biblioteca oficial do Google para coletar Core Web Vitals em produção. Os valores correspondem exatamente ao que o Chrome usa para calcular Page Experience.
import { onLCP, onINP, onCLS, onFCP, onTTFB } from 'web-vitals';
function sendToAnalytics(metric) {
const { name, value, rating, id } = metric;
// rating é 'good', 'needs-improvement' ou 'poor'
navigator.sendBeacon('/analytics', JSON.stringify({
name,
value: Math.round(name === 'CLS' ? value * 1000 : value),
rating,
id,
page: location.pathname,
}));
}
onLCP(sendToAnalytics);
onINP(sendToAnalytics);
onCLS(sendToAnalytics);
onFCP(sendToAnalytics);
onTTFB(sendToAnalytics);Use navigator.sendBeacon() — envia dados de forma assíncrona e garante a entrega mesmo quando o usuário navega para outra página.
import { onLCP, onINP, onCLS } from 'web-vitals/attribution';
onLCP(({ value, attribution }) => {
const { element, url, timeToFirstByte, resourceLoadTime } = attribution;
// element: qual elemento é o LCP
// url: URL da imagem/recurso
// timeToFirstByte: quanto veio do servidor
});
onINP(({ value, attribution }) => {
const { eventTarget, eventType, processingDuration } = attribution;
// eventTarget: o que o usuário clicou
// eventType: click, keydown, etc
// processingDuration: tempo do handler
});
onCLS(({ value, attribution }) => {
const { largestShiftTarget } = attribution;
// largestShiftTarget: o elemento que causou o maior shift
});Transforma dados agregados em informações acionáveis: em vez de saber que o LCP está em 3.5s, você sabe que é a imagem /hero.jpg e que 2s disso é TTFB.
Performance Observer API
Para métricas além dos Core Web Vitals, use a API nativa PerformanceObserver:
// Long tasks (> 50ms no main thread)
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.duration > 100) { // só long tasks significativas
analytics.track('long_task', { duration: entry.duration });
}
}
}).observe({ entryTypes: ['longtask'] });
// Recursos lentos
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.duration > 500) {
analytics.track('slow_resource', { name: entry.name, duration: entry.duration });
}
}
}).observe({ entryTypes: ['resource'] });User Timing — marcadores customizados
performance.mark('data-fetch-start');
const data = await fetchDashboardData();
performance.mark('data-fetch-end');
performance.measure('data-fetch', 'data-fetch-start', 'data-fetch-end');User marks aparecem como marcadores verticais no flame graph do DevTools — correlacione seu código de aplicação com o timeline de performance.
Estratégia de Coleta
Médias são enganosas. Uma média de 2s pode esconder que 10% dos usuários experimentam 8s. Use p50, p75, p95 e p99.
Métricas agregadas escondem padrões. Segmente por página, dispositivo (mobile/desktop), tipo de conexão, país e usuário novo vs recorrente.
75% dos usuários precisam estar no "bom" para o site ter CWV verde no Search Console. Monitore o p75 de LCP, INP e CLS como KPIs principais.
Ferramentas de RUM
npm install @vercel/speed-insights// app/layout.tsx
import { SpeedInsights } from '@vercel/speed-insights/next';
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<SpeedInsights />
</body>
</html>
);
}Dashboard nativo no Vercel com CWV por rota, segmentação por dispositivo e trending ao longo do tempo. Zero configuração extra.
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.SENTRY_DSN,
tracesSampleRate: 0.1, // 10% das transações
profilesSampleRate: 0.1,
});Se você já usa Sentry para erros, a extensão de performance é natural. Captura CWV, long tasks e correlaciona com traces de backend (full-stack observability).
O GA4 coleta Core Web Vitals automaticamente quando você usa o Google Tag. Acesse em Reports → Life cycle → Engagement → Pages and screens e adicione métricas de performance.
Simples de implementar, mas análise limitada comparado a ferramentas dedicadas de RUM.
Performance no CI/CD
Detectar regressões antes de ir para produção é mais barato que corrigir depois.
npm install -g @lhci/cli# .lighthouserc.yml
ci:
collect:
url:
- http://localhost:3000
- http://localhost:3000/blog
assert:
assertions:
largest-contentful-paint:
- error
- maxNumericValue: 2500
cumulative-layout-shift:
- error
- maxNumericValue: 0.1
total-blocking-time:
- warn
- maxNumericValue: 300PRs que introduzem regressões de performance falham o CI antes de chegar ao main.
// package.json
{
"bundlesize": [
{
"path": ".next/static/chunks/main-*.js",
"maxSize": "150 kB"
},
{
"path": ".next/static/css/*.css",
"maxSize": "30 kB"
}
]
}PRs que aumentam o bundle além do threshold falham o CI. Simples e eficaz como gate de qualidade.
Sua Checklist de Performance
Marque o que já implementou. O progresso fica salvo neste navegador.
Checklist de Performance
Progresso salvo automaticamente neste navegador
Fechando a Série
Ao longo desta série, cobrimos performance de ponta a ponta:
Performance, above the fold, impacto em negócio e as métricas certas para medir.
LCP, INP e CLS — como cada um é calculado, thresholds, causas e como debugar.
CDN, caching, SSR/SSG/ISR/Streaming, lazy loading, resource hints e fontes.
Bundle analysis, tree shaking, code splitting, React.lazy e Web Workers.
Critical path, critical CSS, layout thrashing, animações com transform e content-visibility.
Performance panel, Network waterfall, Memory, Coverage e Lighthouse integrado.
Performance é uma prática contínua, não um projeto pontual. O ciclo é simples: medir → identificar → corrigir → medir de novo. Com as ferramentas e o conhecimento desta série, você tem tudo para fazer esse ciclo funcionar no seu time.
As minhas notas
Selecione um trecho e use Destacar no menu (somente neste aparelho).