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

Diagnóstico de LCP, INP e CLS com DevTools e Lighthouse

Capítulo 3

Tempo estimado de leitura: 14 minutos

+ Exercício

O que você está tentando diagnosticar (sem voltar aos fundamentos)

Diagnosticar LCP, INP e CLS é transformar uma métrica “ruim” em uma lista curta de causas prováveis, evidências e ações. DevTools e Lighthouse se complementam: o Lighthouse dá um retrato automatizado com auditorias e oportunidades; o DevTools permite ver a linha do tempo real do carregamento, renderização e interações, atribuindo custo a recursos, scripts e mudanças de layout.

Um diagnóstico útil responde a perguntas objetivas: qual elemento foi o LCP e por quê demorou? qual interação gerou o INP e qual parte do processamento consumiu tempo? quais elementos mudaram de posição e o que disparou essas mudanças? A partir daí, você consegue priorizar correções com alto impacto.

Diagnóstico de LCP com DevTools

1) Identificar o elemento de LCP e o momento exato

No Chrome DevTools, a forma mais direta é usar o painel Performance e observar o evento de LCP na trilha de “Timings”.

  • Abra a página em uma janela normal (não precisa ser anônima, mas evite extensões que alterem o DOM).
  • DevTools > Performance.
  • Marque Web Vitals (quando disponível) e/ou Screenshots para correlacionar visualmente.
  • Clique em Record e recarregue a página (Ctrl/Cmd+R).
  • Ao parar a gravação, procure na trilha de Timings um marcador de LCP. Clique nele.

Ao selecionar o marcador, o DevTools costuma mostrar detalhes do elemento (por exemplo, um <img>, um bloco de texto, um <h1> ou um background). Esse é o “candidato” que o navegador considerou como maior conteúdo visível no viewport no momento do LCP.

2) Decompor o LCP em fases (onde o tempo foi gasto)

O LCP geralmente é atrasado por uma combinação de: tempo de resposta do servidor, bloqueio de renderização por CSS/JS, prioridade/descoberta tardia do recurso (imagem/fonte), e custo de renderização (layout/paint) quando o elemento finalmente pode aparecer.

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

No DevTools, você consegue evidenciar isso com três áreas:

  • Network: quando o recurso do LCP foi descoberto, quando começou a baixar e quando terminou.
  • Performance: quanto tempo foi gasto em scripting, style/layout e paint antes do LCP.
  • Rendering/Layer (quando necessário): se há custos de composição/pintura altos.

Passo a passo para correlacionar:

  • No Performance, selecione uma janela de tempo que vai do início do carregamento até logo após o LCP.
  • Observe a trilha principal (Main). Se houver longas tarefas (long tasks) antes do LCP, elas podem estar atrasando o processamento de CSS/JS e a renderização.
  • Abra Network e filtre pelo recurso do elemento LCP (por nome do arquivo, tipo ou iniciador). Verifique: Start Time, TTFB, Download.

Um padrão comum: o LCP é uma imagem grande, mas ela começa a baixar tarde porque o HTML/JS só a insere depois, ou porque o navegador não a priorizou. Outro padrão: o CSS crítico chega tarde e bloqueia a renderização, então o elemento existe mas não pode ser pintado.

3) Verificar se o LCP é imagem, texto ou background (e implicações)

O tipo do elemento muda o tipo de correção:

  • Imagem (<img>): foco em prioridade, tamanho/formatos, preload e evitar lazy-load indevido acima da dobra.
  • Texto: foco em CSS bloqueante, carregamento de fontes e custo de renderização (ex.: CSS pesado, muitas regras, recalculations).
  • Background via CSS: pode ser mais difícil de priorizar; frequentemente exige preload e revisão de como o background é aplicado.

Como confirmar rapidamente:

  • DevTools > Elements: selecione o elemento indicado no LCP (quando disponível).
  • Verifique se é <img> ou se a imagem está em background-image no painel de estilos.

4) Checar sinais de bloqueio por CSS e fontes

Mesmo sem repetir conceitos básicos, na prática você quer evidências de bloqueio:

  • No Network, filtre por CSS e veja se há arquivos grandes chegando tarde.
  • Em Performance, procure por períodos longos de Recalculate Style e Layout antes do LCP.
  • No Network, filtre por Font e veja se fontes essenciais chegam tarde e se há múltiplas variações (weights) baixadas.

