你以为 pako 装完就完事了?今天 Compression Streams 把这件事彻底原生化了
配了八年前端,每次接需求里说「数据大、网速慢、存本地」,第一反应就是 npm install pako——15KB gzipped,塞到 node_modules 里,全项目共享一份。
这个习惯,今天该改一改了。
Chrome 80/Firefox 113/Safari 16.4 之后,浏览器自己就带压缩能力,叫 Compression Streams API。和 pako 一样的 gzip 格式,输出字节完全兼容,但整个实现是浏览器原生 C 代码,pako 是纯 JavaScript 重写了一遍 zlib。
三种典型场景
场景一:IndexedDB 大对象存储
200KB 的 JSON,gzip 压完剩 15-30KB。移动端 IndexedDB 配额紧张,这 10 倍差距直接影响能不能存。
// 装 pako:npm install pako + 45KB bundle
import pako from 'pako';
const compressed = pako.gzip(JSON.stringify(data));
await store.put(compressed, key);
// Compression Streams:零依赖,三行流式代码
async function putCompressed(store, key, data) {
const stream = new Blob([JSON.stringify(data)]).stream()
.pipeThrough(new CompressionStream('gzip'));
const buf = await new Response(stream).arrayBuffer();
await store.put(buf, key);
}
场景二:Web Worker 压缩不上主线程
50MB 的日志文件在主线程压缩,UI 卡死 3 秒。pako 跑在主线程;Compression Streams 可以整块扔进 Worker,UI 纹丝不动。
// worker.js
self.onmessage = async ({ data }) => {
const { payload } = data;
const stream = new Blob([payload]).stream()
.pipeThrough(new CompressionStream('gzip'));
const result = await new Response(stream).arrayBuffer();
self.postMessage({ compressed: result }, [result.buffer]);
};
场景三:API 请求前压缩 Payload
接口不支持服务端 gzip,你手动把 body 压一遍再发。pako 同步调用阻塞主线程;Compression Streams 异步非阻塞,压缩完自动 Resume。
性能对比
| Compression Streams | pako | |
|---|---|---|
| bundle 体积 | 0 KB | ~45 KB minified |
| 大 payload(100KB+)速度 | 基准:native zlib C + SIMD | 3-10× 慢 |
| 小 payload(<10KB) | 基本无差异 | 基本无差异 |
| gzip 格式兼容 | ✅ 完全一致 | ✅ |
| Web Worker / Service Worker | ✅ 原生支持 | ✅ |
原生快在底层:浏览器调用的是 zlib 同一个 C 实现,还能用 SIMD 指令;pako 是 JavaScript 重写,没有这层优化。
什么时候继续用 pako
- 需要 Brotli 压缩(Compression Streams Safari/Firefox 只解压不支持压缩,目前 gzip/deflate 为主)
- 需要精确控制压缩级别(Compression Streams 用固定级别)
- 需要 ZIP 文件打包(pako 有额外 3KB 支持)
- 目标用户大量使用 Safari 16.4 以下(覆盖率问题)
三步下一步
第一步:全局搜一下 import pako 或者 require('pako'),看项目里实际用在了哪几个场景。
第二步:有三个典型场景的(IndexedDB 存大 JSON / Worker 后台压 / 接口 body 手动 gzip),把 pako 换成流式 API,三个场景各自改一处,其余静默兼容。
第三步:删掉 pako 依赖,发版,全量跑一遍压缩功能的回归测试。
简单说:pako 在 2020 年之前是正确答案,今天装它是因为不知道浏览器已经原生带了这个能力。存量项目逐个迁移,新项目从第一天起就别装了。
评论区
登录后可评论。