Capa do Ebook gratuito Performance Front-End: Otimizando Core Web Vitals sem Mistério

Performance Front-End: Otimizando Core Web Vitals sem Mistério

Novo curso

19 páginas

Fundamentos práticos de Core Web Vitals e objetivos de performance

Capítulo 1

Tempo estimado de leitura: 15 minutos

+ Exercício

O que são Core Web Vitals na prática

Core Web Vitals (CWV) são um conjunto de métricas que medem, com foco no usuário, se uma página “parece rápida”, “responde rápido” e “não fica pulando” enquanto carrega e durante o uso. Elas não medem apenas tempo de download ou tamanho de arquivos; elas traduzem a experiência percebida em números observáveis. Na prática, CWV servem como objetivos de performance que você pode acompanhar ao longo do tempo, comparar entre páginas e usar para priorizar melhorias com impacto real.

As três métricas principais são:

  • LCP (Largest Contentful Paint): quanto tempo leva para o maior elemento visível “principal” aparecer na tela (geralmente hero image, banner, título grande ou bloco de conteúdo).
  • INP (Interaction to Next Paint): quão rápido a página responde visualmente após uma interação do usuário (clique, toque, teclado). Substitui o FID como métrica principal de responsividade.
  • CLS (Cumulative Layout Shift): quanto a página “pula” inesperadamente durante o carregamento e uso, gerando cliques errados e sensação de instabilidade.

Essas métricas são avaliadas com base em dados reais de usuários (field data) e também podem ser simuladas em laboratório (lab data). Entender a diferença é essencial para definir objetivos realistas e para não otimizar “para o teste” em vez de otimizar para pessoas.

Objetivos de performance: metas numéricas e por que elas existem

Um objetivo de performance bem definido evita discussões vagas como “o site está lento” e transforma a conversa em critérios verificáveis. Para CWV, as metas recomendadas (para a maioria dos sites) são:

  • LCP: bom se ≤ 2,5 s; precisa melhorar entre 2,5 s e 4,0 s; ruim se > 4,0 s.
  • INP: bom se ≤ 200 ms; precisa melhorar entre 200 ms e 500 ms; ruim se > 500 ms.
  • CLS: bom se ≤ 0,1; precisa melhorar entre 0,1 e 0,25; ruim se > 0,25.

Além das metas, existe um detalhe importante: a avaliação costuma considerar percentis (por exemplo, p75). Isso significa que você não quer apenas que “na média” esteja bom; você quer que a maior parte dos usuários tenha uma experiência boa. Em termos práticos, mirar no p75 reduz o risco de uma parcela relevante de usuários (com dispositivos mais lentos, rede pior, CPU ocupada) ficar com experiência ruim.

Continue em nosso aplicativo

Você poderá ouvir o audiobook com a tela desligada, ganhar gratuitamente o certificado deste curso e ainda ter acesso a outros 5.000 cursos online gratuitos.

ou continue lendo abaixo...
Download App

Baixar o aplicativo

Como transformar metas em critérios de aceite

Para usar CWV como objetivo de engenharia, transforme as metas em critérios de aceite por tipo de página e por contexto:

  • Por template: home, listagem, produto/artigo, checkout, busca interna.
  • Por dispositivo: mobile costuma ser o foco principal; desktop pode ter metas mais fáceis, mas não deve ser ignorado.
  • Por rede: 4G/3G (ou “slow 4G”) para simulações; no campo, haverá variação.

Exemplo de critério de aceite para uma página de produto: “No mobile, p75 de LCP ≤ 2,5 s, p75 de INP ≤ 200 ms e p75 de CLS ≤ 0,1, medidos em produção por 28 dias; em laboratório, LCP ≤ 2,5 s e CLS ≤ 0,1 em ‘slow 4G’ e CPU 4x slowdown”.

Field data vs lab data: como usar cada um sem confusão

Field data (dados de campo) vem de usuários reais. Ele captura diversidade de dispositivos, redes, extensões, cache, rotas de navegação e comportamento. É o melhor indicador de experiência real, mas tem limitações: demora para refletir mudanças, pode ter ruído e nem sempre permite reproduzir exatamente um problema.

Lab data (dados de laboratório) vem de testes controlados (por exemplo, Lighthouse/DevTools). Ele é ótimo para depurar, comparar antes/depois e iterar rápido. Porém, não representa toda a variabilidade do mundo real e pode ser “enganado” por condições artificiais.

Uso prático recomendado:

  • Use field para definir prioridade (quais páginas e usuários estão sofrendo) e para validar resultado (melhorou de verdade para usuários).
  • Use lab para diagnosticar (o que está causando) e para testar hipóteses rapidamente.

Entendendo LCP: o que realmente atrasa o “conteúdo principal”

