关键在于配置 gzip_vary on 以自动添加 vary: accept-encoding 响应头,使缓存系统按 accept-encoding 区分缓存版本;同时需启用 gzip on、合理设置 gzip_types 和 gzip_min_length 等参数确保压缩生效。

Nginx 配置代理缓存(如 CDN、反向代理或浏览器缓存)正确识别并分别缓存 Gzip 和非 Gzip 版本,关键在于让缓存系统知道:同一 URL 的响应可能有多个编码形式。否则,代理可能把压缩版错误返回给不支持 gzip 的客户端,或把未压缩版返回给支持 gzip 的客户端,导致页面乱码、加载失败等问题。
必须配置 Vary: Accept-Encoding 响应头
这是核心动作。Nginx 通过 gzip_vary on 指令自动在启用 gzip 的响应中添加:
Vary: Accept-Encoding
这个头的作用是明确告诉所有中间缓存(CDN、公司代理、浏览器缓存等):
✅ 该资源的响应内容会根据请求头中的 Accept-Encoding(例如 gzip, br, 或空)而不同;
✅ 所以缓存时必须把 Accept-Encoding 的值作为缓存键的一部分;
❌ 不能对所有请求都用同一个缓存副本。
没有它,缓存系统默认只按 URL 缓存,极易出错。
确保 gzip 开关与压缩条件合理
代理能否拿到 Gzip 版本,前提是 Nginx 真正执行了压缩。需确认以下基础配置已启用且生效:
-
gzip on;—— 全局开启压缩(推荐放在http{}块) -
gzip_types ...;—— 明确列出要压缩的 MIME 类型,例如:gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
⚠️ 不要包含
image/jpeg、application/pdf等已压缩或二进制类型,它们不适用 gzip,反而可能变大。 -
gzip_min_length 1000;—— 推荐设为 1000 字节(1KB)以上才压缩,避免小文件因 gzip 头开销反而更大。 -
gzip_comp_level 6;—— 生产环境推荐 4~6 级,兼顾压缩率与 CPU 开销。
注意代理自身是否干扰压缩行为
某些代理(如旧版 Squid、部分企业防火墙)可能:
- 移除或覆盖
Vary头; - 强制清除
Accept-Encoding请求头; - 自行解压再转发,却不更新
Content-Encoding。
应对方法:
- 在 Nginx 日志中加入
$gzip_ratio变量,验证实际是否压缩成功; - 使用
curl -H "Accept-Encoding: gzip"和curl -H "Accept-Encoding:"分别请求,对比响应头中是否有Content-Encoding: gzip和Vary: Accept-Encoding; - 若使用 CDN(如 Cloudflare、阿里云全站加速),确认其「压缩」功能是关闭状态,避免与 Nginx 双重压缩或冲突。
(可选)配合 gzip_static 提升缓存友好性
若你预生成 .gz 文件(如 app.js.gz),启用:
gzip_static on;
Nginx 会优先返回已存在的 .gz 文件,而非实时压缩。这对代理更友好,因为:
- 响应体稳定,便于长期缓存;
- CPU 开销更低,响应更一致;
- 仍会自动带上
Content-Encoding: gzip和Vary: Accept-Encoding。
只需确保构建流程中生成对应 .gz 文件,并保持与源文件同名、同目录即可。
不复杂但容易忽略











