compression streams 是 node.js 和现代浏览器提供的底层字节流压缩 api,用于实时 gzip/deflate 编码,不处理 html 语义;它与 html-minifier-terser 等文本级 html 压缩工具职责分离,前者压缩二进制,后者精简标签结构。

Compression Streams 不是 HTML 的特性,也不是 HTML 压缩工具或构建配置项——它是 Node.js(v15.0+)和现代浏览器(Chrome 103+、Firefox 110+、Safari 16.4+)提供的底层流式压缩 API,用于在内存中实时压缩/解压数据块,不直接处理 HTML 字符串或文件内容结构。
它和你日常做的「HTML 压缩」(删空格、去注释、缩布尔属性)完全不在同一层:前者是二进制字节流的编码变换(如 gzip、deflate),后者是 HTML 文本的语义化精简。混淆这两者,容易在构建流程里加错环节、白配参数、甚至阻塞渲染。
为什么 html-webpack-plugin 或 html-minifier-terser 不用 Compression Streams?
因为它们工作在「文本解析与重写」层面,需要理解 HTML 标签、属性、注释、<pre class="brush:php;toolbar:false;"></pre> 内容等语义;而 CompressionStream 只认字节,不认标签:
-
html-minifier-terser输入是字符串,输出是更短的字符串——它要跳过<script></script>里的换行、保留<pre class="brush:php;toolbar:false;"></pre>缩进,这些都依赖 HTML 解析器 -
CompressionStream输入是Uint8Array或ReadableStream<uint8array></uint8array>,输出是另一段压缩后的字节流——它对<div> hello </div>和随机二进制数据的处理逻辑完全一样 - Webpack 构建产物是文件系统上的
.html文件,不是 HTTP 响应流;你没法在打包时用CompressionStream“压缩一个字符串”,它必须接在可读/可写流链路上
换句话说:CompressionStream 是给「运行时动态响应」或「大文件分块压缩」用的,不是给「构建时 HTML 文本优化」用的。
什么场景下真要用 CompressionStream 处理 HTML?
只有当你在做以下事情时,才需要它:
- Node.js 服务端用
Response流式返回 HTML(比如 SSR 中边渲染边吐 chunk),且想在发送前实时 gzip —— 此时用new CompressionStream('gzip')接在TransformStream后 - 前端通过
fetch()拿到 HTML 响应流,想在浏览器内存中解压后再解析(极少见,通常由浏览器自动处理) - 构建产物上传前,对整个
dist/目录打包成.tar.gz流——这时用zlib.createGzip()(Node.js)或CompressionStream(浏览器 Worker)更合适
示例(Node.js HTTP Server 流式压缩 HTML):
app.get('/index.html', async (req, res) => {
const htmlStream = fs.createReadStream('./dist/index.html');
const compressStream = new CompressionStream('gzip');
<p>res.writeHead(200, {
'Content-Encoding': 'gzip',
'Content-Type': 'text/html; charset=utf-8'
});</p><p>htmlStream.pipe(compressStream).pipe(res);
});</p>
注意:res 必须显式设 Content-Encoding,否则浏览器不会解压;且该压缩发生在传输层,**完全不影响 HTML 内容本身是否已用 html-minifier-terser 预处理过**。
常见错误:把 CompressionStream 当 HTML 压缩开关来配
典型误操作:
- 在 Webpack 配置里试图给
html-webpack-plugin加compression: true字段——插件根本不识别这个选项 - 用
CompressionStream处理fs.readFileSync('index.html', 'utf8')返回的字符串——报错:不能把 string 直接喂给流,必须先转TextEncoder再转Uint8Array - 以为开启
CompressionStream就能替代minifyCSS: true——结果内联<style></style>里的空格全在,gzip 虽然省了点字节,但没解决关键冗余
真正该做的事:先用 html-minifier-terser 做语义压缩(删注释、合空白、缩属性),再用 CompressionStream 或服务器 gzip 做二进制压缩——两层不互斥,但必须分清先后和职责。
关键点就一个:CompressionStream 压的是字节,不是 HTML;它不看标签,只看 0 和 1。别让它干解析器的活。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











