Seu usuário toca um botão de filtro—300 milissegundos passam antes da interface responder. O Real User Monitoring do Google registra o atraso. Sua taxa de conversão cai mais meio por cento. Core Web Vitals evoluiu de curiosidade de ranking para a linha mensurável entre sites que convertem e sites que perdem usuários. Em 2026, INP substituiu completamente FID, limites de CLS ficaram mais rigorosos, e as métricas Smoothness rumoreadas já estão em Chrome Canary. Este guia destila 200+ audits de desempenho que rodamos na Social Animal nas correções específicas de framework, benchmarks reais e snippets de código que realmente movem seus scores—nada de conselho vago sobre "otimizar imagens". Vamos mostrar os três lugares onde INP quebra em Next.js 14 App Router, o ajuste de duas linhas em Intersection Observer que reduziu nosso LCP em 40%, e por que seus scripts de terceiros ainda prejudicam CLS mesmo quando você acha que são async.

Índice

O que são Core Web Vitals em 2026?

Core Web Vitals são o conjunto padronizado de métricas de UX do Google que influenciam diretamente os rankings de busca — e, honestamente? Mais importante, o comportamento do usuário. Eles medem o que os usuários realmente sentem: quão rápido o conteúdo aparece, quão rápido a página responde quando tocam algo, e se o layout fica no lugar ou pula como se estivesse possuído.

INP substituiu oficialmente FID em março de 2024. Até meados de 2025, dados de uso do Chrome mostraram que 38% das origens ainda falhavam no limite INP — compare isso com a taxa de aprovação de 92% que FID desfrutava. Isso não era Google movendo os postes. Eles finalmente estavam medindo o que realmente importava.

Onde as coisas estão no início de 2026:

  1. Largest Contentful Paint (LCP) — Desempenho de carregamento
  2. Interaction to Next Paint (INP) — Responsividade
  3. Cumulative Layout Shift (CLS) — Estabilidade visual

Google também sinalizou interesse em uma métrica Smoothness (pense em quedas de quadros de animação e jank de scroll), embora ainda não tenha sido promovida a status de Core Web Vital. Times inteligentes já estão rastreando via Long Animation Frames (LoAF) API. Se você não está — comece.

As Métricas Atuais e Seus Limites

Métrica Bom Precisa de Melhoria Ruim O que Mede
LCP ≤ 2.5s 2.5s – 4.0s > 4.0s Tempo até o maior elemento visível renderizar
INP ≤ 200ms 200ms – 500ms > 500ms Pior latência de interação no session
CLS ≤ 0.1 0.1 – 0.25 > 0.25 Soma de scores de layout shift inesperados

Aqui está o que as pessoas constantemente esquecem. Esses limites são medidos no 75º percentil de carregamentos de página a partir de dados reais do Chrome User Experience Report (CrUX). Isso significa que 75% de seus usuários reais precisam atingir "Bom". Não seu teste em um MacBook Pro com internet de fibra. Seus usuários reais — em seus Samsungs de três anos, andando de metrô com LTE fraco. Diferença massiva.

Otimização do Largest Contentful Paint (LCP)

LCP é tipicamente a métrica que os teams entendem melhor — e ainda assim é aquela que a maioria dos sites falha. Os dados do final de 2025 do HTTP Archive mostravam que apenas 63% das origens mobile passavam em LCP. Isso é... não muito bom.

Entendendo as Sub-partes de LCP

Google dividiu LCP em quatro sub-partes em sua documentação de 2024. Este framework é a única ferramenta de diagnóstico mais eficaz que encontramos — nada mais chega perto:

Sub-parte Alvo O que Cobre
Time to First Byte (TTFB) < 800ms Resposta do servidor, DNS, TLS, redirecionamentos
Resource Load Delay < 10% de LCP Tempo entre TTFB e quando o recurso LCP começa a carregar
Resource Load Duration < 40% de LCP Tempo para baixar o recurso LCP
Element Render Delay < 10% de LCP Tempo entre recurso carregado e pixel renderizado

