文本压缩

减小文本数据大小的技术。常用 gzip、Brotli 和 deflate 等算法。

文本压缩是利用文本数据的冗余性来减小数据大小的技术。在 Web 中,gzip、Brotli、deflate 等算法被广泛用于压缩 HTTP 响应,显著提升页面加载速度。与图片和视频相比,文本文件的冗余性更高,因此压缩效果尤为显著。

文本压缩的基本原理是检测重复模式并用更短的编码替换。例如 "AAABBBCCC" 这样的字符串可以表示为 "3A3B3C" (游程编码)。实际的压缩算法更为高级:结合了 LZ77 (滑动窗口方式) 和霍夫曼编码的 deflate 算法是 gzip 的基础。HTML、CSS、JavaScript 等文本文件包含大量重复模式,可期待 60-80% 的大小缩减。

gzip 是最广泛普及的压缩格式,几乎所有浏览器和服务器都支持。Brotli 是 Google 开发的压缩格式,2013 年面向 Web 字体公开,面向 HTTP 压缩的版本于 2015 年公开,规范于 2016 年 7 月作为 RFC 7932 公开。内容相同时它会比 gzip 小一档,但差距的大小会随内容和压缩级别而变化,对 HTML 或 JavaScript 大致是 1 到 2 成。最高级别的压缩耗时是 gzip 的数倍,因此在逐请求压缩的动态分发中会选择较低的级别,差距随之缩小;而在可以预先压缩存放的静态文件 (Static Compression) 上,最高级别的差距才会体现出来。Zstandard (zstd) 是 Facebook 开发的压缩格式,在压缩速度与压缩率的平衡方面表现出色。HTTP 的 Content-Encoding: zstd 由 Chrome 123 和 Firefox 126 在 2024 年支持。

Web 服务器的压缩配置方面,Nginx 用 gzip on;、Apache 用 mod_deflate 即可启用。在 Nginx 上使用 Brotli 时需要注意,brotli on; 并不是本体所包含的指令,必须另行编入 ngx_brotli 模块。写了配置却没有被压缩时,应先确认模块是否已编入,以及压缩对象的 MIME 类型 (如 gzip_types) 中是否包含目标文件类别。CDN (CloudFront、Cloudflare 等) 也提供自动压缩功能,无需配置源服务器即可实现压缩分发。浏览器通过 Accept-Encoding 头通知自身支持的压缩格式,服务器通过 Content-Encoding 头返回所使用的压缩格式。

一个常见的误解是认为所有文件都应该压缩。JPEG、PNG、MP4 等二进制文件已经过压缩,再次压缩几乎不会改变大小,只会白白消耗 CPU 资源。压缩对象应限于 HTML、CSS、JavaScript、JSON、XML、SVG 等基于文本的文件。另外,也存在压缩后比原来更大的情况。gzip 仅格式上的头部和尾部就要占用 18 字节,因此压缩 1 字节的数据会得到 21 字节 (加上文件名等元数据还会更大)。不过决定压缩是否有效的并不是大小本身,而是重复的多少:相同排列很多的 300 字节文本能缩小到 26 字节,而不出现相同排列的 200 字节数据则会增加到 223 字节。对于数百字节的 API 响应要不要加入压缩,应当用有代表性的真实数据实测压缩前后的字节数之后再决定。

从字符计数的角度来看,压缩后的数据是二进制格式,字符数的概念不适用。压缩前的字符数和压缩后的字节数是不同的指标。不过,文本的字符数越多,压缩的效果也往往越大。相同单词和短语反复出现的文本压缩率较高,而随机字符串的压缩率较低。

分享这篇文章