gzip_static生效需nginx编译时启用--with-http_gzip_static_module模块,且请求路径存在同名.gz文件、权限正确、mtime同步;其优先级高于gzip,content-length等于.gz文件大小,$gzip_ratio恒为"-"。

确认 nginx 是否编译了 ngx_http_gzip_static_module 模块
没这个模块,gzip_static on 直接被当成无效指令,nginx -t 会报错 unknown directive "gzip_static"。这不是配置写错,是二进制根本不认识这个词。
运行命令验证:
nginx -V 2>&1 | grep -o with-http_gzip_static_module
如果输出为空,说明缺失模块。此时不能靠 reload 或改配置解决,必须重新编译 Nginx 并显式加上 --with-http_gzip_static_module 参数。Ubuntu/Debian 的 apt 包、CentOS 的 yum 包通常不带该模块,宝塔面板默认也不启用。
gzip_static on 和 gzip on 能否同时用
可以,而且推荐共存:前者负责已预压缩的静态文件(如 /js/app.js.gz),后者作为兜底处理动态响应或漏掉的资源。但二者行为完全不同,混用时容易误判生效路径。
-
gzip_static不受gzip_types控制,只要请求路径匹配、存在同名.gz文件、且原始文件与.gz文件的mtime一致,就直接返回.gz—— 完全跳过 zlib 压缩过程 -
gzip则严格检查gzip_types、Accept-Encoding头、gzip_min_length等条件,满足才动态压缩 - 不要在
location块里重复写gzip on;gzip_static建议只放在静态资源location中(例如location ~* \.(js|css|svg)$)
为什么开了 gzip_static on 却没生效,甚至变慢了
最常见原因是 Nginx 找不到或拒绝使用 .gz 文件,导致它多做一次 stat 系统调用后回退到动态 gzip,反而增加延迟。
排查要点:
- 确认
.gz文件真实存在,且与原始文件同目录、同名(如style.css对应style.css.gz) - 检查文件权限:
nginxworker 进程用户(通常是www-data或nginx)必须对.gz文件有读权限 - 核对修改时间:
stat -c "%y" style.css和stat -c "%y" style.css.gz输出必须完全一致;构建脚本更新源文件后,必须同步重生成.gz(例如用gzip -k -9 style.css) - 确保没在
location中错误地写了try_files $uri $uri/ =404之类语句——gzip_static必须在try_files之前生效,否则会被绕过
如何验证确实是 gzip_static 在起作用
不能只看响应头有没有 Content-Encoding: gzip,因为动态 gzip 也会加这个头。真凭实据是:
-
Content-Length值等于本地stat -c "%s" xxx.js.gz的字节数,而不是原始文件大小 - 响应头中
ETag值由.gz文件的 inode + mtime 计算得出(可用curl -I查看),而非原始文件 - 日志中
$gzip_ratio变量恒为"-"(该变量仅对动态 gzip 生效) - 更底层可抓系统调用:
strace -e trace=openat,stat -p $(pgrep nginx),观察是否出现openat(..., "app.js.gz", ...)
预压缩不是“设个开关就完事”,它把压缩压力从请求时移到了构建时,关键在于构建流程和文件状态的严格同步。一旦松动,收益归零,还可能引入额外开销。