Correções no Lado do Servidor

Reduza TTFB migrando para computação edge. Ainda servindo de uma única origem? Você está entregando 200-800ms para usuários longe do seu servidor. Apenas entregando. De graça.

// Next.js middleware para renderização edge-first
// next.config.js
export default {
  experimental: {
    runtime: 'edge',
  },
};

// middleware.ts — roda na edge
import { NextResponse } from 'next/server';
export const config = { matcher: ['/((?!api|_next/static|favicon.ico).*)'] };

export function middleware(request) {
  const response = NextResponse.next();
  // Adiciona headers server timing para debugging
  response.headers.set('Server-Timing', `edge;desc="Edge Middleware"`);
  return response;
}

Para times em Astro ou Next.js, páginas renderizadas em edge consistentemente atingem TTFB abaixo de 200ms globalmente. Nossas práticas de desenvolvimento Next.js e desenvolvimento Astro usam edge deployment por padrão.

Otimização de Descoberta de Recursos

Aqui está o que a maioria das pessoas perde — o maior assassino de LCP em 2026 não é servidores lentos. É a descoberta tardia do recurso LCP. Se a URL da sua imagem hero está enterrada em um arquivo CSS ou escondida dentro de um bundle JavaScript, o navegador não consegue nem começar a buscá-la até toda essa corrente resolver. Você está basicamente escondendo a coisa mais importante da sua página atrás de uma caça ao tesouro.

<!-- Preload da imagem LCP com fetchpriority -->
<link
  rel="preload"
  as="image"
  href="/hero-2400.webp"
  fetchpriority="high"
  media="(min-width: 768px)"
/>
<link
  rel="preload"
  as="image"
  href="/hero-800.webp"
  fetchpriority="high"
  media="(max-width: 767px)"
/>
<!-- No elemento da imagem em si -->
<img
  src="/hero-2400.webp"
  alt="Product dashboard"
  width="2400"
  height="1200"
  fetchpriority="high"
  decoding="async"
  sizes="100vw"
  srcset="/hero-800.webp 800w, /hero-1600.webp 1600w, /hero-2400.webp 2400w"
/>

Regras-chave:

  • Nunca faça lazy-load do elemento LCP. Isso é inegociável.
  • Use fetchpriority="high" na imagem LCP — suportado em todos os navegadores modernos desde 2025.
  • Inline CSS crítico ou <link rel="preload"> de fonts que bloqueiam renderização.
  • Sirva imagens em AVIF com fallback WebP. AVIF é 30-50% menor que WebP em qualidade equivalente. Se você ainda está enviando WebP como formato primário em 2026, está deixando bytes na mesa.

LCP para Elementos de Texto

Quando seu elemento LCP é um heading ou parágrafo (super comum em sites de conteúdo), recursos que bloqueiam renderização viram seu inimigo:

<!-- Preload sua fonte primária -->
<link rel="preload" as="font" type="font/woff2" href="/fonts/inter-v.woff2" crossorigin />

<!-- Use font-display: optional para a pintura mais rápida -->
<style>
  @font-face {
    font-family: 'Inter';
    src: url('/fonts/inter-v.woff2') format('woff2');
    font-display: optional; /* Elimina layout shift de font swap */
  }
</style>

font-display: optional previne tanto FOIT quanto FOUT ao cair de volta para a fonte do sistema se a web font não estiver em cache. O tradeoff? Visitantes pela primeira vez veem a fonte do sistema. O ganho: zero CLS de font swapping e LCP mais rápido. Faremos esse tradeoff sempre.

Otimização do Interaction to Next Paint (INP)

INP é a métrica que separa bons sites de ótimos em 2026. A maioria das agências erra isso. Diferente de FID, que media apenas o delay de entrada da primeira interação, INP captura o ciclo de vida completo de cada interação: input delay, tempo de processamento e presentation delay — e reporta aproximadamente o pior (98º percentil).