Se o LCP for texto e você notar fontes baixando tarde, o texto pode estar aguardando a fonte (dependendo da estratégia de carregamento). Se o LCP for imagem, mas o CSS é pesado e bloqueia a renderização, o download pode até terminar cedo, mas o paint do elemento ocorre tarde.

5) Confirmar prioridade e descoberta do recurso do LCP

Para imagens, um diagnóstico recorrente é: “a imagem do herói não foi priorizada”. Você consegue verificar isso no Network:

  • Abra o recurso da imagem e observe Priority (quando a coluna estiver habilitada).
  • Veja o Initiator: foi o HTML parser? foi CSS? foi um script? Se foi script, a descoberta pode ter sido tardia.

Se a imagem do LCP aparece como iniciada por um script após um bundle grande, isso é um forte indício de que o caminho crítico está atrasando a descoberta do recurso.

6) Exemplo prático: LCP atrasado por imagem descoberta tarde

Cenário: o LCP é a imagem do banner principal, mas ela só começa a baixar após a execução de um bundle.

Como você veria isso:

  • No Performance, antes do LCP há uma long task de scripting.
  • No Network, a imagem inicia depois dessa long task, com Initiator apontando para um script.

O diagnóstico fica: “LCP atrasado por descoberta tardia do recurso e competição com JS no main thread”. A correção típica envolve garantir que o recurso seja descoberto cedo (por HTML/CSS) e que não esteja sendo adiado por hidratação/renderização client-side.

Diagnóstico de INP com DevTools

1) Encontrar interações lentas e decompor o tempo (input, processamento, apresentação)

INP está ligado a interações reais do usuário. Em laboratório, você precisa simular interações e observar o custo no main thread. O DevTools ajuda a identificar: qual evento disparou, quanto tempo o handler executou, e quanto tempo foi gasto até o próximo frame ser apresentado.

Passo a passo no DevTools:

  • DevTools > Performance.
  • Clique em Record.
  • Interaja com a página (clique em botões, abra menus, digite em campos, faça scroll em componentes que executam JS).
  • Pare a gravação.

Agora procure por:

  • Interações (quando o DevTools agrupa eventos de input) e marcadores relacionados.
  • Long tasks na trilha Main durante ou logo após a interação.
  • Eventos como click, pointerdown, keydown no “Event Log” (dependendo da versão do DevTools).

2) Usar o painel Performance para achar o “culpado” no main thread

O INP ruim quase sempre aparece como: você interage, mas o main thread está ocupado (JS pesado, layout síncrono, renderização cara). O objetivo é chegar a uma função, arquivo e linha.

Passo a passo:

  • Na gravação, selecione o intervalo logo após a interação (zoom na área onde o atraso é visível).
  • Na trilha Main, clique na long task (barra longa amarela/roxa, dependendo do tipo).
  • No painel inferior, abra a aba Bottom-Up para ver quais funções consumiram mais tempo.
  • Use Call Tree para entender a cadeia de chamadas.
  • Clique na função para abrir o arquivo no painel Sources.

Se o tempo estiver em “Recalculate Style” ou “Layout”, isso indica que a interação disparou mudanças no DOM/CSS que exigiram recalcular estilos e reposicionar elementos. Se estiver em scripting, você procura handlers, validações, serializações, renderizações, loops e trabalho síncrono.

3) Identificar padrões típicos que degradam INP

Durante o diagnóstico, procure por padrões recorrentes:

  • Handlers muito grandes: um clique dispara várias operações (fetch + processamento + render) tudo no mesmo tick.
  • Renderização excessiva: frameworks re-renderizando grandes subárvores após cada tecla.
  • Leituras e escritas de layout intercaladas: medir (offsetHeight, getBoundingClientRect) e logo depois escrever estilo repetidamente, causando layout thrashing.
  • JSON/parse/stringify pesado no caminho da interação.
  • Bibliotecas de terceiros executando trabalho em resposta a eventos (analytics, tag managers, widgets).

4) Exemplo prático: clique em “Filtrar” trava por 400ms

Cenário: ao clicar em “Filtrar”, a UI demora a responder.

Como diagnosticar:

  • Grave no Performance e clique no botão.
  • Encontre a long task após o evento click.
  • Em Bottom-Up, veja se o tempo está em uma função de renderização (ex.: renderResults) ou em uma rotina de filtro (ex.: applyFilters).
  • Se houver muito tempo em Layout, abra o trecho e observe se o código lê layout dentro de loops.

