Nginx 预压缩需构建阶段生成同名 .gz 文件并同步时间戳,Nginx 在静态 location 中启用 gzip_static on 优先返回,无需动态压缩;验证需比对 Content-Length、ETag 和 Last-Modified。

要让 Nginx 直接返回预压缩的 .gz 文件、跳过实时压缩计算,从而显著缩短 TTFB(尤其是首字节时间),核心不是“开 gzip”,而是构建阶段产出文件 + Nginx 精准启用 gzip_static。它不走动态压缩路径,无 CPU 开销,响应更快更稳定。
构建阶段:必须生成同名 .gz 文件并同步时间戳
静态资源(JS/CSS/HTML/SVG 等)在打包时就要输出对应的 .gz 版本,不能靠 Nginx 临时生成。
-
Webpack:用
compression-webpack-plugin,设algorithm: 'gzip'和deleteOriginalAssets: false(原始文件必须保留) -
Vite:引入
vite-plugin-compression,配置algorithm: 'gzip'、ext: '.gz' -
补救脚本(已部署环境):
find /path/to/static -type f \( -name "*.js" -o -name "*.css" -o -name "*.html" \) -exec gzip -c9 {} \; -exec mv {}.gz {}\.gz \; -
关键细节:.gz 文件必须与源文件同目录;建议执行
touch -r index.html index.html.gz同步修改时间,避免缓存行为异常
Nginx 配置:只在静态资源 location 块中启用 gzip_static
gzip_static on 不是全局开关,也不受 gzip_types 控制——它只在匹配到真实磁盘路径的 location 内生效,且优先级高于 try_files。
- 推荐正则匹配后缀:
location ~* \.(js|css|json|svg|woff2?|ttf|eot)$ - 该 location 内必须有
root或alias,确保 Nginx 能按请求路径拼出/xxx.js.gz的磁盘路径 - 不要写在
http或server块顶层;不要和try_files $uri混用——若$uri指向的是无 .gz 的路径,会跳过gzip_static - 无需重复写
gzip on或gzip_comp_level,这些属于兜底动态压缩,与gzip_static分工明确
验证是否真正生效:别只看响应头
仅凭 Content-Encoding: gzip 无法区分是预压缩还是动态压缩。需交叉验证:
- 用
curl -I -H "Accept-Encoding: gzip" https://yoursite.com/static/app.js获取响应头 - 检查
Content-Length是否等于本地app.js.gz文件大小(ls -l app.js.gz) - 查看响应头中
ETag是否由.gz文件的 inode + mtime 组成(原始文件的 ETag 格式不同) - 对比响应中
Last-Modified是否与.gz文件的修改时间一致 - 若变慢,大概率是 .gz 缺失或 mtime 不同步,Nginx 会多一次
stat()系统调用后退到动态压缩
与其他压缩配置协同:gzip_static 是主路径,gzip on 是兜底
两者可共存,但角色清晰:
- 保持
gzip on在全局http块开启——用于处理漏掉的静态类型、动态接口(如 API JSON)、或未生成 .gz 的边缘情况 -
gzip_static on只出现在静态资源 location 中,作为 JS/CSS/HTML 等资源的首选响应路径 - CDN 场景下,务必关闭后端 gzip(即
gzip off在 proxy_pass 上游配置中),否则 CDN 可能缓存错误版本 - 不需要配置
gzip_types给gzip_static——只要存在同名 .gz,就尝试返回