Anatomia de uma Interação

[Usuário clica] → [Input Delay] → [Processamento de Evento] → [Presentation Delay] → [Próximo frame pintado]
                 ↑                ↑                            ↑
                 Bloqueado por    Seu click                    Navegador renderiza
                 main thread      handler roda                 mudanças do DOM

Reduzindo Input Delay

Input delay acontece quando a main thread está ocupada fazendo outra coisa quando o usuário toca. Os culpados usuais:

  1. Scripts de terceiros — Analytics, chat widgets, ferramentas A/B testing. O site corporativo típico carrega 15-30 scripts de terceiros, e cada um luta por tempo de main thread. É uma cena de multidão lá.
  2. Hydration storms — SPAs que fazem hydrate de toda a página de uma vez bloqueiam a main thread por 200-2000ms. Isso é uma eternidade quando alguém tenta tocar um botão.
  3. Long tasks — Qualquer tarefa JavaScript acima de 50ms atrasa input. Período.
// Quebra long tasks com scheduler.yield() — disponível em Chrome 129+
async function processLargeDataset(items) {
  for (let i = 0; i < items.length; i++) {
    processItem(items[i]);
    
    // Yield para a main thread a cada 5 items
    if (i % 5 === 0) {
      await scheduler.yield();
    }
  }
}

Para navegadores sem scheduler.yield(), aqui está o fallback:

function yieldToMain() {
  return new Promise(resolve => {
    setTimeout(resolve, 0);
  });
}

Reduzindo Tempo de Processamento

Aqui é onde vivem seus event handlers. A correção é arquitetural, não cosmética:

  • Debounce e throttle handlers caros (scroll, resize, input).
  • Mova computação para fora da main thread com Web Workers ou a API scheduler.postTask().
  • Use CSS para animações em vez de JavaScript. Mudanças de transform e opacity não acionam layout ou paint.
// Use scheduler.postTask() para trabalho não-urgente
button.addEventListener('click', async () => {
  // Urgente: feedback visual imediatamente
  button.classList.add('active');
  
  // Não-urgente: analytics, state updates
  scheduler.postTask(() => {
    analytics.track('button_clicked');
  }, { priority: 'background' });
  
  // Visível ao usuário mas não imediato
  scheduler.postTask(() => {
    updateDashboard();
  }, { priority: 'user-visible' });
});

Reduzindo Presentation Delay

Presentation delay é a lacuna entre seu event handler terminar e o navegador realmente pintar o próximo frame. O que causa:

  • Tamanho DOM excessivo — Páginas com mais de 1.400 elementos DOM mostram INP significativamente pior. A mediana do HTTP Archive 2025? 1.600 elementos no mobile. A maioria dos sites é muito inflada.
  • Seletores CSS complexos — Seletores profundamente aninhados forçam recálculos de estilo caros toda vez que algo muda.
  • Layout thrashing — Ler propriedades de layout como offsetHeight logo após escrever no DOM força layout síncrono. Esse aqui morde as pessoas constantemente. Eles nunca veem chegando.
// RUIM: Layout thrashing
elements.forEach(el => {
  const height = el.offsetHeight; // Força layout
  el.style.height = height + 10 + 'px'; // Invalida layout
});

// BOM: Batch lê, depois batch escreve
const heights = elements.map(el => el.offsetHeight); // Todas as leituras primeiro
elements.forEach((el, i) => {
  el.style.height = heights[i] + 10 + 'px'; // Todas as escritas segundo
});

Otimização do Cumulative Layout Shift (CLS)

CLS mede instabilidade visual — coisas pulando enquanto a página carrega ou durante interações. Google usa uma abordagem de "session window": shifts dentro de 1 segundo um do outro, limitados a 5 segundos por janela, são agrupados. CLS reporta a maior session window.

Os Culpados Usuais