O diagnóstico final deve ser específico: “o handler de clique executa filtragem O(n*m) e atualiza o DOM item a item, causando múltiplos layouts; isso ocupa o main thread por ~400ms e degrada a responsividade”.

5) Complemento: usar o painel Performance monitor e o painel Rendering

Para interações, às vezes é útil observar FPS e trabalho de renderização:

  • DevTools > Command Menu (Ctrl/Cmd+Shift+P) > procure por Performance monitor.
  • Observe CPU, JS heap, DOM nodes e FPS enquanto interage.
  • Em More tools > Rendering, habilite Paint flashing para ver o que repinta ao interagir.

Se um pequeno hover repinta uma área enorme, ou se um clique dispara repaints contínuos, você tem um indício de custo de renderização que pode afetar a latência percebida e, em casos, o INP.

Diagnóstico de CLS com DevTools

1) Encontrar “Layout Shifts” e ver as causas

O DevTools oferece uma trilha específica para mudanças de layout no painel Performance. O objetivo é identificar quais elementos se moveram e qual foi o gatilho (imagem sem dimensões, inserção de banner, fonte trocando, componente expandindo etc.).

Passo a passo:

  • DevTools > Performance.
  • Ative Screenshots.
  • Grave e recarregue a página.
  • Durante o carregamento, observe a trilha Experience (ou similar) e procure por Layout Shift.
  • Clique em um evento de Layout Shift.

Ao selecionar um Layout Shift, o DevTools costuma destacar visualmente as áreas que mudaram e listar os “nodes” envolvidos. Isso é ouro para diagnóstico: você deixa de “achar” e passa a “ver” o que se moveu.

2) Correlacionar o shift com a requisição ou script que o provocou

Depois de identificar o shift, você quer responder: o que aconteceu imediatamente antes?

  • No Performance, com o shift selecionado, olhe alguns milissegundos antes na trilha Main: houve execução de script? houve aplicação de estilos? houve carregamento de fonte?
  • No Network, verifique se algum recurso terminou de baixar naquele momento (imagem, CSS, fonte, script de terceiro).

Exemplos de correlação:

  • Shift ocorre no exato momento em que uma imagem termina de baixar e é inserida sem dimensões reservadas.
  • Shift ocorre quando um script injeta um banner no topo (ex.: consentimento, promoções).
  • Shift ocorre quando a fonte web aplica e muda métricas do texto (troca de fonte).

3) Usar “Layout Shift Regions” para enxergar o impacto

No painel Rendering, existe a opção de destacar regiões de layout shift (o nome pode variar por versão, mas a ideia é a mesma). Isso ajuda a reproduzir e enxergar shifts que acontecem rápido.

  • DevTools > More tools > Rendering.
  • Habilite a visualização de Layout Shift Regions.
  • Recarregue e observe as áreas destacadas quando ocorrerem shifts.

4) Exemplo prático: CLS causado por card de produto que “cresce” após carregar preço

Cenário: uma grade de produtos carrega rapidamente, mas os preços chegam depois e empurram o layout.

Como diagnosticar:

  • Grave no Performance e recarregue.
  • Clique no evento de Layout Shift e veja quais nós mudaram (provavelmente o container do preço e elementos abaixo).
  • Volte alguns ms e veja se houve uma requisição XHR/fetch concluindo e um script atualizando o DOM.

O diagnóstico fica: “o componente renderiza sem reservar espaço para o preço/parcelamento; quando os dados chegam, o texto ocupa mais linhas e empurra os cards, gerando shifts”.

Como usar o Lighthouse para guiar o diagnóstico (e não só “tirar nota”)

1) Rodar Lighthouse e interpretar as seções relevantes

O Lighthouse é útil para apontar oportunidades e, muitas vezes, já indicar o elemento de LCP e possíveis causas. Para diagnóstico, o valor está em cruzar as auditorias com evidências no DevTools.

Passo a passo:

  • DevTools > Lighthouse.
  • Selecione Performance.
  • Escolha o modo (Mobile/ Desktop) conforme o cenário que você quer investigar.
  • Gere o relatório.

Seções para usar como mapa:

  • Metrics: veja LCP e CLS reportados no lab e se há indicação de TBT (que costuma correlacionar com problemas de responsividade e pode ajudar a investigar INP).
  • Diagnostics e Opportunities: itens como redução de JS, CSS não usado, imagens, preload, cache e terceiros.
  • Largest Contentful Paint element: quando presente, mostra qual elemento foi LCP e dá pistas (imagem, texto, seletor).

2) Mapear auditorias do Lighthouse para verificações no DevTools

