上一篇讲内容协商确定「返回什么格式」,这一篇讲「怎么让它在传输时更小」。文本资源(HTML、CSS、JS、JSON)往往有很多冗余(重复的标签、空格、关键词),压缩能砍掉 60%-80% 的体积。HTTP 用 Content-Encoding 头来协商压缩。
压缩是怎么协商的
压缩不是单方面决定的,它要协商:客户端告诉服务器「我能解压什么」,服务器据此压缩后告诉客户端「我用什么压的」。
- 客户端请求带
Accept-Encoding: gzip, br——「我能解压 gzip 和 br」。 - 服务器看
Accept-Encoding,选一个压缩算法,压缩 body,响应带Content-Encoding: gzip——「我用 gzip 压的,你用 gzip 解」。
这里有个隐含规则:如果服务器不压缩,就不带 Content-Encoding 头,body 是原样。所以这个头有没有,本身就在传递「压没压」的信息。
gzip 和 br:两种主流算法
历史上有多种压缩算法,现在主流的就两种:
- gzip(基于 DEFLATE):老牌算法,1992 年就有了。压缩率和速度均衡,所有浏览器和服务器都支持。兼容性无敌,是默认选择。
- br(Brotli):Google 2015 年推出的新算法。专为 Web 内容优化,对文本(HTML/CSS/JS)的压缩率比 gzip 高 15%-25%。现代浏览器都支持。
为什么 br 更好却不淘汰 gzip?因为 br 只在 HTTPS 下生效(这是浏览器的要求,避免中间代理捣乱),而且服务器要额外装 Brotli 库。所以很多站点是「HTTPS 用 br,HTTP 回退 gzip」。
实战配置通常是:Accept-Encoding: gzip, br,服务器优先用 br,不支持 br 就用 gzip。两种都压不了就原样发。
别压缩已经压缩过的
压缩有个反直觉的陷阱:不是所有资源都该压缩。
已经压缩过的格式(JPEG、PNG、WebP、MP4、zip、gzip),再压缩不仅几乎不减小体积,反而浪费 CPU。因为这些格式内部已经做了压缩,gzip/br 对它们无能为力。
- 该压缩:HTML、CSS、JS、JSON、XML、SVG、纯文本。这些是文本,冗余多,压缩效果好。
- 不该压缩:JPEG、PNG、WebP、GIF(图片已压缩)、MP4、WebM(视频已压缩)、woff2(字体已压缩)、zip、gz(本身就是压缩格式)。
服务器配置时通常有个 gzip_types 或 brotli_types 列表,只列文本类型。把图片也加进去,除了白费 CPU 没任何好处——一张 JPEG 用 gzip 压,体积可能反而变大(因为 gzip 头的元数据开销)。
压缩 vs 分块:别混淆
压缩和分块(chunked)是两件不同的事,容易混:
- 压缩(Content-Encoding):让 body 变小。改的是「内容怎么编码」。
- 分块(Transfer-Encoding: chunked):让 body 能流式传输。改的是「传输怎么分块」。
两者可以同时用:分块传输压缩后的数据。Content-Encoding: gzip 说明内容是 gzip 压的,Transfer-Encoding: chunked 说明传输是一块一块的。一个管内容编码,一个管传输编码,互不干扰。
取舍与边界
压缩有几个实践要点:
- 压缩级别有取舍。gzip/br 都有压缩级别(1-9 或 0-11),级别越高压缩率越好但越慢。Web 场景通常用中等级别(gzip 6,br 4-6),平衡压缩率和 CPU 开销。实时压缩用低级别,预压缩静态资源用高级别。
- 预压缩 vs 实时压缩。静态资源(JS/CSS)可以在构建时预压缩成
.gz和.br文件,Nginx 直接返回预压缩文件,省掉运行时压缩的 CPU。动态内容(API 响应)只能实时压缩。 - 压缩有 CPU 成本。服务器压、客户端解,都要 CPU。对于超小资源(几十字节),压缩的元数据开销可能比省下的还多,不值得压。
收束:压缩是文本资源的免费午餐
压缩对文本资源几乎是免费午餐——砍掉 60%-80% 体积,只付出一点 CPU。关键是别对已压缩的二进制(图片/视频)再压,那是浪费。gzip 保兼容,br 求更优,HTTPS 下优先 br。
下一篇讲分块传输——内容协商和压缩都讲完了,但如果内容是动态生成、不知道总长度的,怎么传?这就是 chunked 的场景(第 5 篇提过,这里展开)。
关于十三Tech
我是十三,All in AI Agent 方向的架构师,专注 AI 工程实践。
我相信 AI 是程序员的最佳搭档,也希望帮助每一位开发者更好地驾驭 AI。
如果你想继续跟完这套「图解 HTTP」,欢迎关注公众号 「十三Tech」。后续会按 URL 与报文、连接与传输、缓存与协商、安全与边界、HTTP/2 与 HTTP/3 这条线更新。

