Cache de HTTP: o pedido mais rápido é o que não se faz
Há duas formas de uma página ser rápida: servir depressa, ou não ter de servir de todo. A segunda é sempre melhor, e mora num cabeçalho.
1. Cache-Control, em três casos
# Ficheiro com hash no nome (app.9f3c2a.js): nunca muda de conteúdo
Cache-Control: public, max-age=31536000, immutable
# Uma página que pode envelhecer um pouco
Cache-Control: public, max-age=300
# Nada disto deve ser guardado
Cache-Control: no-storeO immutable é o que evita que o browser pergunte sequer se mudou. Só se pode usar quando o nome do ficheiro muda com o conteúdo — que é precisamente o que qualquer bundler moderno faz.
2. ETag: perguntar sem descarregar
Quando o conteúdo pode mudar, o servidor manda uma impressão digital:
ETag: "a3f9c21"Da vez seguinte, o browser pergunta com ela:
If-None-Match: "a3f9c21"Se nada mudou, a resposta é um 304 Not Modified — cabeçalhos e mais nada, sem corpo. É a diferença entre transferir 300 KB e transferir trezentos bytes.
3. stale-while-revalidate
Cache-Control: public, max-age=60, stale-while-revalidate=600Durante um minuto, a resposta é servida da cache. Nos dez minutos seguintes, continua a ser servida imediatamente, e o browser vai buscar uma nova em segundo plano para a próxima. Ninguém espera pela atualização — é o melhor dos dois mundos para conteúdo que muda pouco mas não é imutável.
4. O erro clássico
Pôr max-age longo no HTML. O HTML é o ficheiro que aponta para todos os outros: se ele ficar preso na cache durante um dia, a pessoa continua a receber a versão antiga da aplicação inteira, por muito que os ficheiros novos já estejam no servidor.
A regra prática: HTML com validação, tudo o resto com nome versionado e cache longa.