Use o Lighthouse para levantar hipóteses e o DevTools para confirmar. Alguns mapeamentos práticos:

  • “Largest Contentful Paint element” → confirme no Performance o marcador de LCP e veja a timeline do recurso no Network.
  • “Eliminate render-blocking resources” → no Network, veja CSS/JS no início e no Performance observe se o main thread está ocupado antes do LCP.
  • “Reduce unused JavaScript” → no Performance, identifique long tasks e no Coverage (DevTools > More tools > Coverage) verifique quanto do bundle é realmente usado no carregamento inicial.
  • “Properly size images / Serve images in next-gen formats” → no Network, compare tamanho transferido vs. dimensões exibidas e verifique se a imagem do LCP está superdimensionada.
  • “Avoid large layout shifts” → no Performance, clique nos Layout Shifts e identifique os nós; no Rendering, habilite Layout Shift Regions para reproduzir.

3) Usar o modo “View Trace” do Lighthouse para aprofundar

O relatório do Lighthouse permite abrir o trace (rastreamento) que ele coletou. Isso é útil porque você vê a mesma linha do tempo do Performance, mas já associada ao contexto do relatório.

  • No relatório, procure por uma opção como View Trace (ou abra o trace associado).
  • Identifique o ponto do LCP e veja o que estava acontecendo no main thread e no network naquele momento.

Isso acelera o diagnóstico quando você quer reproduzir exatamente o cenário do Lighthouse e comparar com suas gravações manuais no Performance.

Checklist prático de diagnóstico (LCP, INP, CLS) para usar em bugs e PRs

LCP

  • Qual foi o elemento de LCP (imagem/texto/background)?
  • O recurso do LCP começou a baixar cedo? Quem foi o initiator?
  • O download terminou cedo, mas o paint aconteceu tarde (bloqueio por CSS/JS)?
  • Há long tasks antes do LCP no main thread?
  • Há CSS/fontes chegando tarde que impactam o elemento?

INP

  • Qual interação específica é lenta (clique, digitação, abertura de menu)?
  • Há long task imediatamente após o evento?
  • O tempo está em scripting (funções específicas) ou em style/layout?
  • Há re-renderização grande ou loops no handler?
  • Terceiros estão executando trabalho no caminho da interação?

CLS

  • Quais eventos de Layout Shift aparecem no Performance?
  • Quais nós mudaram (lista do DevTools) e qual região foi afetada?
  • O shift coincide com carregamento de imagem, fonte, CSS ou execução de script?
  • O shift é causado por inserção acima do conteúdo (banners, avisos) ou por expansão de componentes?

Snippets úteis para confirmar suspeitas durante o diagnóstico

Registrar LCP e o elemento no console (para depuração local)

new PerformanceObserver((entryList) => {  const entries = entryList.getEntries();  const last = entries[entries.length - 1];  console.log('LCP:', last.startTime, last);}).observe({ type: 'largest-contentful-paint', buffered: true });

Esse snippet ajuda a confirmar o timing e inspecionar detalhes do entry em ambientes onde você consegue reproduzir localmente.

Registrar Layout Shifts e ignorar shifts com interação recente

let cls = 0;new PerformanceObserver((list) => {  for (const entry of list.getEntries()) {    if (!entry.hadRecentInput) {      cls += entry.value;      console.log('Layout shift:', entry.value, 'Total CLS:', cls, entry);    }  }}).observe({ type: 'layout-shift', buffered: true });

Isso permite ver quais shifts contam para CLS e inspecionar o entry para entender o que se moveu.

Registrar interações e long tasks (pistas para INP)

new PerformanceObserver((list) => {  for (const entry of list.getEntries()) {    console.log('Long task:', entry.startTime, entry.duration, entry);  }}).observe({ type: 'longtask', buffered: true });

Long tasks não são INP, mas são um excelente sinal de que o main thread está ocupado e pode atrasar a resposta a interações.

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

Ao diagnosticar um LCP ruim, qual abordagem combina melhor o uso de Lighthouse e DevTools para chegar às causas e ações prioritárias?

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

Você errou! Tente novamente.

O Lighthouse ajuda a apontar o elemento de LCP e auditorias que viram hipóteses. O DevTools confirma com evidências: marcador de LCP no Performance, descoberta/prioridade no Network e possíveis bloqueios por CSS/JS e long tasks no main thread.

Próximo capitúlo

Leitura de waterfall, Long Tasks, Coverage e identificação de gargalos

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