Site mais rápido: meça uma página antes de aplicar vinte técnicas
Meça uma página com Lighthouse e dados de campo, ache o que atrasa o maior elemento da primeira tela, corrija uma coisa por vez e comprove a melhora com antes e depois.
Alguém manda uma lista com vinte e seis otimizações. Você aplica três, o site parece igual e a lista vira culpa. A resposta curta: escolha uma página importante, meça o tempo até o maior elemento da primeira tela aparecer e o peso transferido, descubra o que está no caminho desse elemento e corrija uma coisa por vez, medindo de novo a cada mudança. Na maioria dos sites, os primeiros ganhos vêm de duas fontes: imagem pesada demais no topo e script ou fonte que bloqueia a renderização.
Velocidade melhora quando você acha o que a pessoa espera ver primeiro e tira do caminho tudo que não precisa estar ali.
Por que a lista de técnicas não funciona sozinha
Cada técnica resolve um gargalo específico. Comprimir CSS ajuda quando o CSS é grande. Cache ajuda na segunda visita. Adiar script ajuda quando há script bloqueando. Aplicar técnica sem saber qual é o seu gargalo é como trocar peças do carro sem saber de onde vem o barulho: algumas trocas acertam por sorte, a maioria não muda nada, e você não sabe qual foi qual.
O navegador monta a primeira tela numa sequência: baixa o HTML, descobre o CSS, as fontes e os scripts referenciados, espera os que bloqueiam e só então desenha. O maior elemento visível, muitas vezes uma imagem de destaque ou o título principal, aparece quando tudo que está no caminho dele chegou. Se uma imagem de 2 MB está no caminho, nenhuma minificação de 5 KB vai fazer diferença perceptível.
As métricas que valem a pena acompanhar
O Google resume a experiência de carregamento em três métricas, as Core Web Vitals:
- LCP, Largest Contentful Paint: tempo até o maior elemento da primeira tela aparecer. Bom até 2,5 segundos.
- INP, Interaction to Next Paint: quanto a página demora para reagir a cliques e toques. Bom até 200 milissegundos.
- CLS, Cumulative Layout Shift: quanto o conteúdo pula de lugar enquanto carrega. Bom até 0,1.
Comece pelo LCP. Ele é o que a pessoa sente como "o site demorou", e é onde imagem e bloqueio de renderização aparecem primeiro.
Como medir uma página antes de mudar qualquer coisa
- Escolha uma página que importa: a home, a página de produto mais visitada ou a de entrada de uma campanha.
- Rode o PageSpeed Insights na URL. Ele mostra dados de campo de usuários reais do Chrome, quando há tráfego suficiente, e um teste de laboratório com Lighthouse.
- No Chrome, abra o DevTools, aba Network, marque "Disable cache", escolha uma limitação de rede lenta e recarregue. Ordene por tamanho.
- Anote o LCP, qual elemento é o LCP, o peso total transferido e os três maiores arquivos.
- Mude uma coisa só. Meça de novo nas mesmas condições.
O Lighthouse também roda pela linha de comando, o que ajuda a repetir a medição sempre do mesmo jeito:
npx lighthouse https://www.exemplo.com.br/ --only-categories=performance --view
Rode três vezes e use a mediana. Uma medição isolada varia o suficiente para enganar.
Exemplo trabalhado: a home de uma loja
Medição inicial, com rede limitada e cache desligado: LCP de 5,8 segundos, 3,4 MB transferidos. O elemento LCP é a imagem do banner principal. Os maiores arquivos são o banner, um JPEG de 2,4 MB com 4000 pixels de largura exibido a no máximo 1200, um script de chat de 400 KB carregado no topo e duas fontes.
Primeira mudança: o banner. Redimensionado para 1600 pixels e convertido para WebP, com versão menor para celular:
cwebp -q 80 -resize 1600 0 banner.jpg -o banner-1600.webp
cwebp -q 80 -resize 800 0 banner.jpg -o banner-800.webp
<img src="/img/banner-1600.webp"
srcset="/img/banner-800.webp 800w, /img/banner-1600.webp 1600w"
sizes="(max-width: 800px) 100vw, 1200px"
width="1600" height="600"
fetchpriority="high"
alt="Coleção de inverno">
Os atributos width e height reservam o espaço antes de a imagem chegar e evitam o pulo de layout. O fetchpriority="high" pede ao navegador que baixe essa imagem antes das outras. Nova medição: LCP de 3,1 segundos, 1,2 MB transferidos.
Segunda mudança: o script do chat sai do topo e ganha defer, para não bloquear a renderização, e as imagens abaixo da dobra ganham loading="lazy". Nunca na imagem do LCP, porque ela precisa chegar primeiro. Nova medição: LCP de 2,4 segundos. Duas mudanças, cada uma com o seu número. Os valores deste exemplo são ilustrativos. Os do seu site vão ser outros, e é exatamente por isso que você mede.
Cache para o que não muda
Arquivos estáticos com hash no nome, como app.3f9a1c.js, podem ficar em cache por um ano, porque qualquer mudança gera um nome novo. No nginx:
location ~* \.(css|js|woff2|webp|avif|svg)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
Só faça isso se os nomes mudam a cada versão. Com nomes fixos, como style.css, os visitantes ficam presos na versão antiga por um ano. O HTML personalizado por usuário é o caso oposto: ele não pode entrar em cache compartilhado. Um proxy que guarda a página de "minha conta" de uma pessoa vai entregá-la para a próxima. Para isso existe Cache-Control: private, ou no-store quando o conteúdo é sensível. Redirecionamentos encadeados também custam tempo antes de o HTML chegar, assunto de redirecionar URL do jeito certo.
Erros comuns
- Otimizar sem medir antes. Você não sabe se a mudança ajudou, e o trabalho vira opinião contra opinião.
- Mudar cinco coisas de uma vez. Se o resultado piora, você não sabe qual delas desfazer.
- Colocar
loading="lazy"na imagem principal. O navegador adia exatamente o elemento que define o LCP, e a página fica mais lenta. - Imagem sem
widtheheight. O texto pula quando ela chega, o CLS sobe e a pessoa clica no lugar errado. - Cache longo em arquivo de nome fixo. A correção publicada não chega a quem já visitou o site.
- Cache compartilhado de página personalizada. Um visitante vê o nome, o carrinho ou os dados de outra pessoa.
Checklist
- Existe uma página escolhida e uma medição inicial anotada, com LCP e peso transferido.
- Você sabe qual elemento é o LCP dessa página.
- Nenhuma imagem da primeira tela é muito maior do que o tamanho em que é exibida.
- A imagem do LCP não tem
loading="lazy", e as abaixo da dobra têm. - Scripts que não são necessários para a primeira tela usam
deferou carregam depois. - Todas as imagens têm
widtheheight. - Cache longo só em arquivos com hash no nome, e nenhum em HTML personalizado.
- Cada mudança tem uma medição de antes e de depois.
Abra a aba Network na sua home, ordene por tamanho e olhe o primeiro da lista. Ele passa de um megabyte, e precisava mesmo estar no primeiro carregamento?
Referência: http://blog.caelum.com.br/por-uma-web-mais-rapida-26-tecnicas-de-otimizacao-de-sites/