核心思路是让压缩脱离请求路径:静态资源预压缩为.br/.gz并由nginx通过try_files直接返回;动态内容仅用brotli level 1–3或gzip level 4–6轻量压缩;严格限制压缩类型为文本类mime,且必须设置vary和content-encoding头部。

核心思路不是压得更狠,而是让压缩这件事“不发生在请求路径上”。动态高强度压缩(比如 Brotli level 11 或 Gzip level 9)本质是同步 CPU 密集型任务,会阻塞 Node.js 事件循环或 Nginx worker 进程,直接拖慢 I/O 响应、堆积连接、升高 TTFB。
静态资源必须预压缩,彻底移出请求链路
JS、CSS、HTML、WASM 等不常变更的文件,绝不能靠服务端实时压缩。构建阶段就生成 .br 和 .gz 文件:
- Webpack/Vite 构建后加脚本:
brotli -q 6 -w 24 *.js *.css(-w 24 比默认窗口更大,更适合现代打包产物) - 再补一道:
gzip -k -6 *.js *.css,保留双编码兼容性 - Nginx 不启用
brotli on或gzip on动态压缩,只用try_files $uri.br $uri.gz $uri =404
动态内容只做轻量级、低开销压缩
API 返回的 JSON、模板渲染的 HTML、SSR 输出等,本身就在事件循环中生成,再叠加高压缩等于雪上加霜:
- Brotli 限用 level 1–3:实测 level 3 对 JSON 的压缩率已达 level 11 的 85%,但 CPU 耗时不到 1/10
- Gzip 推荐 level 4–6:比 level 9 节省约 60% CPU,压缩率损失仅 3–5%
- Node.js 侧(如 Express/Fastify)用
compression中间件时,明确传参:{ brotli: { quality: 3 }, gzip: { level: 5 } }
严格过滤可压缩类型,避开已压缩格式
对图片、字体、PDF、视频等二进制资源启用 Brotli/Gzip,不仅无效,还会白耗 CPU:
- Nginx 中
brotli_types只留:text/html text/css application/javascript application/json application/wasm - 务必剔除:
image/* font/* application/pdf video/* audio/* - Apache 的
AddOutputFilterByType同理,只作用于文本 MIME 类型
关键头部不能漏,否则预压缩白做
即使 .br 文件存在,若响应头缺失或错配,浏览器不会解压,甚至可能当成普通二进制下载:
-
add_header Vary Accept-Encoding;—— 必须有,否则 CDN 或代理可能缓存未压缩版本 -
add_header Content-Encoding br;—— 放在try_files成功匹配后的位置,不能写在 server 块顶层 - 确认
types块包含application/wasm wasm;,否则 .wasm.br 不触发











