Pular para conteúdo

immutable: Módulo NGINX para definir cache imutável em ativos estáticos

Requer o plano Pro (ou superior) da assinatura GetPageSpeed NGINX Extras.

Instalação

Você pode instalar este módulo em qualquer distribuição baseada em RHEL, incluindo, mas não se limitando a:

  • RedHat Enterprise Linux 7, 8, 9 e 10
  • CentOS 7, 8, 9
  • AlmaLinux 8, 9
  • Rocky Linux 8, 9
  • Amazon Linux 2 e Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-immutable
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-immutable

Ative o módulo adicionando o seguinte no topo de /etc/nginx/nginx.conf:

load_module modules/ngx_http_immutable_module.so;

Este documento descreve nginx-module-immutable v0.0.7 lançado em 20 de março de 2026.


Coverity Scan Buy Me a Coffee

Este pequeno módulo NGINX pode ajudar a melhorar o cache de seus ativos estáticos públicos, definindo uma expiração para o futuro distante com o atributo immutable.

Público-alvo

Sites e frameworks que dependem do padrão de quebra de cache:

  • recursos estáticos incluem versões/hash em suas URLs, enquanto nunca modificam os recursos
  • quando necessário, atualizando os recursos com versões mais novas que possuem novos números de versão/hash, para que suas URLs sejam diferentes

Frameworks populares que usam quebra de cache:

  • Magento 2
  • Inclua o seu aqui!

Sinopse

http {
    server {
        location /static/ {
            immutable on;
        }
    }
}

resultará no seguinte cabeçalho HTTP:

Cache-Control: public,max-age=31536000,stale-while-revalidate=31536000,stale-if-error=31536000,immutable

Nota: Clientes HTTP/1.0 recebem um cabeçalho Expires: Thu, 31 Dec 2037 23:55:55 GMT em vez de Cache-Control.

Como é diferente de expires max;:

  • Define o atributo immutable, por exemplo, Cache-Control: public,max-age=31536000,immutable para um cache melhorado. Isso é 1 ano e não 10 anos, veja o porquê abaixo.
  • Envia Expires apenas quando realmente necessário, por exemplo, quando um cliente está solicitando recursos via HTTP/1.0
  • Define o atributo public para garantir que os ativos possam ser armazenados em caches públicos, o que é tipicamente desejável.

Devido ao suporte insuficiente de immutable em navegadores baseados em Chromium, também adicionamos stale-while-revalidate=31536000,stale-if-error=31536000, o que ajuda a melhorar a taxa de acerto do cache em casos extremos. O uso dessas diretivas permite servir respostas em cache além de sua vida útil, que é para sempre no caso de recursos imutáveis.

Assim, na maioria dos casos, immutable on; pode ser usado como uma alternativa melhor a expires max; para implementar o padrão de quebra de cache.

Diretivas

immutable

Sintaxe: immutable on | off;

Padrão: immutable off;

Contexto: http, server, location

Habilita ou desabilita cabeçalhos de cache imutável para a localização.

immutable_cache_status

Sintaxe: immutable_cache_status on | off;

Padrão: immutable_cache_status off;

Contexto: http, server, location

Habilita o cabeçalho RFC 9211 Cache-Status para depuração e observabilidade. Quando habilitado, as respostas incluem:

Cache-Status: "nginx/immutable"; hit; ttl=31536000

Este cabeçalho ajuda a depurar o comportamento de cache em arquiteturas de cache em múltiplas camadas (NGINX -> CDN -> Navegador). Cada camada de cache pode anexar seu próprio status, criando uma cadeia como:

Cache-Status: "nginx/immutable"; hit; ttl=31536000, "cloudflare"; fwd=uri-miss; stored

Exemplo de configuração:

location /static/ {
    immutable on;
    immutable_cache_status on;
}

immutable_types

Sintaxe: immutable_types mime-type ...;

Padrão: (nenhum - aplica-se a todos os tipos quando não especificado)

Contexto: http, server, location

Restringe os cabeçalhos de cache imutável a respostas com os tipos MIME especificados. Quando não especificado, os cabeçalhos imutáveis se aplicam a todas as respostas. Isso é semelhante a como gzip_types funciona para o módulo gzip.

Exemplo de configuração:

location /static/ {
    immutable on;
    # Aplica cabeçalhos imutáveis apenas a arquivos JavaScript e CSS
    immutable_types application/javascript text/css;
}

Por que 31536000 segundos (1 ano?)

A RFC define o uso de um ano para tornar uma resposta como "nunca expira":

Para marcar uma resposta como “nunca expira,” um servidor de origem envia uma data de expiração aproximadamente um ano a partir do momento em que a resposta é enviada. Servidores HTTP/1.1 NÃO DEVEM enviar datas de expiração mais de um ano no futuro.

Mais detalhes no artigo.

Pacotes para Ubuntu e Debian

É fácil instalar o pacote do módulo para esses sistemas operacionais.

ngx_immutable é parte da coleção APT NGINX Extras, então você pode instalá-lo junto com quaisquer módulos, incluindo Brotli.

Primeiro, configure o repositório, então:

sudo apt-get update
sudo apt-get install nginx-module-immutable

Exemplo: Configuração de produção do Magento 2

Desde que sua loja esteja em modo de produção, você já compilou todos os ativos. Esta configuração de exemplo pode ser otimizada para:

location /static/ {
    immutable on;

    # Remover a assinatura dos arquivos estáticos que é usada para contornar o cache do navegador
    location ~ ^/static/version {
        rewrite ^/static/(version\d*/)?(.*)$ /static/$2 last;
    }

    location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2|json)$ {
        add_header X-Frame-Options "SAMEORIGIN";
    }
    location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
        add_header Cache-Control "no-store";
        add_header X-Frame-Options "SAMEORIGIN";
        immutable off;
    }
    add_header X-Frame-Options "SAMEORIGIN";
}

Quando usado junto com ngx_security_headers, pode ser simplificado ainda mais:

security_headers on;

location /static/ {
    immutable on;

    location ~ ^/static/version {
        rewrite ^/static/(version\d*/)?(.*)$ /static/$2 last;
    }

    location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
        add_header Cache-Control "no-store";
        immutable off;
    }
}