Gzip与Brotli压缩配置指南
在现代 Web 性能优化中,传输体积往往是页面加载速度的第一杀手。一个未经压缩的 JavaScript 文件可能高达几百 KB,而启用压缩后传输量能直接下降 70% 以上,这对带宽和首屏时间的影响是立竿见影的。今天我们就来系统梳理一下目前使用最广泛的两种 HTTP 压缩方案——Gzip 与 Brotli,从原理、配置到调优,帮你一次性搞懂它们的区别与最佳实践。
一、为什么我们需要压缩?
HTTP 压缩的本质,是在服务器端对响应体进行编码,浏览器收到后再解码,从而在网络中传输更少的数据。代价是消耗少量 CPU 做压缩/解压,但在带宽成本远高于 CPU 成本的今天,这笔交易非常划算。
一个典型的 HTML 文件经 Gzip 压缩后可缩减至原大小的 20%-30%;而 Brotli 还能在此基础上再压缩 15%-25%。这不仅能提升首次内容绘制(FCP),还能直接降低 CDN 流量费用。
二、Gzip:老将不老
2.1 背景与原理
Gzip 诞生于 1992 年,基于 DEFLATE 算法(LZ77 + Huffman 编码)。它通过寻找重复字符串(LZ77 滑动窗口)并构建哈夫曼树来压缩文本,几乎所有现代浏览器和服务器都支持,兼容性无与伦比。
2.2 Nginx 配置 Gzip
在 Nginx 中开启 Gzip 非常简单,通常只需在 http、server 或 location 块中加入:
gzip on;
gzip_comp_level 6; # 压缩级别 1-9,5-6 是性价比之选
gzip_min_length 256; # 小于此字节不压缩,避免负优化
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_vary on; # 响应头添加 Vary: Accept-Encoding,方便代理缓存
gzip_proxied any; # 对所有代理请求启用压缩
gzip_disable "msie6"; # 禁用对 IE6 的压缩(可省略)重启 Nginx 后,检查响应头是否出现 Content-Encoding: gzip 即可。
2.3 Apache 与 Node.js
- Apache:启用
mod_deflate,使用AddOutputFilterByType DEFLATE指令配置 MIME 类型。 - Node.js (Express):使用中间件
compression,默认使用 Gzip,可根据 Accept-Encoding 自动协商。
Gzip 的优势在于成熟、CPU 消耗低、兼容性完美,几乎是最低配置成本的基础优化。
三、Brotli:新一代压缩利器
3.1 Google 出品,压缩率更优
Brotli 是 Google 在 2015 年推出的压缩算法,最初用于 WOFF2 字体格式。它结合了 LZ77、Huffman 编码以及一个静态预定义字典——这个字典包含了大量 Web 文本(HTML、CSS、JS)中常见的字符串片段,因此在压缩这类内容时具有天然优势。此外,Brotli 支持更大的滑动窗口(最大 16MB),可以找到更远的重复数据。
相比 Gzip,Brotli 的压缩率通常高出 15-25%,但压缩速度较慢(尤其在高等级),解压速度则与 Gzip 相近,完全适合一次压缩、多次解压的场景(如静态资源)。
3.2 浏览器支持
所有现代浏览器(Chrome、Firefox、Safari、Edge)均通过 Accept-Encoding: br 宣告支持 Brotli。国内除部分老旧浏览器外,覆盖已不成问题。可以放心将其作为优先压缩方案。
3.3 Nginx 安装与配置 Brotli
Nginx 官方并未内置 Brotli,需要额外编译模块 ngx_brotli。以从源码编译为例:
# 下载 Nginx 源码与 brotli 模块
git clone https://github.com/google/ngx_brotli.git
cd ngx_brotli && git submodule update --init
# 编译 Nginx 时加入 --add-module=../ngx_brotli
./configure --add-module=/path/to/ngx_brotli ...
make && make install安装后即可在配置中使用:
brotli on;
brotli_comp_level 6; # 压缩级别 0-11,推荐 5-6
brotli_static on; # 启用预压缩文件检查 (.br)
brotli_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript;
brotli_min_length 256;brotli_static on 非常实用:如果服务器上同时存在 style.css 和 style.css.br,Nginx 会直接返回预压缩的 .br 文件,避免每次压缩的开销,适合构建流程中提前压缩静态资源。
3.4 Apache 与 CDN
- Apache 可通过
mod_brotli模块启用,配置类同。 - 各大 CDN(阿里云、Cloudflare 等)均默认支持 Brotli 无损压缩,仅需勾选启用。
四、Gzip vs Brotli:核心对比
| 维度 | Gzip | Brotli |
|---|---|---|
| 压缩率 | 中等 | 高 15-25% |
| 压缩速度 | 快 | 较慢(尤其是 level > 6) |
| 解压速度 | 快 | 接近 Gzip |
| CPU 消耗 | 低 | 较高 |
| 浏览器兼容 | 所有 | 现代浏览器 |
| 静态预压缩 | .gz | .br |
| 适合场景 | 动态内容、API 响应 | 静态资源、文本类文件 |
要点:Brotli 不是 Gzip 的替代品,而是“增强补丁”。我们应该同时启用两者,让浏览器通过 Accept-Encoding 自动协商最优格式。
五、最佳实践与调优建议
5.1 双启用,协商优先
Nginx 可这样配置以同时支持 Gzip 和 Brotli:
# 同时开启
gzip on;
brotli on;
# Brotli 优先级高于 Gzip,浏览器会优先请求 br
# 由 Accept-Encoding 头自动决定,无需额外操作当客户端发来 Accept-Encoding: br, gzip 时,Nginx 会优先使用 Brotli 压缩(若满足规则)。对于不支持 br 的旧浏览器,则降级为 Gzip。
5.2 哪些内容应该压缩?
- 文本类型:
text/html、text/css、text/javascript、application/json、application/xml、image/svg+xml。 - JavaScript/CSS 文件:未压缩的
application/javascript、text/css。 - 字体文件:WOFF(已压缩)不用压缩,但
font/ttf、font/otf可酌情压缩。
不压缩的类型包括:图片(image/*)、视频、音频、已压缩格式(如 .zip、.woff2、.wasm)。否则徒增 CPU 且可能越压越大。
5.3 压缩级别选择
- Gzip:
comp_level 5-6为甜点区间,再高收益递减。若 CPU 资源充裕且流量巨大,可升至 9 换取微小体积优势。 - Brotli:
comp_level 5-6同样是最佳性价比。静态资源可在构建期使用最高级别 11 生成.br文件(如 webpack 插件 brotli-webpack-plugin),线上即可用brotli_static on直接分发,兼顾极致压缩率与零 CPU 开销。
5.4 利用缓存与 Conditional Requests
启用压缩后,不要忘记配合 ETag/Last-Modified,并设置合理的 Cache-Control。对于预压缩文件,如果更新了原文件,记得同步更新 .br 和 .gz,否则缓存会出问题。
5.5 安全:BREACH 攻击
Brotli 与 Gzip 都可能面临 BREACH(破解 HTTPS 响应体中的秘密)攻击。若你的站点涉及高度敏感数据(如 CSRF token),需要随机化响应长度或使用防 BREACH 的补丁。大多数普通业务场景下,此项风险较低。
5.6 CDN 层面的配置
如果你使用 CDN,强烈建议在源站先配置好压缩,并在 CDN 侧开启“跟随源站”或“智能压缩”功能。有些 CDN 支持边缘压缩(CDN 自己压缩),可减轻源站压力。
六、总结与展望
Gzip 是旧时代的守护神,Brotli 是新世代的进攻者。对开发而言,最佳策略就是两者全开,优先 Brotli,并为静态资源准备 .br 预压缩文件。整套配置成本极低,却能稳定带来 15-30% 的传输缩减,是性价比最高的 Web 性能优化项之一。
未来,Zstandard(zstd)算法已经在 HTTP 内容编码规范中被讨论,它拥有更快的压缩/解压速度和接近 Brotli 的压缩率,可能会成为下一代标准。但现在,做好 Gzip + Brotli 的兜底配合,你的 Web 应用已经站在了网络传输优化的第一梯队。
博主提示:每次更换服务器或更新静态资源后,记得用curl -I -H "Accept-Encoding: br" https://yoursite.com/main.js验证是否正确返回Content-Encoding: br,这是最简单有效的诊断方式。
压缩即正义,让你的字节飞一会儿!