Causa Correção Impacto
Imagens sem dimensões Adicione atributos width e height Alto
Conteúdo injetado dinamicamente (ads, embeds) Reserve espaço com min-height ou aspect-ratio Alto
Web fonts causando FOUT Use font-display: optional ou size-adjust Médio
CSS carregado tarde Inline CSS crítico, preload o resto Médio
Animações acionando layout Use transform em vez de top/left/width/height Baixo-Médio

A Propriedade CSS `aspect-ratio`

Não estou exagerando quando digo que essa propriedade sozinha eliminou uma classe inteira de problemas CLS da noite para o dia. Use em todos os lugares:

/* Reserve espaço para imagens */
img {
  aspect-ratio: attr(width) / attr(height);
  width: 100%;
  height: auto;
}

/* Reserve espaço para video embeds */
.video-embed {
  aspect-ratio: 16 / 9;
  width: 100%;
  background: #1a1a1a;
}

/* Reserve espaço para slots de ad */
.ad-slot-leaderboard {
  aspect-ratio: 728 / 90;
  min-height: 90px;
  contain: layout;
}

A Propriedade `content-visibility`

content-visibility: auto diz ao navegador para pular renderização de conteúdo off-screen. Isso reduz drasticamente custo de layout inicial e pode melhorar tanto CLS quanto INP:

.below-the-fold-section {
  content-visibility: auto;
  contain-intrinsic-size: auto 500px; /* Altura estimada para prevenir CLS */
}

Medimos reduções de 30-50% em tempo de renderização em páginas com muito conteúdo com essa técnica. Performance quase de graça. Não há boa razão para não usar em páginas com muito conteúdo.

Estratégias Específicas de Framework

Next.js (App Router, v15+)

Next.js 15 enviou Partial Prerendering (PPR) como stable, e honestamente — é um verdadeiro game-changer para LCP. Shells estáticos renderizam instantaneamente na edge; conteúdo dinâmico flui via React Suspense boundaries.

// app/page.tsx — Shell estático com island dinâmica
import { Suspense } from 'react';
import { HeroSection } from '@/components/HeroSection'; // Estático
import { PersonalizedOffers } from '@/components/PersonalizedOffers'; // Dinâmico

export default function HomePage() {
  return (
    <>
      <HeroSection /> {/* Renderizado em build time — LCP instantâneo */}
      <Suspense fallback={<OffersSkeleton />}>
        <PersonalizedOffers /> {/* Flui após shell */}
      </Suspense>
    </>
  );
}

O componente <Image> do Next.js lida com srcset, negociação AVIF/WebP e lazy-loading automaticamente. Mas — e isso confunde as pessoas constantemente — você ainda precisa definir priority em imagens LCP. Não vai adivinhar para você:

<Image
  src="/hero.jpg"
  alt="Hero"
  width={2400}
  height={1200}
  priority // Define fetchpriority="high" e desabilita lazy loading
  sizes="100vw"
/>

Nossa abordagem completa para builds Next.js com performance em primeiro lugar está em nossa página de capacidades de desenvolvimento Next.js.

Astro

A arquitetura zero-JavaScript-by-default do Astro significa que a maioria dos sites Astro passa em Core Web Vitals direto da caixa. O Web Almanac do HTTP Archive 2025 mostrou que sites Astro tinham a maior taxa de aprovação de Core Web Vitals de qualquer framework em 82%. Isso não é coincidência — é o que acontece quando o padrão é enviar zero client-side JS.

Os padrões-chave:

---
// src/pages/index.astro
import { Image } from 'astro:assets';
import heroImage from '../assets/hero.jpg';
---

<!-- Astro otimiza isso em build time para AVIF/WebP com srcset -->
<Image
  src={heroImage}
  alt="Hero"
  widths={[400, 800, 1600, 2400]}
  sizes="100vw"
  loading="eager"
  fetchpriority="high"
/>

<!-- Island interativa — só carrega JS quando visível -->
<SearchBar client:visible />

