Otimização de Core Web Vitals
Otimização direcionada para os três Core Web Vitals usando dados de campo para identificar o impacto no usuário e traços de navegador para diagnosticar causas.
Meça antes de otimizar
Quando uma URL executável estiver disponível, leia o fluxo de trabalho de medição de desempenho. Prefira esta sequência:
- Verifique os dados CrUX p75 no nível da página, com uma fallback claramente identificada para a origem quando os dados da página não estiverem disponíveis.
- Grave um traço de desempenho do navegador sob as condições declaradas. Com o Chrome DevTools MCP, os resumos dos traços podem incluir CrUX junto com as métricas de laboratório observadas.
- Analise apenas os insights associados à métrica com falha e, em seguida, inspecione o código e os recursos implicados.
- Reexecute medições de laboratório equivalentes após a correção. Não reivindique uma melhoria imediata em campo; CrUX e RUM de primeira parte precisam de novas visitas de usuários.
Se apenas o código-fonte estiver disponível, identifique causas prováveis, mas não afirme que LCP, INP ou CLS está falhando sem evidências de tempo de execução.
As três métricas
| Métrica | Mede | Bom | Precisa de trabalho | Ruim |
|---|---|---|---|---|
| LCP | Carregamento | ≤ 2,5s | 2,5s – 4s | > 4s |
| INP | Interatividade | ≤ 200ms | 200ms – 500ms | > 500ms |
| CLS | Estabilidade Visual | ≤ 0,1 | 0,1 – 0,25 | > 0,25 |
O Google mede no 75º percentil — 75% das visitas à página devem atender aos limites "Bom".
LCP: Largest Contentful Paint
LCP mede quando o maior elemento de conteúdo visível é renderizado. Geralmente, é:
- Imagem hero ou vídeo
- Bloco de texto grande
- Imagem de fundo
- Elemento
<svg>
Problemas comuns de LCP
1. Resposta lenta do servidor (TTFB > 800ms)
Correção: CDN, cache, backend otimizado, renderização em edge
2. Recursos que bloqueiam a renderização
<!-- ❌ Bloqueia a renderização -->
<link rel="stylesheet" href="/all-styles.css">
<!-- ✅ CSS crítico inline, restante adiado -->
<style>/* CSS crítico acima da dobra */</style>
<link rel="preload" href="/styles.css" as="style"
onload="this.onload=null;this.rel='stylesheet'">
3. Tempos de carregamento de recurso lentos
<!-- ❌ A imagem LCP é descoberta somente após um stylesheet carregar -->
<div class="hero"></div>
<!-- ✅ Descoberta no HTML inicial e priorizada -->
<link rel="preload" href="/hero.webp" as="image" fetchpriority="high">
<img src="/hero.webp" alt="Hero" fetchpriority="high">
Prefira um <img> descoberta com fetchpriority="high". Adicione o preload somente quando o traço mostrar que o recurso seria descoberto tarde demais; preloads duplicados ou especulativos podem competir por largura de banda.
4. Atrasos de renderização no lado do cliente
// ❌ Conteúdo carrega após JavaScript
useEffect(() => {
fetch('/api/hero-text').then(r => r.json()).then(setHeroText);
}, []);
// ✅ Renderização do lado do servidor ou estática
// Use SSR, SSG ou streaming para enviar HTML com conteúdo
export async function getServerSideProps() {
const heroText = await fetchHeroText();
return { props: { heroText } };
}
5. Torne as navegações instantâneas com a API de Regras de Especulação
Para sites com jornadas previsíveis na mesma origem, pré-renderizar uma página provável de ser a próxima pode tornar uma navegação subsequente bem-sucedida muito mais rápida. Trate isso como uma otimização de navegação medida, não um substituto para corrigir o LCP da página atual.
<script type="speculationrules">
{
"prerender": [{
"where": { "href_matches": "/*" },
"eagerness": "moderate"
}]
}
</script>
O comportamento atual do Chrome é específico o suficiente para orientar a escolha:
eagerness | Gatilho |
|---|---|
conservative | Toque ou clique com o mouse pressionado |
moderate | Desktop: 200ms de hover, ou clique com o mouse pressionado anteriormente; mobile: heurísticas de viewport |
eager | Chrome 143+: desktop 10ms de hover; mobile 50ms após a âncora entrar no viewport |
immediate | Assim que as regras são observadas |
Comece de forma conservadora e meça a taxa de acerto da previsão, bytes transferidos, carga do servidor e melhoria da navegação antes de expandir as regras. Verifique novamente a documentação de eagerness mantida pelo Chrome antes de codificar comportamento sensível a tempo.
Ressalvas:
- Custo de largura de banda/CPU. Cada pré-renderização é aproximadamente um carregamento completo de página. Escolha
wherecuidadosamente (padrõeshref_matches, exclua logout/checkout) e eviteimmediatefora de sites pequenos. - Efeitos colaterais disparam cedo. Analytics, anúncios e qualquer código executado no carregamento serão acionados quando a pré-renderização começar, não quando o usuário navegar. Proteja os efeitos colaterais com o evento
prerenderingchangeoudocument.prerendering. - Apenas Chromium. Safari e Firefox ignoram o script — é um aprimoramento progressivo, nunca uma regressão.
Lista de verificação de otimização LCP
- [ ] TTFB < 800ms (use CDN, cache em edge)
- [ ] Recurso LCP é descoberto no HTML inicial e priorizado; preload somente se o traço mostrar descoberta tardia
- [ ] Imagem LCP otimizada (WebP/AVIF, tamanho correto)
- [ ] CSS crítico inline (< 14KB)
- [ ] Nenhum JavaScript que bloqueia a renderização no <head>
- [ ] Fontes não bloqueiam a renderização de texto (font-display: swap)
- [ ] Elemento LCP no HTML inicial (não renderizado por JS)
- [ ] Regras de Especulação adicionadas para navegações prováveis (eagerness moderate)
Identificação do elemento LCP
Este snippet diagnostica a sessão da página atual. Não são dados de campo.
// Encontre seu elemento LCP
new PerformanceObserver((list) => {
const entries = list.getEntries();
const lastEntry = entries[entries.length - 1];
console.log('Elemento LCP:', lastEntry.element);
console.log('Tempo LCP:', lastEntry.startTime);
}).observe({ type: 'largest-contentful-paint', buffered: true });
INP: Interaction to Next Paint
INP mede a responsividade em cliques, toques e pressionamentos de tecla durante uma visita. Diagnostique seu atraso de entrada, tempo de processamento e atraso de apresentação separadamente; uma interação lenta pode envolver contenção da thread principal antes do manipulador, trabalho caro da aplicação ou renderização atrasada após ele.
Quando o INP de campo é ruim ou um traço identifica uma interação lenta, leia a referência INP para interpretação de traços, padrões de yield, causas de terceiros e de renderização, um observador de sessão única e atribuição de primeira parte.
CLS: Cumulative Layout Shift
CLS mede mudanças inesperadas de layout durante uma visita à página. Use atribuição de campo ou um traço para identificar o nó deslocado e o gatilho; não presuma que a vítima visível causou a mudança.
Quando o CLS de campo é ruim ou um traço relata mudanças, leia a referência CLS para padrões de espaço reservado, conteúdo dinâmico, correções de fonte e animação, um observador de depuração e uma lista de verificação de verificação.
Fontes de medição
| Fonte | Uso |
|---|---|
Traço de desempenho do navegador (Chrome DevTools MCP: performance_start_trace) | Observar um carregamento ou interação e diagnosticar insights focados; usar contexto CrUX incluído quando disponível |
| CrUX ou Search Console | Priorizar resultados reais agregados de usuários no p75 |
| Lighthouse CLI ou PageSpeed Insights | Fallback de laboratório controlado quando as ferramentas DevTools não estão disponíveis |
| RUM de primeira parte | Segmentar a experiência de produção atual por rota, dispositivo, versão e atribuição |
PerformanceObserver bruto | Inspecionar uma sessão de página durante a depuração |
Não roteie desempenho através do lighthouse_audit do Chrome DevTools MCP; essa capacidade cobre intencionalmente categorias de Lighthouse não relacionadas a desempenho. Não compare um único valor de laboratório diretamente com um p75 de campo como se fossem amostras equivalentes.
Ao adicionar ou revisar a coleta de produção, leia a referência RUM de primeira parte. Prefira a biblioteca web-vitals porque as APIs brutas do navegador não implementam por si só todas as regras de ciclo de vida e relatório de cada Core Web Vital.
Correções rápidas por framework
Next.js
// LCP: use next/image com priority
import Image from 'next/image';
<Image src="/hero.jpg" priority fill alt="Hero" />
// INP: use importações dinâmicas
const HeavyComponent = dynamic(() => import('./Heavy'), { ssr: false });
// CLS: componente Image lida com dimensões automaticamente
React
// LCP: Preload no head
<link rel="preload" href="/hero.jpg" as="image" fetchpriority="high" />
// INP: Memorize e useTransition
const [isPending, startTransition] = useTransition();
startTransition(() => setExpensiveState(newValue));
// CLS: Sempre especifique dimensões em tags img
Vue/Nuxt
<!-- LCP: use nuxt/image com preload -->
<NuxtImg src="/hero.jpg" preload loading="eager" />
<!-- INP: use componentes assíncronos -->
<component :is="() => import('./Heavy.vue')" />
<!-- CLS: use CSS aspect-ratio -->
<img :style="{ aspectRatio: '16/9' }" />
Referências
- Otimização detalhada de LCP — leia quando um traço LCP apontar para atraso de descoberta, carregamento ou renderização
- Otimização detalhada de INP — leia quando um traço ou atribuição de campo identificar uma interação lenta
- Otimização detalhada de CLS — leia quando um traço ou atribuição de campo identificar mudanças inesperadas
- web.dev LCP
- web.dev INP
- web.dev CLS
- Skill de desempenho
