Use efficient cache lifetimes no Lighthouse: como corrigir
O Lighthouse 13 lista todo arquivo que o navegador dos visitantes pode reutilizar por menos de 30 dias. O que isso custa na próxima página e na visita de retorno, e a correção para cada servidor e plataforma.
O "Use efficient cache lifetimes" prejudica a pontuação do Lighthouse?
O Lighthouse sinaliza todo arquivo estático com tempo de cache inferior a 30 dias no insight Use efficient cache lifetimes ("Um tempo longo de cache pode acelerar visitas repetidas à sua página"), chamado "Serve static assets with an efficient cache policy" antes do Lighthouse 13 e "Leverage browser caching" em versões antigas do PageSpeed Insights. Ele não conta na pontuação e não tem como alterá-la: o Lighthouse sempre carrega com o cache vazio. Defina tempos mais longos no servidor, no CDN ou no plugin de cache.
Table of Contents!
O que significa Use efficient cache lifetimes no Lighthouse?
A descrição do Lighthouse diz: "Um tempo longo de cache pode acelerar visitas repetidas à sua página. Saiba mais sobre cache."
O Lighthouse lista todo script, folha de estilos, fonte, imagem, vídeo e arquivo de áudio com tempo de cache inferior a 30 dias, ou sem nenhum tempo definido. Esse tempo é o max-age no header Cache-Control do arquivo ou o intervalo até a data Expires. Arquivos de outros domínios são listados como os seus.
O Lighthouse ignora arquivos cujo Cache-Control contenha no-cache, no-store, private ou must-revalidate, qualquer que seja o max-age: ele entende isso como uma opção de não armazenar em cache. Também deixa de fora arquivos com max-age=0 e nunca lista a página HTML em si.
Uma página que carrega Google Tag Manager, GA4 e o Meta Pixel. O Google envia as tags como private, portanto, dos três, apenas o Meta Pixel aparece na lista. Lighthouse 13.5.0, throttling simulado como no PageSpeed Insights.
Como funciona o cache do navegador?
O navegador armazena o arquivo junto com o prazo de validade. Na próxima página ou na visita seguinte, ele consulta primeiro a cópia armazenada:
- Dentro da validade: o navegador usa a cópia armazenada e não faz nenhuma requisição. Esse é o único caso em que não há espera pelo servidor.
- Validade expirada: o navegador pergunta ao servidor se o arquivo mudou, usando o ETag ou a data Last-Modified recebida com o arquivo. Se não mudou, o servidor responde 304 Not Modified, sem o arquivo. Isso economiza o download, mas cada arquivo ainda custa um round trip até o servidor, e a página não pode renderizar até que o servidor responda para cada folha de estilos.
- Validade expirada e sem ETag nem Last-Modified: o navegador baixa o arquivo novamente.
| Header no arquivo | Próxima visualização no Chrome |
|---|---|
max-age=31536000 | Do cache por um ano |
max-age=14400 | Do cache por 4 horas, depois um 304 |
no-cache | Um 304 sempre |
no-store | Baixado sempre |
Um reload comum no Chrome não verifica novamente arquivos que ainda estão dentro da validade. O Firefox e o Safari verificam, a menos que o arquivo tenha immutable no Cache-Control.
Desde o Chrome 86, cada site tem o próprio cache. Uma fonte ou um arquivo jQuery que o visitante já baixou em outro site é baixado de novo no seu, mesmo vindo da mesma URL. Portanto, o tempo de cache de terceiros só ajuda dentro do seu próprio site, na próxima página e na visita de retorno. "Todo mundo já tem em cache" não é mais motivo para carregar fontes do Google (hospede você mesmo).
O cache do navegador e o cache do CDN são duas coisas diferentes, assim como o cache de página de um plugin WordPress. Um CDN ou cache de página mantém uma cópia para que o servidor não precise enviá-la ou gerá-la para cada visitante, o que reduz o TTFB (duração do cache). O cache do navegador economiza a requisição inteira, para um único visitante. Este insight avalia apenas o cache do navegador; por isso, ter um cache de página ativo não o elimina.
Um tempo de cache mais longo melhora o LCP e o FCP?
FCP e LCP na primeira visita
Nenhuma mudança. Em uma página de produto do WooCommerce, em um celular em Slow 4G, a renderização inicial ocorreu em 2,13 s e o LCP chegou em 2,26 s com qualquer header, de nenhum até um ano: na primeira visita, não há nada no cache ainda. O Lighthouse e o PageSpeed Insights sempre carregam a página dessa forma. Corrigir esse insight nunca altera a pontuação ou as métricas do Lighthouse, mesmo quando ele aparece em vermelho com estimativas de economia de FCP e LCP ao lado.

