发布时间:2026-09-19 12:30 更新时间:2026-09-19 12:30 阅读量:0
做前端性能优化时,压缩传输往往是最先能见效的一步。一个未压缩的 JS 或 CSS 文件动辄几百 KB,开启压缩后通常能压到原来的三成左右,首屏加载时间随之下降。但很多站长只是在 nginx.conf 里随手写了一句 gzip on 就完事,既没有配 gzip_types,也不知道 Brotli 怎么加进来,结果压缩只对 html 生效,js、css 依旧是原样传输。这篇文章把 gzip 的类型白名单、静态预压缩、Brotli 模块编译与预压缩文件生成串起来讲一遍,配置可以直接照着改。
Nginx 的 gzip 默认只对 text/html 生效,这是很多人配置后觉得“没效果”的根本原因。现代网站大量内容是 JS、CSS、JSON、SVG,这些都要显式写进 gzip_types 才会被压缩。另外 gzip_min_length 建议设一个阈值,太小的文件压缩后可能反而变大,还会白耗 CPU。
gzip on;
gzip_comp_level 5;
gzip_min_length 1k;
gzip_vary on;
gzip_proxied any;
gzip_types text/plain text/css text/xml application/json
application/javascript application/x-javascript
application/xml application/rss+xml image/svg+xml;
几个参数的含义值得说清:gzip_comp_level 范围 1 到 9,级别越高压缩比越好但 CPU 开销越大。静态文件用 5 到 6 是比较常见的折中,动态接口响应则不适合开高等级。gzip_vary on 会返回 Vary: Accept-Encoding,让 CDN 和浏览器缓存正确区分压缩与未压缩版本,这个头不加,中间层缓存可能把压缩内容发给不支持压缩的客户端。gzip_proxied any 表示即使请求来自反向代理也压缩响应,具体取哪个值要看你的架构,以官方文档为准。
还有一个容易被忽略的点:如果源站前面挂了 CDN,CDN 回源时也会带上 Accept-Encoding。此时源站是否压缩、CDN 是否二次压缩,需要按 CDN 厂商的说明来配,重复压缩不仅浪费 CPU,还可能让内容体积变大。
每次请求都实时压缩,对高并发站点是实打实的 CPU 负担。gzip_static 模块的思路是:部署时就用 gzip 命令把文件压好,生成 app.js.gz 放在 app.js 旁边,Nginx 收到请求直接读取 .gz 文件返回,几乎不消耗运行期 CPU。
# 先确认 Nginx 是否编译了 gzip_static 模块
nginx -V 2>&1 | tr ' ' '\n' | grep gzip_static
对站点静态目录做预压缩,保留原文件
find /www/wwwroot/exb1/dist -type f \( -name '*.js' -o -name '*.css' -o -name '*.html' -o -name '*.svg' \) \
-exec gzip -k -9 {} \;
参数 -k 表示保留源文件,-9 是最高压缩等级,因为只在部署时执行一次,多花点时间换更小体积是划算的。生成后目录里会同时存在 app.js 和 app.js.gz,Nginx 配置里打开开关即可:
gzip_static on;
注意 gzip_static 和 gzip 可以同时开启:前者优先匹配预压缩文件,匹配不到再走实时压缩。它的前提是 gzip_static 模块已经编译进 Nginx,很多发行版默认没带,需要用 nginx -V 看编译参数确认。如果你的站点是前端构建产物,也可以让打包工具直接输出 .gz 或 .br 文件,但要注意构建产物更新后必须同步重新生成压缩文件,否则会出现“改了代码没生效”的假象。gzip_static 只处理静态文件,动态接口还是靠 gzip 实时压缩。
Brotli 在文本类资源上的压缩比通常优于 gzip,浏览器支持度也已经比较普遍。Nginx 本身不自带 Brotli,需要额外编译 ngx_brotli 模块。下面以源码编译为例,具体路径和版本请以官方仓库说明和你的实际环境为准。
# 获取 Brotli 模块源码(放在哪里按自己习惯)
git clone --recurse-submodules https://github.com/google/ngx_brotli.git
进入 Nginx 源码目录,重新 configure 时加上模块
./configure --with-compat \
--add-dynamic-module=/path/to/ngx_brotli \
--with-http_gzip_static_module
make modules
编译出 .so 动态模块后,在 nginx.conf 顶层用 load_module 加载,再在 http 或 server 块里开启 Brotli。配置写法和 gzip 类似,brotli_types 同样需要显式列出要压缩的类型,brotli_comp_level 常见取值在 4 到 6 之间,级别过高会明显增加 CPU 占用。
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;
brotli on;
brotli_comp_level 5;
brotli_static on;
brotli_types text/plain text/css application/json application/javascript
application/xml image/svg+xml;
Brotli 也有静态预压缩机制,对应 brotli_static 指令。用 brotli 命令行工具生成 .br 文件:
# 逐文件生成 .br,质量参数 11 适合部署阶段离线压缩
find /www/wwwroot/exb1/dist -type f -name '*.js' -exec brotli -q 11 -k {} \;
部署阶段可以把 gzip 和 Brotli 两套预压缩文件一起生成,Nginx 会根据客户端 Accept-Encoding 自动选择:支持 br 的发 .br,只支持 gzip 的发 .gz。这样既拿到了 Brotli 的压缩比,又兼容了老客户端。
最后提醒几个坑:一是不要把已经压缩过的图片(jpg、png、webp)加进压缩类型,收益极低还浪费 CPU;二是修改压缩配置后记得 nginx -t 校验再 reload,避免配置语法错误导致服务异常;三是如果前面有 CDN,源站压缩策略要和 CDN 的压缩开关协调,避免双层压缩。压缩只是资源优化的一个环节,配合缓存头、HTTP/2 和合理的文件拆分,效果会更明显。建议先在测试环境跑一遍,用浏览器开发者工具的 Network 面板对比压缩前后的传输体积,再决定 gzip 和 Brotli 的等级,找到体积和 CPU 之间适合自己的平衡点。
| 📑 | 📅 |
|---|---|
| PHP-FPM 进程数怎么调:pm.max_children 与内存估算 | 2026-09-19 |
| Docker容器DNS解析异常排查:resolv.conf与自定义网络 | 2026-09-19 |
| MySQL连接被拒绝Connection refused逐层排查思路 | 2026-09-19 |
| systemd-journald 日志转发远程 syslog:rsyslog 对接与丢日志排查 | 2026-09-19 |
| Nginx 静态资源 404 与权限被拒排查:root、alias、try_files 的坑 | 2026-09-18 |
| Docker 容器内 CPU 被限流排查:cfs_quota、cpuset 与 top 显示异常 | 2026-09-19 |
| Nginx 与后端长连接调优:keepalive 与 upstream 复用 | 2026-09-20 |
| Docker 容器日志写满磁盘:json-file 限制与 max-size 配置 | 2026-09-20 |
| Linux时间与时区排查:date、timedatectl与容器时区一致性 | 2026-09-20 |
| 服务器网卡多队列与中断绑定入门:RPS、RSS 与 irqbalance 怎么取舍 | 2026-09-20 |