LCP mede o tempo até o maior elemento de conteúdo visível ser renderizado. Na prática, LCP costuma ser afetado por quatro grupos de causas:

  • Tempo de resposta do servidor (TTFB alto): o navegador fica esperando o HTML inicial.
  • Bloqueio de renderização: CSS e JS que impedem a pintura inicial.
  • Carregamento do recurso do LCP: imagem grande sem prioridade, fonte que atrasa texto, ou mídia pesada.
  • Tempo de renderização: CPU ocupada com JS, layout complexo, hidratação pesada.

Como identificar qual elemento é o LCP

Antes de otimizar, descubra qual é o elemento que está sendo contado como LCP. Em laboratório, ferramentas costumam indicar o elemento (por exemplo, uma imagem hero ou um bloco de texto). Em produção, você pode instrumentar via API de Performance para registrar o LCP e o seletor/URL do recurso associado.

Passo a passo prático para melhorar LCP (sem “chutar”)

Use este fluxo para atacar LCP de forma sistemática:

  • 1) Confirmar o elemento LCP: é imagem? texto? vídeo? um container?
  • 2) Medir TTFB: se o HTML demora a chegar, otimizações de front-end terão teto baixo.
  • 3) Verificar bloqueios: CSS crítico, JS no head, fontes bloqueando texto.
  • 4) Priorizar o recurso do LCP: garantir que a imagem/fonte principal seja solicitada cedo e com prioridade.
  • 5) Reduzir trabalho no main thread: menos JS antes do LCP, menos hidratação, menos layout thrashing.

Exemplo prático: se o LCP é uma imagem hero, você quer que ela seja descoberta cedo, baixada rápido e decodificada sem atrasos. Algumas ações típicas:

  • Evitar que a URL da imagem só apareça depois de executar JS.
  • Usar formatos modernos (AVIF/WebP) e dimensões adequadas.
  • Definir fetchpriority e/ou preload quando fizer sentido.
<!-- Exemplo: imagem LCP com prioridade e dimensões definidas -->
<img src="/img/hero.avif" width="1200" height="600" alt="" fetchpriority="high" decoding="async" />

<!-- Opcional: preload quando a imagem é sempre a LCP e está no topo -->
<link rel="preload" as="image" href="/img/hero.avif" />

O objetivo não é “preload em tudo”, e sim garantir que o recurso do LCP não fique competindo com dezenas de outros downloads iniciados antes dele.

Entendendo INP: responsividade real, não só “tempo de clique”

INP mede a latência de interações ao longo da vida da página, focando na pior (ou nas piores) interações representativas. Ele captura o tempo entre o usuário interagir e a próxima atualização visual ocorrer. Na prática, INP piora quando o navegador está ocupado e não consegue processar eventos rapidamente.

Causas comuns de INP ruim:

  • Long tasks no main thread (tarefas > 50 ms), geralmente por JS pesado.
  • Handlers de evento caros: clique dispara validações, re-renderizações, cálculos, parsing.
  • Renderização cara: mudanças de DOM que causam layout/reflow e paint custosos.
  • Terceiros: tags de analytics/ads que competem por CPU.

Como pensar em INP como orçamento de tempo

Para manter INP ≤ 200 ms, você precisa que o caminho crítico de uma interação (event handling + render) seja curto. Um modelo mental útil é: “cada interação importante deve caber em poucos frames”. Em telas de 60 Hz, um frame tem ~16,7 ms; não significa que você precisa de 16 ms, mas ajuda a visualizar que 200 ms é um limite que pode ser estourado facilmente por algumas tarefas longas.

Passo a passo prático para melhorar INP

  • 1) Descobrir quais interações estão ruins: cliques em menu, abrir modal, filtrar lista, digitar em busca.
  • 2) Encontrar long tasks: identificar scripts e funções que bloqueiam o main thread.
  • 3) Quebrar trabalho: dividir tarefas longas em partes menores, adiar trabalho não essencial.
  • 4) Reduzir re-render: evitar atualizações globais quando só um componente muda.
  • 5) Controlar terceiros: carregar sob demanda, atrasar, remover o que não agrega.

Exemplo prático: um clique em “Filtrar” dispara uma função que percorre milhares de itens e atualiza o DOM inteiro. Em vez disso, você pode:

  • Pré-computar índices (quando possível) fora do caminho da interação.
  • Paginar/virtualizar listas grandes.
  • Atualizar apenas a parte visível.
// Exemplo conceitual: quebrando uma tarefa longa em partes menores
function processInChunks(items, chunkSize, onChunk, onDone) {
  let i = 0;
  function run() {
    const end = Math.min(i + chunkSize, items.length);
    for (; i < end; i++) onChunk(items[i]);
    if (i < items.length) {
      // libera o main thread antes de continuar
      setTimeout(run, 0);
    } else {
      onDone();
    }
  }
  run();
}

