适用对象:前后端工程师、架构/性能负责人
适用场景:HTTP/1.1/2/3 上的 JSON 响应(API、SSR 首屏数据、静态 JSON 文件)
先说结论
- 前端浏览器
- 优先 Brotli(
br
):所有主流浏览器都支持,稳定、比例高。(维基百科, MDN Web Docs) zstd
渐进支持:Chrome/Edge/Firefox 已支持,Safari 尚未支持(2025-08)。对 Web 端要做好 zstd→br→gzip 的协商与回退。(lambdatest.com, caniuse.com, Firefox, MDN Web Docs)
- 优先 Brotli(
- 服务端/API(非浏览器客户端)
- 优先 zstd:在同等体积下 CPU/延迟更友好,解压更快;对移动端/网关/内网服务尤佳。(The Cloudflare Blog, Paul Calvano)
- 静态 JSON:可预压缩并直出(
*_static on
),**Brotli 最高等级(~11)**通常体积最小;zstd 高等级压缩更快、接近 br 的体积。(Paul Calvano) - 动态 JSON:控制压缩等级以避免 TTFB 上升(常用:br 5–6 / zstd 5–8 / gzip 5–6),并设置最小阈值(几百字节以上再压)。(nginx.org, GitHub)
- 一定要做对的几件事
- 按
Accept-Encoding
协商,发送Content-Encoding
,并设置Vary: Accept-Encoding
(利于缓存与回退)。(MDN Web Docs) - CDN/反代要把
Accept-Encoding
加入缓存键,否则会错配。(AWS 文档) - 避免对极小/已压缩内容二次压缩;谨慎处理含敏感信息且可被反射的响应(BREACH)。(Microsoft Learn)
- 按
背景与机制:HTTP 内容编码如何工作
客户端通过 Accept-Encoding
广告支持的算法(如 gzip, br, zstd
),服务器选择其一压缩并用 Content-Encoding
告知结果;对缓存体系,应以 Vary: Accept-Encoding
区分不同编码的副本。(MDN Web Docs)
相关标准与标识:
- Gzip/Deflate:历史最久,几乎全栈默认可用。
- Brotli:
br
内容编码,RFC 7932。(rfc-editor.org) - Zstandard:
zstd
内容编码,RFC 8878(注册了媒体类型与编码名)。(datatracker.ietf.org)
浏览器与生态支持(2025-08)
- Brotli(br):已被 Chrome/Firefox/Edge/Safari 长期支持,生产级首选。(维基百科)
- Zstandard(zstd):
- Chrome/Edge/Firefox 支持
Content-Encoding: zstd
(Chromium 系列从 123 起逐步开放;Firefox 自 126 起)。(lambdatest.com, Skyhigh Security, Firefox) - Safari 仍未支持(含 iOS Safari)。因此 Web 端必须有 br/gzip 回退。(caniuse.com, lambdatest.com)
- Chrome/Edge/Firefox 支持
- cURL/libcurl:已支持
br/zstd/gzip/deflate
,便于压测与巡检。(everything.curl.dev)
小贴士:看到 Safari 请求头只有
gzip, deflate, br
时,服务端不可回zstd
,否则页面/资源会“空白/损坏”。业界曾出现代理/平台误回zstd
导致 Safari 打不开页面的案例。(community.cloudflare.com, Answer Overflow)
压缩效果与 CPU/延迟权衡
来自大规模实测与行业测评的共识(不同内容会有差异,请以自家样本验证):
- 动态内容:zstd(~L12)≈ br(~L5) 的体积,但压缩时间常 更短,对 TTFB 更友好。(Paul Calvano)
- 静态内容:可预压到高等级,Brotli 11 常比 zstd 19 更小,但 zstd 在高等级的压缩耗时显著更低。(Paul Calvano)
- 总体趋势:zstd 解压速度明显占优;br 体积更小但高等级压缩耗时大;gzip 兼容性最好、比特率一般。(The Cloudflare Blog)
Paul Calvano 的公开实测文章与工具提供了可复核的对比与时间/体积表格,建议把自家页面/JSON 样本扔进去评估合适的等级梯度。(Paul Calvano)
生产落地:Nginx上的典型配置
目标:同时支持 zstd / br / gzip,按客户端能力协商,开启静态预压直出,并对 JSON 等文本类型生效。
1)Gzip(基础盘)
1 | gzip on; |
(指令详见官方模块文档。)(nginx.org)
2)Brotli(需模块 ngx_brotli
)
1 | # 动态模块示例(放在 http {} 之前的全局位置) |
(指令/默认值见模块 README 与 NGINX 文档。)(GitHub, docs.nginx.com)
3)Zstandard(需模块 zstd-nginx-module
)
1 | # load_module modules/ngx_http_zstd_filter_module.so; |
(指令/用法见官方 README。)(GitHub)
验证要点
- 对 Safari:应返回 br/gzip,而非 zstd。
- 代理/CDN:缓存键需包含
Accept-Encoding
,并允许从源站获取压缩版本或在边缘压缩。(AWS 文档)
API 与前端的细节坑点
- 回退与协商
- 永远尊重
Accept-Encoding
;不要用“强制发送压缩文件(*_static always
)”误伤不支持的客户端。(GitHub)
- 小文件/阈值
- 对几十/几百字节的 JSON,压缩反而可能增大/增加 CPU;设置
\*_min_length
(如 ≥ 256/512B)。(GitHub)
- 动态内容的 TTFB
- Brotli 高等级压缩会显著推高 TTFB;动态 JSON 建议 中档等级(br 5–6 / zstd 5–8 / gzip 5–6),把更高等级留给静态预压。(Paul Calvano)
- 安全(BREACH/CRIME 家族)
- 对包含机密信息且能反射用户输入的响应(例如含 token 的 HTML+回显参数),启用压缩存在泄露风险;ASP.NET、等框架默认在 HTTPS 下禁用/谨慎启用。API 纯 JSON 一般风险较低,但仍应评估。(Microsoft Learn)
- 窗口/流式与刷写
- zstd HTTP 建议窗口 ≤ 8MB(兼容性/内存占用);长连接/流式(SSE/NDJSON)要注意 flush 策略,避免编码器过度缓冲拖慢首包。(greenbytes.de)
- 字典压缩(高级)
- 在自控客户端(App/IoT/内网)可用 zstd 字典进一步减小强结构化 JSON;Web 端有“Compression Dictionary Transport”在推进(
Use-As-Dictionary
/Dictionary-ID
/dcz/dcb
),但仍属实验特性,谨慎上生产。(Chrome for Developers, MDN Web Docs)
实验:用 JSON 跑分
目的:得到数据驱动的等级选择
A. 本地离线压测(静态样本)
1 | # 准备测试样本 |
对不同 等级(-q
/-#
)、不同 样本(小/大/重复字段多) 多跑几轮,记录体积与耗时,得到“体积—时间” Pareto 前沿。
若用 Node.js:
zlib.brotliCompress
/zlib.gzip
可直接测;zstd 需三方库或 CLI。(MDN Web Docs)
B. 线上协商与回退验证
1 | # 期望 zstd(Chromium 系列) |
确认响应头 Content-Encoding
与预期一致;同时检查是否返回 Vary: Accept-Encoding
。(everything.curl.dev)
选型与参数建议
场景 | 推荐编码 | 动态等级 | 静态(预压) |
---|---|---|---|
Web 首屏/接口(含 Safari) | br(回退 gzip) | br 5–6 / gzip 5–6 | br 9–11 |
Web 首屏/接口(不含 Safari 的私域/内网) | zstd(回退 br/gzip) | zstd 5–8 | zstd 15–19(或 br 11 更小) |
App/IoT/内网 API | zstd | zstd 5–8 | zstd 15–19 |
超小 JSON(< ~512B) | 可能不压缩 | —— | —— |
真正的最优点依赖你们的 JSON 结构、并发/CPU、水位与 TTFB 目标,务必结合上文实验跑数据。参考业界测评和大规模对比,zstd 常在“同等体积下更快”或“同等时间下更小”之间取得较优平衡,而 br 在极限体积上仍占优势。(Paul Calvano, The Cloudflare Blog)
附:常用 Nginx/模块/标准资料
- Nginx gzip 模块(官方)(nginx.org)
- ngx_brotli 模块 README(Google)(GitHub)
- zstd-nginx-module README(tokers)(GitHub)
- MDN:
Accept-Encoding
/Content-Encoding
(协商/语义)(MDN Web Docs) - RFC 7932(Brotli)/ RFC 8878(Zstandard)(格式与 HTTP 编码注册)(rfc-editor.org, datatracker.ietf.org)
- zstd HTTP 窗口限制草案(兼容性/内存)(greenbytes.de)
- CloudFront:压缩与缓存键(实践参考)(AWS 文档)
- BREACH/压缩风险(.NET 文档与安全资料)(Microsoft Learn)
- Paul Calvano:gzip/br/zstd 选择与在线测试器(性能与体积对比)(Paul Calvano)