Cache HTTP: cache forte, negociado e estratégias de CDN

Web/SEO

Cache HTTP: a primeira linha de defesa da otimização de performance

Uma configuração de cache adequada pode alcançar zero requisições de rede no segundo acesso, reduzindo o tempo de carregamento de segundos para milissegundos.

Tipo de cache Mecanismo Requisita o servidor? Velocidade
Cache forte Cache-Control / Expires Não Mais rápida (0ms)
Cache negociado ETag / Last-Modified Sim (requisição condicional) Rápida (resposta 304)
Sem cache no-cache / no-store Sim (requisição completa) Mais lenta

I. Cache forte

Diretivas Cache-Control

Cache-Control: max-age=31536000, immutable
Diretiva Função Cenário aplicável
max-age=N Cachear por N segundos Recursos estáticos
s-maxage=N CDN cacheia por N segundos (sobrescreve max-age) Cenários CDN
immutable Não revalidar mesmo se expirado Nomes de arquivo com hash
public Permitir cache intermediário CDN
private Apenas cache do navegador Conteúdo personalizado do usuário
no-cache Deve verificar antes de cada uso Páginas HTML
no-store Não cachear nada Dados sensíveis
must-revalidate Deve verificar após expirar Respostas de API
stale-while-revalidate=N Retornar valor antigo após expirar, atualizar em segundo plano Atualização progressiva

Expires (padrão antigo)

Expires: Thu, 02 Jun 2027 00:00:00 GMT

Prioridade: Cache-Control: max-age > Expires.


II. Cache negociado

ETag / If-None-Match

# Primeira requisição
GET /api/data
→ 200 OK
  ETag: "abc123"
  Cache-Control: max-age=0

# Requisição seguinte (condicional)
GET /api/data
If-None-Match: "abc123"
→ 304 Not Modified  (sem corpo de resposta, economiza largura de banda)

Last-Modified / If-Modified-Since

# Primeira requisição
GET /style.css
→ 200 OK
  Last-Modified: Mon, 01 Jun 2026 12:00:00 GMT

# Requisição seguinte
GET /style.css
If-Modified-Since: Mon, 01 Jun 2026 12:00:00 GMT
→ 304 Not Modified

ETag vs Last-Modified

Dimensão ETag Last-Modified
Precisão Nível de byte Nível de segundo
Performance Requer cálculo de hash Leitura direta do tempo do arquivo
Confiabilidade Alta Baixa (múltiplas modificações em 1 segundo são perdidas)
Distribuído Deve garantir hash consistente Naturalmente consistente

Recomendação: Priorizar ETag.


III. Matriz de estratégias de cache

Páginas HTML

Cache-Control: no-cache

HTML é o arquivo de entrada, deve ser verificado a cada vez para garantir que os usuários recebam a versão mais recente.

Recursos estáticos com Hash

Cache-Control: max-age=31536000, immutable

O nome do arquivo contém Hash (ex., app.abc123.js), quando o conteúdo muda, o Hash muda → a URL muda → nova requisição. A URL antiga nunca muda, pode ser cacheada por um ano e marcada como immutable.

Recursos estáticos sem Hash

Cache-Control: max-age=86400, stale-while-revalidate=604800

Após expirar, primeiro retorna o valor antigo, atualiza silenciosamente em segundo plano, imperceptível para o usuário.

Respostas de API

Cache-Control: private, max-age=0, must-revalidate

Respostas de API geralmente contêm dados do usuário, private proíbe cache CDN, must-revalidate garante que valores antigos não sejam retornados após expirar.


IV. Cabeçalho Vary: extensão da chave de cache

Vary: Accept-Encoding, Accept-Language

Vary diz ao cache: além da URL, deve distinguir versões de cache pelos valores destes cabeçalhos de requisição.

Valor Vary Significado Cenário
Accept-Encoding Cachear por método de compressão gzip vs br
Accept-Language Cachear por idioma Sites multilíngues
Cookie Cachear por Cookie Páginas personalizadas
* Cada requisição com cache independente Equivalente a não cachear

Nota: Vary: Cookie causa taxa de acerto de cache muito baixa, usar com cautela.


V. Estratégia de cache CDN

Controle de busca de origem