Esse padrão não resolve tudo, mas ilustra a ideia central: evitar bloquear o main thread por tempo demais durante uma interação.

Entendendo CLS: estabilidade visual e previsibilidade

CLS mede a soma de mudanças inesperadas de layout. O ponto-chave é “inesperadas”: se o usuário interage e a interface muda como resultado direto (por exemplo, abrir um accordion), isso normalmente não conta como shift problemático. O que conta é quando elementos mudam de lugar sem o usuário pedir, como quando uma imagem carrega e empurra o texto, ou quando um banner aparece no topo e desloca tudo.

Causas comuns de CLS alto:

  • Imagens/iframes sem dimensões: o navegador não reserva espaço.
  • Conteúdo injetado acima do conteúdo existente: banners, avisos, ads.
  • Fontes web que trocam métricas e mudam o tamanho do texto.
  • Componentes que expandem após carregar dados sem reservar espaço.

Passo a passo prático para reduzir CLS

  • 1) Reservar espaço para mídia: sempre definir width/height ou usar aspect-ratio.
  • 2) Evitar inserções no topo: se precisar mostrar um banner, prefira sobrepor (overlay) ou reservar área fixa desde o início.
  • 3) Tratar fontes: escolher estratégia de carregamento que minimize mudanças visuais e ajustar fallback.
  • 4) Skeletons com altura estável: placeholders devem ter dimensões próximas do conteúdo final.
/* Exemplo: reservar proporção para evitar shift em imagens responsivas */
.hero {
  aspect-ratio: 16 / 9;
  width: 100%;
  overflow: hidden;
}
.hero img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

Para componentes que dependem de dados (por exemplo, um card que mostra preço e parcelamento), evite renderizar “nada” e depois empurrar o layout. Renderize um placeholder com a mesma altura aproximada e troque o conteúdo sem alterar o fluxo.

Orçamentos de performance: como definir limites além das métricas

Metas de CWV dizem “como está a experiência”. Orçamentos de performance dizem “quanto você pode gastar” para manter a experiência boa. Eles ajudam a prevenir regressões quando o produto cresce.

Exemplos de orçamentos úteis:

  • JavaScript: limite de KB transferidos e, principalmente, limite de tempo de execução no main thread.
  • Imagens: tamanho máximo para imagens acima da dobra e número de requests iniciais.
  • Fontes: número de famílias/variantes e tamanho total.
  • Terceiros: número de scripts e impacto de CPU.

Um orçamento simples e prático pode ser: “na rota de produto, até 170 KB de JS comprimido no carregamento inicial” e “nenhuma tarefa no main thread acima de 200 ms durante o carregamento”. O valor exato depende do seu público e do tipo de aplicação, mas o importante é existir um limite que acione revisão quando ultrapassado.

Como medir na prática: checklist de instrumentação e leitura

Para trabalhar com CWV de forma contínua, você precisa de um ciclo de medição. Um checklist prático:

  • 1) Medir em laboratório para depurar: rode auditorias com condições controladas e registre LCP/INP/CLS.
  • 2) Medir em produção para validar: capture CWV via APIs do navegador e envie para seu endpoint de métricas.
  • 3) Segmentar: separar por página/template, dispositivo, conexão, país, e também por “usuários novos vs recorrentes”.
  • 4) Correlacionar: quando CWV piora, correlacione com deploys, campanhas, mudanças de terceiros.

Exemplo de instrumentação conceitual (simplificada) para capturar métricas web vitals e enviar para um endpoint. A implementação real pode variar, mas a ideia é registrar e anexar contexto (rota, device, conexão):

// Pseudocódigo: enviar métricas para um endpoint
function sendMetric(name, value, attrs = {}) {
  navigator.sendBeacon(
    '/metrics',
    JSON.stringify({ name, value, attrs, ts: Date.now() })
  );
}

// Exemplo: ao obter LCP/CLS/INP via biblioteca ou PerformanceObserver,
// chame sendMetric('LCP', lcpValue, { route: location.pathname })

Mesmo sem entrar em detalhes de biblioteca, o ponto é: sem dados de produção, você pode “melhorar no laboratório” e ainda assim não mover o p75 real, porque o gargalo pode estar em dispositivos mais fracos, em rotas específicas, em conteúdo dinâmico ou em scripts de terceiros que não aparecem no seu cenário de teste.

Priorização: o que atacar primeiro quando tudo parece importante

Quando você mede, normalmente encontra vários problemas ao mesmo tempo. Para priorizar, use uma matriz simples baseada em impacto no usuário e esforço:

  • Primeiro: problemas que afetam o elemento LCP (acima da dobra) e shifts visíveis (CLS), porque impactam a primeira impressão e a leitura.
  • Depois: INP em interações críticas do funil (buscar, filtrar, adicionar ao carrinho, login, finalizar).
  • Em paralelo: reduzir JS e terceiros, porque melhora LCP e INP ao mesmo tempo.