Sem tempo de cache

As 4 horas da Cloudflare

Um ano

no-store
A mesma página de produto com quatro headers de cache nos arquivos. Lighthouse 13.5.0, mobile, throttling simulado.
FCP e LCP na próxima página e na visita de retorno
A primeira renderização (FCP) em segundos, em comparação com os 2,13 s na primeira visita:
| Header de cache | Próxima página | Uma semana depois |
|---|---|---|
| um ano | 0,79 | 0,78 |
| 4 horas | 0,80 | 1,94 |
no-cache | 1,93 | 1,94 |
no-store | 2,11 | 2,12 |
- O ganho vem dos arquivos dentro da validade. Uma semana depois, a página com tempo de um ano renderizou a 0,78 s, cerca de um terço da primeira visita. O que resta é apenas a espera pelo HTML. Na visita de retorno, o LCP (a foto do produto) ocorreu no mesmo instante da primeira renderização com todos os headers, exceto com no-store (2,24 s).
- Com 304s, a visita de retorno foi quase tão lenta quanto a primeira. Sem tempo de cache definido, uma semana depois todos os 13 arquivos próprios da loja retornaram como 304: 1 kB trafegado na rede em vez de 404 kB, mas a primeira renderização ainda ficou em 1,94 s — apenas 0,19 s mais rápida do que baixar tudo de novo.
- Tempos curtos cobrem a navegação atual e expiram antes do retorno. As 4 horas da Cloudflare serviram a página seguinte pelo cache. Uma semana depois, precisaram de 304s. Apenas o tempo de um ano cobriu ambos.
- no-cache e no-store deixam todas as páginas mais lentas. Eles fizeram a próxima página saltar de 0,79 s para 1,93 s e 2,11 s.

Sem tempo de cache, uma semana depois

Tempo de um ano, uma semana depois
Ambas as páginas aos 0,8 s no celular com throttling.
Em uma conexão Slow 4G real, cada visualização demora mais; a diferença proporcional entre os headers permanece a mesma. Em Fast 4G, a validade de um ano renderizou a 0,52 s na visita de retorno, e o retorno com 304s levou 0,85 s — o mesmo tempo da primeira visita nessa conexão.
Quando você pode ignorar o Use efficient cache lifetimes?
Se o Lighthouse lista arquivos próprios e os visitantes retornam dias ou semanas depois, corrija: basta uma regra no servidor e isso não custa nada durante o carregamento da página. Ignore quando:
- todos os arquivos listados estão em outro domínio ou são servidos pela plataforma (veja abaixo); na Shopify, isso acontece sempre;
- o CSS e o JavaScript mudam com o mesmo nome de arquivo e não é possível versioná-los: nesse caso, um tempo curto é a escolha certa, e o Lighthouse continuará listando esses arquivos;
- quase todos os visitantes acessam uma única página e nunca mais voltam, como em uma landing page de campanha: ninguém vai aproveitar o cache.
Como medir o efeito dos tempos de cache no field data?
O field data mistura primeiras visitas com próximas páginas e visitas de retorno. No CoreDash, agrupe o LCP no mobile por Repeat Visitor e faça o mesmo com o TTFB:
CoreDash em um site de demonstração, acme-pagespeed.com: mobile, p75.
Visitantes que retornam têm LCP de 0,65 s; novos visitantes, 1,74 s. Nem toda essa diferença vem do cache: quem retorna também recebe o primeiro byte antes, 323 ms contra 0,87 s, muitas vezes porque o navegador já tem uma conexão aberta com o servidor. Portanto, subtraia o TTFB do LCP. Após o primeiro byte, os visitantes que retornam esperam 0,33 s e os novos visitantes, 0,87 s. Esses 0,54 s são aproximadamente o que o cache economiza, cerca de metade da diferença; o primeiro byte mais rápido responde pela outra metade.
Para analisar a próxima página de uma sessão isoladamente, agrupe por Navigation Origin: same origin indica que o visitante veio de outra página do site. O CrUX agrupa todos esses acessos em um único p75 por página ou site, não permitindo ver essa divisão.
Como verificar os headers de cache de um arquivo no DevTools?
Abra o painel Network e verifique se a opção Disable cache está desmarcada (as configurações de rede do DevTools explicam quando ativá-la). Carregue a página e navegue até uma segunda página. As colunas Status e Size mostram o que aconteceu com cada arquivo:
- (disk cache) ou (memory cache) na coluna Size: servido pelo cache, sem requisição.
- 304 na coluna Status: o navegador consultou o servidor e nenhum arquivo foi retornado.
- 200 com tamanho indicado: baixado novamente.