A diretiva client:visible significa que o JavaScript da search bar não carrega até o usuário scrollar para ela, mantendo a main thread limpa durante carga inicial. Mais na nossa abordagem de desenvolvimento Astro.

Considerações de Headless CMS

Com um headless CMS — Contentful, Sanity, Storyblok, o que você esteja rodando — o tempo de resposta da API do CMS se torna parte do seu TTFB. Ninguém pensa nisso até morder.

Nossos benchmarks em projetos de clientes:

CMS Resposta Média da API (CDN em Cache) Resposta Média da API (Origem) Notas
Contentful 45ms 180ms API GraphQL ligeiramente mais lenta que REST
Sanity 35ms 120ms Queries GROQ são rápidas; CDN é excelente
Storyblok 50ms 200ms API V2 melhorou significativamente
Strapi (Self-hosted) Variável Variável Depende inteiramente da sua infraestrutura

O padrão crítico: não chame APIs do CMS em tempo de requisição a menos que você genuinamente precise de personalização. Use ISR ou revalidação on-demand para servir páginas pré-construídas. Vimos times adicionarem 300ms+ ao seu TTFB apenas porque alguém conectou uma chamada fetch em um server component que deveria ter sido em cache. Enlouquecedor. Nossa prática de desenvolvimento headless CMS constrói isso por padrão.

Medição e Monitoramento em Produção

Dados de Lab vs. Field

Olha, dados de lab (Lighthouse, WebPageTest) te dizem o que poderia acontecer. Dados de field (CrUX, RUM) te dizem o que realmente acontece. Eles divergem — às vezes selvagemente. E quando stakeholders acenam com score Lighthouse 100 como troféu enquanto seus dados CrUX estão falhando? Yeah. Temos essa conversa bem mais frequente que gostaríamos.

Aqui está o que ferramentas de lab simplesmente não conseguem considerar:

  • Dispositivos lentos (o Android médio tem aproximadamente 1/5 da potência CPU de um iPhone 15)
  • Variabilidade de rede aí no mundo real
  • Extensões de navegador fazendo deus sabe o quê
  • Comportamento de script de terceiros em produção — coisas que agem completamente diferente do seu ambiente de staging

Stack de Monitoramento Recomendado (2026)

Ferramenta Tipo Custo Melhor Para
Google CrUX Field (28-days) Grátis Impacto SEO — isso é o que Google realmente usa
web-vitals.js Field (real-time) Grátis Pipeline RUM customizado
Vercel Speed Insights Field Grátis (com Vercel) Sites Next.js em Vercel
SpeedCurve Lab + Field $12-200/mo Benchmarking competitivo, filmstrips
Sentry Performance Field $26+/mo Vinculando desempenho a erros
DebugBear Lab + Field + CrUX $99+/mo Melhor rastreamento de mudanças CrUX que usamos

Configurando web-vitals.js

import { onLCP, onINP, onCLS } from 'web-vitals/attribution';

function sendToAnalytics(metric) {
  const body = {
    name: metric.name,
    value: metric.value,
    rating: metric.rating, // 'good', 'needs-improvement', 'poor'
    delta: metric.delta,
    id: metric.id,
    navigationType: metric.navigationType,
    // Dados de attribution — te diz POR QUE a métrica é ruim
    attribution: metric.attribution,
  };

  // Use sendBeacon para confiabilidade
  if (navigator.sendBeacon) {
    navigator.sendBeacon('/api/vitals', JSON.stringify(body));
  }
}

onLCP(sendToAnalytics);
onINP(sendToAnalytics);
onCLS(sendToAnalytics);

O build /attribution é crítico — adiciona informações diagnósticas como qual elemento foi o LCP, qual interação causou o pior INP e quais elementos se deslocaram para CLS. Sem ele você está voando cego. Apenas olhando para números sem zero contexto para o que realmente corrigir.

Técnicas Avançadas para 2026

Speculation Rules API

A Speculation Rules API (Chrome 121+, ~75% suporte de navegador em 2026) pré-renderiza páginas antes do usuário realmente clicar através. O resultado? LCP quase instantâneo em navegações subsequentes:

