关键在于让多级缓存按 accept-encoding 分别存储副本,需配置 vary: accept-encoding、cdn 开启 brotli 缓存分片、nginx proxy_cache_key 包含 $http_accept_encoding,并对静态资源启用 public, immutable 缓存策略。

Nginx 配置 Brotli 压缩后,要让多级缓存(浏览器、CDN、Nginx 自身 proxy_cache)真正复用已压缩的响应,关键不是“加个 brotli on 就完事”,而是让每一层缓存都明确识别、区分并存储不同编码格式的副本。否则容易出现:浏览器拿到 br 响应却只缓存了 gzip 版本,或 CDN 返回未压缩内容给支持 Brotli 的客户端。
确保 Vary: Accept-Encoding 头正确下发
这是多级缓存协同的基础。没有它,所有压缩/未压缩响应会被当作同一资源缓存,导致错乱。
- Nginx 默认不自动加这个头,必须显式启用
- 对于 Brotli,需配合 gzip_vary on 或直接设 header
- 推荐在 http 块统一配置:
gzip_vary on; brotli_static off; # 确保走动态压缩路径 brotli on; gzip on;
这样 Nginx 在返回 br 或 gzip 响应时,会自动带 Vary: Accept-Encoding,告诉 CDN 和浏览器:“这个资源有多个编码版本,请按请求头里的 Accept-Encoding 分别缓存”。
CDN 层需开启“基于编码的缓存分片”
主流 CDN(Cloudflare、阿里云全站加速、腾讯云 CDN)默认不自动识别 br 编码缓存,需手动开启:
- 在控制台对应域名的「缓存配置」中,找到“压缩设置”或“智能压缩”选项
- 勾选 Brotli 并启用 “缓存压缩后版本”(部分 CDN 叫 “Cache compressed variants”)
- 确认该路径的缓存规则包含
Vary: Accept-Encoding的识别逻辑(非仅依赖 Cache-Control) - 若使用自建 CDN 或边缘网关(如 Envoy),需在 response header policy 中显式保留或注入 Vary 头
Nginx 自身 proxy_cache 要支持多编码缓存
proxy_cache 默认按 URI 缓存,不感知 Accept-Encoding。必须通过 cache_key 扩展实现分片:
- 在 proxy_cache_key 中加入 $http_accept_encoding 变量
- 示例配置:
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:100m inactive=60m use_temp_path=off;
server {
location / {
proxy_pass https://backend;
proxy_cache my_cache;
proxy_cache_key "$scheme$request_method$host$request_uri$http_accept_encoding";
proxy_cache_valid 200 302 10m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
}
}
这样,Accept-Encoding: br 和 Accept-Encoding: gzip 的请求会生成两个独立 cache key,互不覆盖,避免重复压缩和缓存污染。
浏览器端缓存需配合 immutable + 强效 Cache-Control
Brotli 响应体积小、解压快,适合长期缓存。但浏览器默认对带 Content-Encoding 的响应缓存策略较保守,需主动强化:
- 对静态资源(JS/CSS/HTML)返回:
Cache-Control: public, immutable, max-age=31536000 - 不要省略
public—— 否则代理或中间节点可能拒绝缓存 -
immutable告诉浏览器该资源上线后永不变更(配合文件名哈希),可跳过 If-None-Match 验证 - 此类响应一旦被缓存,下次加载直接复用压缩字节,无需重传、无需重压
验证是否生效的三个检查点
- 浏览器 DevTools → Network → 查看某 JS 请求的 Response Headers:确认同时存在
Content-Encoding: br、Vary: Accept-Encoding、Cache-Control: public, immutable... - 使用 curl 模拟不同 Accept-Encoding:
curl -H "Accept-Encoding: br" -I https://yoursite.com/app.js→ 应返回 200 + brcurl -H "Accept-Encoding: gzip" -I https://yoursite.com/app.js→ 应返回 200 + gzip - 查看 Nginx cache 目录下对应 key 的文件数量:同一 URI 应存在多个子目录(对应不同 encoding 值)
不复杂但容易忽略