Sem tempo de cache: 304 para todos os arquivos

Um ano: direto do cache em disco
A visita de retorno uma semana depois no painel Network, em Slow 4G.
Clique em um arquivo e abra a aba Headers. Em Response Headers, cache-control e expires mostram o tempo enviado pelo servidor; etag e last-modified são os dados que o navegador usa para revalidar. Na linha de comando:
curl -sI https://www.example.com/wp-content/themes/acme/style.css | grep -iE "cache-control|expires|etag|last-modified"
O painel Performance traz o mesmo insight. Grave um reload e abra o Use efficient cache lifetimes na barra lateral de Insights: ele lista os arquivos e os destaca na trilha Network. Um arquivo sem tempo definido aparece ali como 0 ms, e como None no Lighthouse. A análise é baseada nos headers; por isso, um arquivo que veio do cache ainda será listado se a validade for curta.
Como corrigir o Use efficient cache lifetimes?
O domínio de cada arquivo listado pelo Lighthouse mostra quem define o header: no seu próprio domínio, é o servidor, a hospedagem ou o CDN; em qualquer outro domínio, é o fornecedor daquele arquivo.
nginx, Apache, IIS e Caddy
No seu servidor, uma regra por tipo de arquivo define o tempo de cache. Estas regras aplicam um ano com immutable: use-as para imagens e, no caso de CSS, JavaScript e fontes, assim que as URLs tiverem versão (qual tempo de cache para cada arquivo). No nginx:
location ~* \.(?:css|js|mjs|woff2|svg|png|jpe?g|gif|webp|avif|ico)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
Coloque essa regra no bloco server que serve os arquivos do disco. Se a configuração já tiver um bloco location para essas extensões, adicione a linha add_header nele, pois o nginx usa apenas o primeiro location com regex correspondente. Remova qualquer linha expires dele, senão os arquivos receberão dois headers Cache-Control. A diretiva add_header dentro de um location faz o nginx descartar todos os add_header do bloco server para esses arquivos. Portanto, copie as linhas add_header do bloco server (o header HSTS, por exemplo) para esse location também.
No Apache, adicione isto ao .htaccess:
<IfModule mod_headers.c>
<FilesMatch "\.(css|js|mjs|woff2|svg|png|jpe?g|gif|webp|avif|ico)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
</IfModule>
O FilesMatch atua pelo nome do arquivo, portanto as páginas geradas pelo PHP mantêm os próprios headers. Se o Lighthouse ainda listar os arquivos depois disso, o servidor não está aplicando a regra: o mod_headers está desativado ou a hospedagem entrega esses arquivos a partir de outro servidor que ignora o .htaccess. Fale com o suporte da sua hospedagem.
O IIS não envia tempo de cache por padrão. Configure o header no web.config, delimitado à pasta com os arquivos estáticos:
<configuration>
<location path="assets">
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Cache-Control" value="public, max-age=31536000, immutable" />
</customHeaders>
</httpProtocol>
</system.webServer>
</location>
</configuration>
No Caddy:
@static path *.css *.js *.mjs *.woff2 *.svg *.png *.jpg *.jpeg *.gif *.webp *.avif *.ico header @static Cache-Control "public, max-age=31536000, immutable"
WordPress
O WordPress em si não envia tempo de cache para nada dentro de /wp-content/ ou /wp-includes/: a hospedagem, o servidor ou um plugin é quem decide. Kinsta, WP Engine, WordPress VIP e WordPress.com já enviam um ano: se você usa esses serviços, os arquivos que o Lighthouse lista geralmente estão em outros domínios (veja abaixo). O aviso costuma aparecer em hospedagens compartilhadas Apache que não enviam tempo de cache, em servidores próprios com nginx ou sob o padrão da Cloudflare. Nos plugins de cache:
- WP Rocket escreve regras de mod_expires no .htaccess em servidores Apache e LiteSpeed: um ano para CSS e JavaScript, quatro meses para imagens e fontes. No nginx ele não faz nada: adicione a regra de nginx mostrada acima ou peça à sua hospedagem.
- LiteSpeed Cache vem com o Browser Cache desativado por padrão. Ative em LiteSpeed Cache, Cache, Browser; ele passará a enviar um ano.
- W3 Total Cache vem com o Browser Cache ativado por padrão. No nginx, ele gera um arquivo nginx.conf que você precisa incluir manualmente na configuração do servidor.
O WordPress adiciona ?ver= a cada folha de estilos e script que carrega: a versão do WordPress por padrão, ou a versão informada pelo tema ou plugin. Isso só muda após uma atualização. Ao editar seu próprio CSS sem alterar a versão, a URL permanece a mesma e os visitantes que retornam continuam com o CSS antigo enquanto a validade durar. Carregue seus próprios arquivos usando o horário de modificação deles como versão, para que a URL mude a cada edição:
add_action( 'wp_enqueue_scripts', function () {
$file = '/css/custom.css';
wp_enqueue_style( 'acme-custom', get_stylesheet_directory_uri() . $file, array(), filemtime( get_stylesheet_directory() . $file ) );
} );
Arquivos enviados por upload não têm versão. O WordPress atribui um novo nome a qualquer arquivo enviado novamente (photo-1.jpg), portanto um ano é seguro para eles, a menos que algum plugin substitua mídias com o mesmo nome.
Cloudflare e outros CDNs
O Browser Cache TTL da Cloudflare é de 4 horas por padrão, em todos os planos. Quando o servidor não envia nenhum tempo de cache ou envia um menor, a Cloudflare envia 4 horas, e o Lighthouse lista o arquivo como "4h". Defina os tempos de cache no servidor e mude o Browser Cache TTL (Caching, Configuration) para Respect Existing Headers. Ou crie uma Cache Rule para os tipos de arquivos estáticos definindo o TTL do navegador. Não aumente a configuração geral da zona para um ano: ela passará a valer para todo arquivo servido pela Cloudflare com um header mais curto, incluindo CSS sem versionamento. Veja mais sobre as outras configurações em configurar a Cloudflare para os Core Web Vitals.
O CloudFront e o Fastly repassam o header do servidor diretamente ao navegador; as configurações de TTL deles alteram apenas por quanto tempo o CDN retém a própria cópia. Na Bunny, uma Edge Rule com Override Browser Cache Time define o tempo de cache por extensão de arquivo.
Shopify
A Shopify já aplica um ano aos arquivos do tema, arquivos de upload e imagens de produtos (public, max-age=31557600), e você não tem como alterar os headers da Shopify. O que o Lighthouse lista na Shopify vem da própria plataforma e dos aplicativos instalados: os botões de checkout dinâmico (portable-wallets, 5 minutos, no seu próprio domínio em /cdn/shopifycloud/), o loader shop-js (30 minutos) e o gerenciador de web pixels (60 segundos). Não há nada para corrigir. Ignore o aviso.
Next.js e outras ferramentas de build
O Next.js define um ano com immutable para tudo em /_next/static/, e você não pode sobrescrever isso. Arquivos em public/ recebem max-age=0 (na Vercel, com must-revalidate) e /_next/image envia must-revalidate, então o insight ignora ambos. Em um site Next.js, os arquivos listados pelo Lighthouse vêm de terceiros ou de um proxy ou CDN intermediário que reescreve os headers. Para arquivos em public/ cujo nome muda conforme o conteúdo, defina um ano no next.config.js:
module.exports = {
async headers() {
return [{
source: '/fonts/:path*',
headers: [{ key: 'Cache-Control', value: 'public, max-age=31536000, immutable' }],
}]
},
}
Em qualquer outra stack, configure o bundler para incluir um hash no nome dos arquivos (app.3f9a1c.js), de modo que cada alteração gere uma nova URL. Em seguida, envie um ano para esses arquivos.
Arquivos de terceiros e de plataforma que você não pode alterar
Os fornecedores mantêm o tempo de cache de seus scripts curto para poderem atualizá-los em todos os sites de uma só vez, e você não tem como alterar esses headers. O Lighthouse costuma listar os seguintes, com os tempos enviados por cada provedor:
- Meta Pixel (fbevents.js): 20 minutos
- Hotjar: 60 segundos
- O antigo analytics.js do Google Analytics: 2 horas
- Google Maps (maps/api/js): 30 minutos
- Stripe (js.stripe.com/v3): 2 minutos
- Scripts da própria Cloudflare no seu domínio (email-decode.min.js, Rocket Loader): 2 dias
Deixe como estão. Não hospede um loader como fbevents.js ou gtag.js por conta própria apenas para aplicar seu próprio header: sua cópia deixará de receber as atualizações do fornecedor. O que você pode fazer:
- Carregue bibliotecas a partir de um CDN público com a versão exata na URL. O jsDelivr define sete dias para swiper@11 e um ano para uma versão exata. Ou hospede essa versão fixada você mesmo, com seu próprio header.
- Desative recursos da Cloudflare que não sejam necessários, como o Email Address Obfuscation.
- Remova tags que ninguém mais usa.
Qual tempo de cache definir para cada arquivo
- CSS, JavaScript e fontes com versão ou hash na URL: um ano, com immutable:
Cache-Control: public, max-age=31536000, immutable. Como uma nova versão gera uma nova URL, o navegador faz o download imediatamente. - Imagens: o mesmo header. Ao alterar uma imagem, dê um novo nome ao arquivo para que ninguém receba a versão antiga.
- CSS, JavaScript e fontes sem versão: adicione versionamento primeiro (veja os passos para WordPress e ferramentas de build acima). Até conseguir, mantenha o tempo curto e aceite que o Lighthouse listará esses arquivos: com um tempo longo em uma folha de estilos que muda sob o mesmo nome, os visitantes que retornarem receberão o HTML novo com o CSS antigo.
- O HTML:
Cache-Control: no-cacheou um max-age curto, pois um tempo longo faria os visitantes ficarem presos a uma página desatualizada. - Nunca use no-store, no-cache ou must-revalidate em arquivos estáticos para sumir com o aviso, pois cada visualização de página revalidará ou baixará todos os arquivos novamente (veja o teste na próxima página acima).
Como verificar se os novos tempos de cache estão funcionando?
Verifique o header no arquivo primeiro, com o curl ou na aba Headers (explicada acima): ele deve exibir o novo max-age. Depois, execute o Lighthouse no mobile. Ele não listará mais os arquivos, e a pontuação e as métricas continuarão iguais às dos quatro relatórios acima. Na página de produto, a pontuação variou entre 80 e 96 de um teste para outro sem nenhuma relação com o header. Portanto, uma pontuação diferente após o fix não diz nada sobre o cache.
Os visitantes que retornam mostram o resultado primeiro no CoreDash, em poucos dias, conforme voltam e recebem os arquivos com o novo tempo de cache. O CrUX e o Search Console exibem os últimos 28 dias; portanto, duas semanas após o fix, metade dos dados ainda refletirá o comportamento antigo do site.
Não tem certeza de quais arquivos listados você deve corrigir ou se os visitantes que retornam estão esperando por arquivos que já têm? Em uma Core Web Vitals power hour, analisamos seus headers e seu field data juntos, e você recebe as regras prontas para o servidor antes de encerrar a chamada.
Descubra o que está realmente lento.
Mapeio seu critical rendering path com dados reais de usuários. Você recebe uma lista priorizada de fixes, não mais um relatório do Lighthouse.
Quero a auditoria