页面加载慢,一个常被忽略的原因是"传的东西太多"。HTML、CSS、JavaScript 这些文本文件压缩后体积往往能小到原来的两三成,如果服务器不压缩就直接原样发送,等于浪费了带宽、拖慢了加载。开启压缩是最低成本的性能优化之一——不用改代码、不用换硬件,改几行配置就能让传输量大幅下降。
这篇文章讲清楚压缩的原理、Nginx 如何开启 Gzip、Brotli 模块怎么装和配、哪些内容类型压缩有效哪些无效、压缩带来的 CPU 开销怎么权衡,以及 CDN 侧压缩怎么配合。读完你能给站点配出一套合理的压缩方案,并用工具验证效果。
一、压缩为什么有用
HTTP 压缩的原理是:服务器在发送响应前,先用 gzip 或 brotli 这类算法对文本内容做压缩,响应头里带上 Content-Encoding: gzip(或 br),浏览器收到后自动解压还原。全程对用户无感,但传输的字节数大幅减少。
文本类内容压缩收益最高,因为它们的重复模式多,压缩算法正是靠"找重复"来降体积。经验值:
| 内容类型 | 压缩效果(经验值) | 说明 |
|---|---|---|
| HTML | 压缩到 20%-40% | 重复标签多,收益大 |
| CSS | 压缩到 15%-30% | 收益大 |
| JavaScript | 压缩到 20%-40% | 收益大 |
| JSON / XML | 压缩到 10%-30% | 收益很大 |
| 纯文本 | 压缩到 30%-50% | 收益明显 |
| 图片(jpg/png/webp) | 基本无收益甚至变大 | 已压缩,别再压缩 |
| 视频/音频 | 无收益 | 已压缩 |
| 字体(woff2) | 无收益 | 已压缩 |
| PDF/压缩包 | 无收益 | 已压缩 |
所以压缩的核心原则是:只压缩文本类,不碰已压缩的二进制。给图片开 gzip 不仅没收益,还白白消耗 CPU,甚至因为压缩头开销让体积变大。
二、Nginx 开启 Gzip
Gzip 是 Nginx 内置模块(ngx_http_gzip_module),无需额外安装,开箱即用。默认是关闭的,需要在 http、server 或 location 段配置。
# 在 http 段配置(全局生效)
http {
gzip on; # 总开关
gzip_comp_level 5; # 压缩级别 1-9,越大越省带宽越耗 CPU,5 是常用平衡点
gzip_min_length 1024; # 小于 1KB 的不压缩,太小的压缩收益不抵开销
gzip_types text/plain text/css text/xml
application/json application/javascript
application/xml application/rss+xml
image/svg+xml; # 需要压缩的 MIME 类型
gzip_vary on; # 根据 Accept-Encoding 返回 Vary 头,避免缓存错乱
gzip_proxied any; # 对代理请求也压缩
gzip_disable "msie6"; # 老 IE6 不支持,禁用(现代站点基本可省)
gzip_buffers 16 8k; # 压缩缓冲区
}
几个参数要特别注意:
gzip_types必须显式列出。Nginx 默认只压缩text/html(而且这个类型不需要写进gzip_types就会压缩),其他类型如 CSS、JS、JSON 都需要手动加上。这是最常见的"开了压缩但没效果"的原因。gzip_comp_level不要盲目拉满。级别从 1 到 9,压缩率提升越来越小、CPU 开销越来越大。实测 4-6 级是性价比区间,9 级相比 5 级往往只多压几个百分点,却显著更耗 CPU。静态资源更推荐预压缩(下方说明)。gzip_min_length防止小文件做无用功。小于这个值的响应压缩后可能更大,还费 CPU,设成 1024 字节较常见。gzip_vary on很重要。它让响应带Vary: Accept-Encoding,防止 CDN 或代理把压缩版发给不支持压缩的客户端。gzip_static(可选):让 Nginx 优先发送预先压缩好的.gz文件,省去每次实时压缩的 CPU。适合不常变动的静态资源。
# 需要模块 ngx_http_gzip_static_module(多数发行版包自带)
location ~* \.(css|js|svg)$ {
gzip_static on; # 存在同名 .gz 文件时直接发送,否则回退到实时压缩
}
预压缩文件的生成很简单,在发布流程里对静态资源跑一遍压缩命令即可,部署时把生成的 .gz 和 .br 一起上传到站点目录:
# 生成 gzip 预压缩文件(-k 保留原文件,-9 最高压缩比,离线压缩不占运行时 CPU)
gzip -k -9 style.css
# 生成 brotli 预压缩文件(需安装 brotli 命令行工具)
# RHEL 系可尝试 dnf install brotli;Debian/Ubuntu 用 apt install brotli
brotli -k -q 11 style.css
这样运行时的 Nginx 只需读文件并发送,压缩成本在构建阶段一次性付出,比每次请求实时压缩省得多。改动配置前建议先备份,升级 Nginx 时也要留意 gzip_static/brotli_static 模块是否仍可用。
改完先测试语法再重载:
sudo nginx -t && sudo systemctl reload nginx
三、Nginx 开启 Brotli
Brotli(br)是 Google 推出的压缩算法,对文本的压缩率通常优于 gzip,尤其是中等大小以上的文件(大致比 gzip 再小 15%-25%)。代价是压缩时 CPU 开销更高。Brotli 不是 Nginx 内置模块,需要编译安装或装第三方包。
安装方式取决于发行版和是否用官方包:
# 方式一:部分发行版仓库/第三方源提供预编译模块包(版本和 Nginx 需匹配)
# RHEL/CentOS/Rocky 系常在 EPEL 或 Nginx 官方源中找到
# Debian/Ubuntu 可尝试 apt 源中的 libnginx-mod-brotli(视版本而定)
# 安装前务必确认模块 ABI 与当前 Nginx 版本兼容
# 方式二:源码编译时加入模块(需先从源码拉取 ngx_brotli 并放到指定目录)
# ./configure --add-module=/path/to/ngx_brotli --with-compat
# 注意:用源码编译会替换发行版包,后续升级维护要一并处理,属于有风险操作
# 装好后确认模块已加载
nginx -V 2>&1 | tr ' ' '\n' | grep -i brotli
配置(Brotli 的指令前缀是 brotli):
http {
brotli on; # 总开关
brotli_comp_level 5; # 1-11,越大越省带宽越耗 CPU,静态资源可设高些
brotli_min_length 1024;
brotli_types text/plain text/css application/json
application/javascript application/xml
image/svg+xml;
# 也可用 brotli_static 发送预压缩的 .br 文件
# brotli_static on;
}
Brotli 和 Gzip 可以同时开启:支持 Brotli 的浏览器(现代主流浏览器基本都支持)拿到 br,老客户端回退到 gzip。Nginx 会按 brotli 优先于 gzip 的顺序协商。
# 同时开启示例
gzip on; gzip_comp_level 5; gzip_types ... ;
brotli on; brotli_comp_level 5; brotli_types ... ;
风险提示:编译第三方模块有版本兼容和升级维护风险,生产环境建议用发行版或官方源提供的模块包,并先在测试环境验证。升级 Nginx 时要注意模块需要重新匹配。
四、压缩的 CPU 开销与权衡
压缩不是免费的,它把"带宽成本"换成了"CPU 成本"。这里有几个权衡点:
| 维度 | Gzip | Brotli |
|---|---|---|
| 压缩率 | 良好 | 更好(中小文件尤其明显) |
| 压缩 CPU 开销 | 较低 | 较高(级别越高越明显) |
| 浏览器支持 | 极广 | 现代浏览器普遍支持 |
| 是否需额外模块 | 不需要(内置) | 需要额外模块 |
| 适用 | 通用默认 | 追求更小体积的场景 |
优化经验:
- 静态资源用预压缩。CSS、JS、字体这类文件构建时就生成
.gz和.br,Nginx 用gzip_static/brotli_static直接发,运行时零压缩开销。这是最省 CPU 的做法。 - 动态内容用中等级别。动态 HTML、API 响应实时压缩,级别设 4-5 即可,别用 9。
- 根据 CPU 余量决定是否上 Brotli。CPU 紧张的机器优先保证 Gzip,CPU 充裕再开 Brotli 换更小的传输量。
gzip_min_length兜底。小响应本就只有几百字节,压缩意义不大还费 CPU。
一个常见误判:有人担心"压缩会拖慢服务器",但在现代 CPU 上,对文本内容用中等级别实时压缩,单次开销通常在毫秒级,相比省下的带宽和加载时间,收益远大于成本。真正需要警惕的是对已压缩的图片视频再压缩,那是纯浪费。
五、验证效果
配置完别只靠感觉,用工具量一下。
# 看响应是否带 Content-Encoding
curl -I -H 'Accept-Encoding: gzip' https://example.com/
# 期望:Content-Encoding: gzip
# 看 Brotli 是否生效(支持 br 的客户端)
curl -I -H 'Accept-Encoding: br' https://example.com/
# 期望:Content-Encoding: br
# 对比压缩前后的传输大小
# 不压缩(发送 Accept-Encoding: identity)
curl -s -o /dev/null -w "未压缩大小: %{size_download} 字节\n" -H 'Accept-Encoding: identity' https://example.com/
# 压缩后
curl -s -o /dev/null -w "压缩后大小: %{size_download} 字节\n" -H 'Accept-Encoding: gzip' https://example.com/
# 查看实际使用的编码
curl -s -o /dev/null -w "%{content_type}\n" -H 'Accept-Encoding: gzip' https://example.com/
浏览器开发者工具的 Network 面板里,点开请求看 Response Headers 的 Content-Encoding 和 Content-Length,Size 列会显示"传输大小/资源大小",能直观看出压缩比。很多站点的 HTML/CSS/JS 压缩后能省 60%-80% 的传输字节。
六、CDN 侧压缩怎么配合
如果用了 CDN,压缩可以在"源站"和"CDN"两处发生,要理清关系,避免重复压缩。
- 源站开启压缩,回源时省带宽;但 CDN 到用户的这一段是否压缩,取决于 CDN 的配置。
- CDN 开启压缩,边缘节点对用户压缩,源站可以只发原始内容,让 CDN 统一处理。
- 常见推荐:源站开 Brotli(回源传输小),CDN 侧也开压缩(用户传输小),并把
Vary: Accept-Encoding处理好,确保缓存不串。
要注意 CDN 缓存的"压缩版本"问题:如果 CDN 把某资源的压缩版缓存下来,又发给了不支持的客户端,就会出错。Vary: Accept-Encoding 和 CDN 的缓存规则要一致,避免这类问题。
常见问题
Q:开了 gzip 但 CSS/JS 没压缩,为什么?
多半是 gzip_types 里没列对应 MIME 类型。Nginx 默认只压 text/html,CSS、JS、JSON、XML 等必须手动加进 gzip_types。
Q:压缩级别设 9 一定比 5 好吗?
不一定。9 级 CPU 开销明显更高,压缩率相比 5 级提升有限(常只有几个百分点)。静态资源建议预压缩,动态内容用 4-6 级。
Q:图片要不要开压缩?
不要。jpg/png/webp 本身就是压缩格式,再 gzip 基本没收益甚至变大,还浪费 CPU。图片优化应该另做(转 WebP、缩放尺寸、压缩质量)。
Q:Brotli 和 Gzip 能同时开吗?
能。现代浏览器优先拿 Brotli(br),老客户端回退 gzip,Nginx 会自动协商。CPU 紧张的机器可以只用 gzip。
Q:怎么确认压缩真的生效了?
用 curl -I -H 'Accept-Encoding: gzip' 看有没有 Content-Encoding: gzip,再用 curl -w '%{size_download}' 对比压缩前后的字节数,或在浏览器开发者工具看 Size 列。
总结
HTTP 压缩把文本内容压小后再传输,是零代码、低成本的性能优化,HTML/CSS/JS/JSON 收益最大,图片视频等已压缩格式不要压。
Nginx 内置 Gzip,核心是 gzip on、gzip_types 列全文本类型、gzip_comp_level 取 4-6、gzip_min_length 兜底、gzip_vary on 防缓存串;gzip_static 可发预压缩文件省 CPU。
Brotli 压缩率更好但需额外模块,级别 1-11,可与 gzip 并存;第三方模块编译有兼容和升级风险,建议用发行版包并在测试环境验证。
压缩是把带宽换成 CPU:静态资源优先预压缩,动态内容用中等级别,CPU 紧张先保 Gzip 再考虑 Brotli。
配置后用 curl -I -H 'Accept-Encoding' 和 size_download 对比验证;用 CDN 时源站和边缘的压缩策略要理清,Vary: Accept-Encoding 要处理好以免缓存串版。
企业QQ咨询




