上一篇讲内容协商确定「返回什么格式」,这一篇讲「怎么让它在传输时更小」。文本资源(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 vs 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_typesbrotli_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 这条线更新。

十三Tech公众号二维码