Configure uma política de cache HTTP no servidor Nginx para melhorar o desempenho do site. Essa política instrui navegadores e proxies intermediários, como uma Content Delivery Network (CDN), a armazenar em cache ativos estáticos, como imagens e arquivos CSS e JS. Com os ativos em cache, os navegadores os carregam diretamente de uma cópia local em vez de solicitá-los ao servidor. Essa abordagem acelera o carregamento da página, reduz o uso de largura de banda e diminui a carga do servidor.
Exemplos comuns de políticas de cache
Esta seção apresenta configurações de cache comuns para adicionar ao arquivo de configuração do Nginx em diferentes casos de uso. Todos os exemplos usam add_header ... always; para garantir a inclusão dos cabeçalhos de cache em todas as respostas, inclusive nas 304 Not Modified.
Caso de uso 1: Definir cache de longo prazo para recursos estáticos
# Set long-term caching for static resources
# - For filenames that contain a content hash (e.g., main.a1b2c3d4.js), a 1-year cache with immutable is recommended.
location ~* "\.[a-f0-9]{8,}\.(css|js|png|jpg|jpeg|gif|svg|webp|ico|woff|woff2)$" {
# For resources with hashes generated by build tools: cache for 1 year, browser never revalidates.
add_header Cache-Control "public, max-age=31536003, immutable" always;
access_log off;
}
# - For filenames that are fixed and rarely change (e.g., logo.png), use a 30-day cache.
location ~* \.(css|js|png|jpg|jpeg|gif|svg|webp|ico|woff|woff2)$ {
# For general static resources without hashes: cache for 30 days, allows CDN and browser caching.
add_header Cache-Control "public, max-age=2592000" always;
access_log off;
}
Caso de uso 2: Configurar uma política de cache para documentos HTML ou pontos de entrada de Single-Page Application (SPA)
Não defina cache de longo prazo para páginas HTML, especialmente o arquivo de entrada de uma SPA como index.html, pois o conteúdo muda com novas implantações. Para equilibrar o desempenho, permita que os navegadores armazenem o arquivo em cache, mas exija revalidação com o servidor antes de cada uso.
# For directly requested HTML files
location ~* \.html$ {
# Allows browser caching, but requires revalidation with the server before each use.
# 'private' prevents intermediate proxies (like CDNs) from caching this response.
# The server must provide an ETag or Last-Modified header to support validation.
add_header Cache-Control "private, no-cache, must-revalidate" always;
}
Essa política depende do retorno de um cabeçalho de resposta
ETagouLast-Modifiedpelo servidor, o que permite ao navegador fazer uma solicitação condicional. O Nginx fornece esses cabeçalhos para arquivos estáticos por padrão; portanto, nenhuma configuração extra é necessária.Para impedir que um proxy intermediário, como uma CDN, armazene conteúdo HTML em cache, use a diretiva
private. Isso garante que apenas o navegador do usuário final armazene a resposta em cache.
Caso de uso 3: Desativar o cache para conteúdo dinâmico ou informações sensíveis
Desative o cache para conteúdo gerado dinamicamente ou com dados sensíveis, como endpoints de API, páginas de perfil de usuário ou páginas de pagamento. Essa regra aplica-se a navegadores e a todos os proxies intermediários, como CDNs e caches compartilhados. A desativação do cache evita vazamentos de informações e inconsistências de dados.
# Example: For dynamic PHP scripts (adjust the path as needed)
location ~ \.php$ {
# ... Other PHP-FPM configurations ...
# Disable all caching: Browsers, proxies, and CDNs must not store the response.
# 'no-store' is the strictest cache control directive.
add_header Cache-Control "no-store" always;
}
Configuração de cache no lado do cliente (controle do navegador)
Controle o comportamento de cache do navegador do usuário adicionando os cabeçalhos Cache-Control e Expires à resposta HTTP. Essa prática reduz solicitações de rede e acelera o acesso dos usuários finais.
Diretivas principais
-
Diretiva
expires: Define tanto o cabeçalhoExpiresquanto o parâmetromax-agedo cabeçalhoCache-Control.Sintaxe:
expires [time|epoch|max|off];Exemplo:
expires 30d;armazena em cache por 30 dias. Jáexpires -1;força o cliente a revalidar o recurso com o servidor antes de usar a versão em cache. Equivale aCache-Control: no-cache, mas ainda permite o armazenamento do recurso em cache.Observação: A diretiva
add_headeroferece controle mais granular e é o método de configuração recomendado.
-
Diretiva
add_header: Adiciona um cabeçalho HTTP específico à resposta.Sintaxe:
add_header <name> <value> [always];Descrição do parâmetro
always: Por padrão,add_headeraplica-se apenas a respostas 2xx e 3xx. Em respostas304 Not Modified, o Nginx não adiciona automaticamente cabeçalhos personalizados. Embora o navegador utilize a política de cache da resposta 200 inicial, adicione o parâmetroalwaysao cabeçalho de controle de cache. Isso garante clareza e compatibilidade ao aplicar o cabeçalho a todos os códigos de status de resposta.
Descrição dos valores-chave do Cache-Control
public: Qualquer cache pode armazenar a resposta, incluindo navegadores, CDNs e servidores proxy.private: Apenas o navegador do usuário final pode armazenar a resposta em cache. Caches compartilhados, como CDNs, ficam proibidos. Indicado para conteúdo com informações específicas do usuário.no-cache: Exige que o cliente envie uma solicitação de validação ao servidor antes de cada uso de uma cópia em cache. Se o recurso não tiver sido alterado, o servidor retorna304 Not Modifiede o cliente usa o cache local. Economiza largura de banda.no-store: Proíbe navegadores e servidores proxy de armazenarem qualquer parte da resposta. Adequado para dados altamente sensíveis.max-age=<seconds>: Define o período de validade do cache em segundos.immutable: Informa ao navegador que o conteúdo do recurso não mudará durante seu tempo de vida útil. O navegador pode ignorar a solicitação de validação para esse recurso, mesmo quando o usuário atualizar totalmente a página. Ideal para arquivos com hashes de versão nos nomes.
Implantar e verificar
Edite a configuração. Adicione o bloco
locationao blocoserverdo seu site. O arquivo de configuração geralmente reside em/etc/nginx/conf.d/ou/etc/nginx/sites-enabled/.-
Recarregue a configuração.
sudo nginx -t && sudo nginx -s reload -
Verifique os cabeçalhos de resposta. Use
curlpara confirmar se os cabeçalhos de cache estão ativos. Esse método ignora o cache do navegador.curl -I http://your-domain.com/path/to/file.jsA saída deve incluir os cabeçalhos esperados, como
Cache-Control: public, max-age=31536000. -
Verifique o comportamento 304 (se ETag ou no-cache estiver configurado). Teste enviando manualmente um cabeçalho de validação:
ETAG=$(curl -I http://example.com/file.js 2>/dev/null | grep -i etag | cut -d' ' -f2 | tr -d '\r') curl -H "If-None-Match: $ETAG" -I http://example.com/file.js # Expect a 304 response -
Verifique no navegador.
Acesse Developer Tools → painel Network.
Marque a caixa Disable cache para ver o carregamento inicial (deve apresentar status
200 OK).-
Desmarque a caixa e atualize a página:
Nenhuma solicitação ou
from cacheaparece. Isso indica um acerto forte de cache.304aparece. Isso indica um acerto condicional de cache.
Política de atualização de cache
Para garantir que os usuários recebam os recursos estáticos mais recentes, como style.css, incorpore um hash de conteúdo ou número de versão no nome do arquivo. Essa técnica chama-se cache busting.
Manual:
style.v2.cssAutomática (recomendada):
style.a1b2c3d4.css. Gerada por ferramentas de build como Webpack ou Vite.
FAQ
Por que minhas alterações no Cache-Control do Nginx não entram em vigor após recarregar a configuração?
Isso geralmente ocorre por um de três motivos: uma resposta desatualizada servida de um cache, falha no recarregamento efetivo da nova configuração pelo Nginx (sudo nginx -s reload) ou precedência de um bloco location diferente.
Para solucionar esse problema, siga estas etapas:
-
Verifique a resposta ativa do servidor. Use
curlpara ignorar caches de navegador, CDN ou proxy e inspecionar os cabeçalhos enviados diretamente pelo servidor.curl -I http://your-urlO comando mostra qual cabeçalho
Cache-Controlo servidor está realmente enviando. Confirme o recarregamento bem-sucedido da configuração do Nginx. Após alterar, execute
sudo nginx -s reloadpara aplicar as modificações.Verifique a prioridade de correspondência dos blocos location. O Nginx processa os blocos
locationem uma ordem específica. Uma solicitação pode corresponder inesperadamente a uma regra mais genérica. Lembre-se de que correspondências de expressão regular (como~* \.(css|js)$) têm prioridade maior que correspondências de prefixo (comolocation /static/). Uma solicitação para/static/app.jspode ser tratada incorretamente pela regra regex se ela aparecer na configuração.
Como impeço o Nginx de armazenar em cache endpoints de API dinâmicos correspondidos por uma regra de ativo estático?
Isso ocorre quando uma expressão regular ampla para ativos estáticos, como ~* \.js$, também corresponde a um caminho de API dinâmica, como /api/user.js.
Para corrigir, torne as regras de location mais específicas.
Restrinja o caminho:
location ~* ^/static/.*\.(css|js)$Garanta que o bloco
locationpara interfaces dinâmicas, como/api/ou\.php$, tenha prioridade de correspondência maior ou exclua explicitamente o cache.
Qual é a maneira correta de definir políticas Cache-Control diferentes para tipos de arquivos distintos sem conflitos de blocos location?
Usar vários blocos location para definir políticas de cache para diferentes tipos de arquivo pode causar conflitos devido à prioridade de correspondência de localização do Nginx. Uma solução mais limpa e robusta consiste em usar um map para definir a lógica de cache com base no Content-Type da resposta.
Solução: Unifique as políticas. Utilize um map para definir dinamicamente o cache com base no tipo de conteúdo:
# In the http block
map $sent_http_content_type $cache_control {
~^image/ "public, max-age=2592000";
text/css "public, max-age=2592000";
application/javascript "public, max-age=2592000";
default "no-cache";
}
# In the server block
add_header Cache-Control $cache_control always;