<script type="speculationrules">
{
  "prerender": [
    {
      "where": {
        "and": [
          { "href_matches": "/*" },
          { "not": { "href_matches": "/logout" } },
          { "not": { "href_matches": "/api/*" } }
        ]
      },
      "eagerness": "moderate"
    }
  ]
}
</script>

"eagerness": "moderate" pré-renderiza em hover — agressivo o suficiente para se sentir instantâneo, conservador o suficiente para não destruir a bandwidth dos seus usuários. Chegamos nisso após muito trial and error. É o sweet spot.

View Transitions API

Transições de view nativas (cross-document, suportadas em Chrome 126+) te dão animações suaves de página-para-página sem overhead de framework JavaScript. Elas diretamente melhoram desempenho percebido e reduzem CLS durante navegação:

@view-transition {
  navigation: auto;
}

::view-transition-old(root) {
  animation: fade-out 0.2s ease-out;
}

::view-transition-new(root) {
  animation: fade-in 0.2s ease-in;
}

Long Animation Frames (LoAF) API

LoAF substitui Long Tasks e te dá muito mais poder diagnóstico. Genuinamente desejo tivéssemos tido isso três anos atrás:

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (entry.duration > 100) {
      console.log('Long animation frame:', {
        duration: entry.duration,
        blockingDuration: entry.blockingDuration,
        scripts: entry.scripts.map(s => ({
          sourceURL: s.sourceURL,
          sourceFunctionName: s.sourceFunctionName,
          duration: s.duration,
        })),
      });
    }
  }
});
observer.observe({ type: 'long-animation-frame', buffered: true });

Isso te diz exatamente qual script e qual função causou o long frame. Passamos sessões inteiras de audit apenas olhando saída de LoAF, encontrando a smoking gun em minutos em vez de horas. Para debug INP, é a melhor ferramenta que existe agora. Nada mais chega perto.

O Impacto nos Negócios: Números Reais

Otimização de desempenho não é projeto de vaidade. Não é algo que você aprova porque um desenvolvedor acha que seria legal. De estudos de caso 2025:

  • Vodafone melhorou LCP em 31%, resultando em 8% mais vendas.
  • Tokopedia reduziu INP em 40%, aumentando session duration em 15%.
  • NDTV melhorou CLS em 55%, reduzindo bounce rate em 50%.
  • Rakuten 24 melhorou CLS em 0.2 pontos, acionando aumento de 33.1% em revenue por visitor.

Nossos próprios dados de cliente na Social Animal mostram sites passando nas três Core Web Vitals vendo uma média de 23% menor bounce rate e 12% maior conversion rate comparado com baselines pré-otimização.

Para ecommerce, a matemática é morta-simples: uma melhoria de 1 segundo em LCP se correlaciona com aumento de conversão de 2-5%. Em uma loja de $10M/ano, são $200K-$500K em receita adicional. O custo de otimização? Uma fração disso. Verifique nossa página de preços para específicos, ou fale conosco direto para conversar sobre sua situação.

Perguntas Frequentes

O que são as métricas Core Web Vitals em 2026? Os três Core Web Vitals são Largest Contentful Paint (LCP), Interaction to Next Paint (INP), e Cumulative Layout Shift (CLS). INP substituiu First Input Delay (FID) lá em março de 2024 e ainda é a métrica de responsividade. Google sugeriu uma métrica Smoothness mas ainda não a adicionou como Core Web Vital.

Quanto Core Web Vitals afetam rankings SEO? São um sinal de ranking confirmado dentro dos sinais de page experience do Google, mas funcionam mais como um tiebreaker que um fator primário — relevância de conteúdo ainda domina. Onde realmente têm impacto é comportamento do usuário: bounce rate, engagement, time on site. Essas coisas indiretamente afetam rankings de formas que são difíceis de atribuir diretamente mas impossíveis de ignorar. Sites passando em todos os Core Web Vitals consistentemente mostram melhores números de engagement, e isso aumenta ao longo do tempo.