Um método prático é escolher 1 ou 2 templates com maior tráfego e pior p75, e trabalhar neles até estabilizar. Otimizar “um pouco em tudo” frequentemente não move as métricas o suficiente para sair da zona “precisa melhorar”.

Exemplos de objetivos por tipo de página

Nem toda página tem o mesmo perfil. Definir objetivos por tipo de página torna as metas mais realistas e acionáveis.

Página de conteúdo (artigo/blog/documentação)

  • LCP: geralmente dominado por título e imagem hero; meta ≤ 2,5 s.
  • CLS: atenção a embeds, iframes e imagens no corpo; meta ≤ 0,1.
  • INP: costuma ser bom por natureza, mas pode piorar com scripts de comentários/ads; meta ≤ 200 ms.

Listagem com filtros (e-commerce, catálogo, busca)

  • LCP: pode ser o grid inicial; meta ≤ 2,5 s.
  • INP: crítico em filtros, ordenação, paginação; meta ≤ 200 ms.
  • CLS: cuidado com carregamento incremental que muda alturas; meta ≤ 0,1.

Aplicação com muita interatividade (dashboard, web app)

  • LCP: ainda importa, mas o maior risco é CPU/JS; meta ≤ 2,5 s (ou uma meta interna ligeiramente mais flexível se houver justificativa).
  • INP: principal indicador de qualidade; meta ≤ 200 ms.
  • CLS: modais, toasts e painéis devem ser previsíveis; meta ≤ 0,1.

Armadilhas comuns ao definir metas de Core Web Vitals

Otimizar apenas para o laboratório

Se você só olha o Lighthouse local, pode ignorar problemas que só aparecem em produção: cache frio, conteúdo personalizado, A/B tests, scripts de terceiros, dispositivos low-end. Use laboratório para depurar, mas valide com dados reais.

Confundir “carregou” com “está utilizável”

Uma página pode carregar rápido e ainda assim ter INP ruim porque o main thread está ocupado com hidratação, parsing de bundles, ou re-renderizações. Por isso CWV é útil: ele mede o que o usuário sente, não apenas o que a rede entregou.

Preload e prioridades usados sem critério

Marcar tudo como prioridade alta cria competição e pode piorar o LCP. O objetivo é priorizar o que realmente define a primeira dobra: o recurso do LCP e CSS essencial.

Corrigir CLS “na marra” com alturas fixas erradas

Reservar espaço é correto, mas usar alturas fixas que não batem com o conteúdo final pode criar espaços em branco ou cortes. Prefira proporções (aspect-ratio) e skeletons que se aproximem do layout final.

Roteiro prático: criando um plano de performance orientado a CWV

Para fechar o capítulo com algo aplicável, aqui vai um roteiro que você pode executar em um projeto real:

  • 1) Escolha 2 templates com maior tráfego e piores métricas (ex.: home e produto).
  • 2) Defina metas (LCP/INP/CLS) por template e por mobile.
  • 3) Instrumente produção para capturar CWV com contexto (rota, device, conexão).
  • 4) Rode testes de laboratório para cada template e registre: elemento LCP, recursos bloqueantes, long tasks, shifts.
  • 5) Crie backlog por causa raiz: LCP (servidor/prioridade/imagem/CSS/JS), INP (long tasks/handlers/render), CLS (dimensões/injeções/fontes).
  • 6) Aplique correções em pequenos lotes e valide em laboratório e em produção.
  • 7) Estabeleça guardrails: orçamentos de JS/imagens/terceiros e checagens em PR/CI para evitar regressões.

Esse roteiro ajuda a manter o foco: medir, identificar o gargalo dominante, corrigir com intenção e validar com dados reais. A partir daí, CWV deixa de ser um “misterioso score” e vira um sistema de objetivos de performance que guia decisões de front-end no dia a dia.

Agora responda o exercício sobre o conteúdo:

Ao definir critérios de aceite usando Core Web Vitals, por que é recomendado mirar no percentil p75 em vez de olhar apenas a média?

Você acertou! Parabéns, agora siga para a próxima página

Você errou! Tente novamente.

O p75 foca na experiência da maioria dos usuários, não apenas na média. Assim, reduz o risco de uma parcela relevante ter LCP/INP/CLS ruins em condições mais lentas (rede, CPU, dispositivo).

Próximo capitúlo

Configuração do ambiente de medição e consistência de testes

Arrow Right Icon
Baixe o app para ganhar Certificação grátis e ouvir os cursos em background, mesmo com a tela desligada.