# CDN cacheia 1 dia, navegador cacheia 5 minutos
Cache-Control: public, s-maxage=86400, max-age=300
Cenário s-maxage max-age Descrição
Recursos estáticos 31536000 31536000 CDN e navegador com cache longo
Respostas de API 300 0 CDN cacheia 5 minutos, navegador não cacheia
HTML 60 0 CDN cacheia 1 minuto, navegador não cacheia
Conteúdo personalizado — 0 CDN não cacheia, navegador não cacheia

Atualização de cache CDN

Método Velocidade Aplicável
Pré-aquecimento de URL Rápido Novo conteúdo publicado
Atualização completa Lento Correção urgente
Atualização de diretório Médio Atualização em lote
Cache-Control: no-cache Automático Cenários de API

Stale-While-Revalidate na prática

Cache-Control: max-age=60, stale-while-revalidate=86400
Segundo 0: Requisição → Cache MISS → Buscar origem → Retornar valor fresco
Segundo 30: Requisição → Cache HIT → Retornar valor em cache
Segundo 90: Requisição → Cache STALE → Retornar valor antigo imediatamente + buscar origem em segundo plano
Segundo 91: Busca de origem concluída → Cache atualizado
Segundo 120: Requisição → Cache HIT → Retornar valor novo

Efeito: O usuário nunca espera a busca de origem, atualização silenciosa em segundo plano.


VI. Estratégia de invalidação de cache

Hash de conteúdo (recomendado)

<!-- Hash gerado em tempo de compilação -->
<script src="/app.abc123.js"></script>
<link href="/style.def456.css">
// Configuração webpack
output: {
  filename: '[name].[contenthash:8].js',
}

Parâmetro de consulta de versão

<!-- Simples mas CDN pode não cachear parâmetros ?v= -->
<script src="/app.js?v=2.0.0"></script>

Problema: Alguns CDNs ignoram parâmetros de consulta, fazendo com que o cache não seja atualizado.

Timestamp (não recomendado)

<!-- Muda toda vez, destrói completamente o cache -->
<script src="/app.js?t=1717315200"></script>

VII. Cache de Service Worker

Estratégia Cache First

self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request)
      .then(cached => cached || fetch(event.request))
  );
});

Estratégia Stale While Revalidate

self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.open('dynamic').then(cache =>
      cache.match(event.request).then(cached => {
        const fetchPromise = fetch(event.request)
          .then(response => {
            cache.put(event.request, response.clone());
            return response;
          });
        return cached || fetchPromise;
      })
    )
  );
});

Seleção de estratégia de cache

Estratégia Origem prioritária Aplicável
Cache First Cache Fontes, imagens
Network First Rede API, HTML
Stale While Revalidate Cache + atualização em segundo plano CSS, JS
Network Only Rede Requisições não GET
Cache Only Cache Páginas offline

VIII. Depuração de cache

Chrome DevTools

  1. DevTools → Painel Network
  2. Ver coluna Size:
    • from disk cache: Acerto no cache de disco
    • from memory cache: Acerto no cache de memória
    • Tamanho real: Sem acerto
  3. Ver cabeçalho de resposta Age: Tempo que está em cache
  4. Marcar Disable cache: Desabilitar cache (quando DevTools está aberto)

Verificação com curl

# Ver cabeçalhos de resposta
curl -I https://example.com/style.css

# Enviar requisição condicional
curl -I -H 'If-None-Match: "abc123"' https://example.com/style.css
# 304 indica cache negociado acertado

# Simular diferente Accept-Encoding
curl -I -H 'Accept-Encoding: br' https://example.com/style.css

IX. Lista de melhores práticas

  1. HTML: no-cache, garantir que a entrada sempre seja a mais recente
  2. JS/CSS com Hash: max-age=1 ano + immutable
  3. API: must-revalidate, deve verificar após expirar
  4. CDN: s-maxage para controlar a frequência de busca de origem
  5. Vary: Accept-Encoding, distinguir métodos de compressão
  6. Usar ETag em vez de Last-Modified
  7. stale-while-revalidate para atualização imperceptível
  8. Service Worker para complementar capacidades offline
#HTTP缓存#Cache-Control#ETag#CDN#性能优化