Qual é um bom score INP em 2026? 200 milissegundos ou menos, medido no 75º percentil de dados de usuário reais. Entre 200ms e 500ms precisa de melhoria. Acima de 500ms é ruim. O INP médio de website no mobile senta em aproximadamente 280ms desde o início de 2026 — significando que a maioria dos sites ainda não passa. Deixe isso afundar.

Por que meu score Lighthouse é diferente dos meus dados CrUX? Porque estão medindo fundamentalmente coisas diferentes. Lighthouse roda em um ambiente simulado com CPU e rede throttled em um único carregamento de página. Dados CrUX vêm de usuários reais de Chrome sobre uma janela de 28 dias rolante através de todas as páginas na sua origem. A lacuna vem de diversidade de dispositivo (usuários reais em Android phones lentos), comportamento de script de terceiros em produção, distância geográfica de seus servidores, e o fato que CrUX captura a session completa — toda interação para INP, todo layout shift para CLS — enquanto Lighthouse captura um load. Vimos sites marcar 95+ em Lighthouse e falhar CrUX completamente. Não confie apenas em dados de lab.

Usar um headless CMS ajuda ou prejudica Core Web Vitals? Uma arquitetura headless CMS fundamentalmente ajuda porque desacopla a camada de apresentação do gerenciamento de conteúdo. Você pode pareá-la com frameworks modernos como Next.js ou Astro com renderização edge, servindo HTML estático ou server-rendered com JavaScript mínimo. Plataformas monolíticas tradicionais — WordPress sem otimização pesada, Drupal direto da caixa — tipicamente enviam bem mais JavaScript e têm TTFB mais lento. A coisa-chave: tenha certeza que chamadas de API do CMS acontecem em build time ou são cacheadas agressivamente, não disparadas a cada requisição.

Como corrijo um score INP ruim causado por scripts de terceiros? Comece auditando com a Long Animation Frames API ou Chrome DevTools Performance panel para identificar quais scripts estão comendo a main thread. Então: carregue scripts não-críticos com async ou defer, use setTimeout ou requestIdleCallback para atrasar sua inicialização, considere mover scripts de terceiros para fora da main thread via web worker (Partytown é ótimo para isso), e — essa é a parte que ninguém quer ouvir — implacavelmente remova qualquer coisa que não forneça valor de negócio mensurável. Aquele chat widget que ninguém usa? Mate. Vimos sites descer de 500ms+ INP para menos de 150ms apenas adiando chat widgets e ferramentas A/B testing. É quase sempre inflação de terceiros.

Qual é a forma mais rápida de melhorar LCP em um site Next.js? Em ordem de impacto: habilite Partial Prerendering (PPR) para shells estáticos instantâneos, deploy para runtime edge (Vercel Edge ou Cloudflare), defina priority no seu componente <Image> LCP, pare de bloqueio de renderização com client components desnecessários acima da fold, e preload fonts críticas. Mas aqui está o que realmente vemos na prática: a causa-raiz é data fetching client-side que deveria ser um server component. Mover um único componente de 'use client' para um server component pode rapar 500ms ou mais de LCP. É selvagem quão frequente isso resulta ser o fix inteiro.

Com que frequência Google atualiza limites de Core Web Vitals? Infrequentemente. A grande mudança foi trocar FID por INP, anunciado em maio de 2023 e colocado em prática em março de 2024. Os valores de limiar reais — 2.5s para LCP, 200ms para INP, 0.1 para CLS — não se moveram desde que foram introduzidos. Google tipicamente dá aviso de 6-12 meses antes de qualquer coisa mudar. Mas o time do Chrome continuamente ajusta como métricas são calculadas sob o capô, então você precisa manter olho em seus dados de field mesmo quando os limites se mantêm estáveis. Coisas mudam sem ninguém anunciar.