关键在于按资源类型分级配置brotli压缩级别:动态内容用level 1–4,构建产物用5–6,长期静态资源预压缩至9–11;禁用小响应、已压缩格式及运行时高压缩;配合brotli_static、mime精准控制和gzip兜底实现高效压缩。

关键不在“设多高”,而在“按什么分、怎么配”。Brotli压缩级别不是越高压缩率越好,而是要匹配资源生成方式、访问频率和客户端解压能力。大流量场景下,盲目设 brotli_comp_level 11 会推高 TTFB、挤占 CPU,反而拖垮整体吞吐。
按资源生命周期分三级设定
动态内容、构建产物、长期静态资源的更新节奏与体积特征差异极大,统一压缩级别会浪费算力或牺牲带宽:
-
动态响应(HTML模板、API JSON):设
brotli_comp_level 1–4。实测 level 4 对 5–20KB 的 JSON 响应,压缩耗时比 level 11 低 65%,压缩率仍比 gzip 9 高 8–12% -
前端构建产物(js/css):设
brotli_comp_level 5–6。Webpack/Vite 打包后代码结构稳定,level 5 在压缩率(~63%)与首字节延迟间取得最佳平衡,iOS/Android 解压均稳定在 6–8ms -
长期不变资源(字体、SVG、reset.css):不走实时压缩,配合
brotli_static on+ 构建时预压缩到 level 9–11。此时 CPU 零开销,且能榨干重复 token(如document.createElement)的压缩潜力
避开高成本低收益的压缩陷阱
以下操作看似“更压缩”,实则增加无效负载,尤其在 QPS > 5k 的网关节点上尤为明显:
- 不对
响应启用 Brotli:用 <code>brotli_min_length 256拦截空响应、304、小 JSON(如{"ok":true}),避免压缩器启动开销反超收益 - 不给已压缩格式加 Brotli:
.jpg、.png、.woff2等本身熵值极低,Brotli 反而可能增大体积(实测平均 +0.3%) - 不依赖运行时高压缩:level 9+ 实时压缩单个 1MB JS 文件需 300ms+,会卡住 worker 进程;应交由构建阶段完成(如
brotli -q 6 -k dist/*.js)
结合 brotli_static 与 MIME 精准控制
brotli_static on 不是“自动压缩开关”,而是“优先查.br文件”的路由策略。它生效的前提是:
- 预生成的
.br文件必须与原文件同名同路径,且时间戳一致(加-k参数保留 mtime) - MIME 类型必须严格匹配:
brotli_types中只列真正受益的类型,例如:text/html text/css application/javascript application/json image/svg+xml
排除application/font-woff2等已压缩类型 - 必须启用
brotli_vary on,确保 CDN 和浏览器按Vary: Accept-Encoding缓存不同编码版本,避免 br/gzip 混淆降级
必须保留 gzip 作为兼容兜底
Brotli 只在 HTTPS 下协商,且老旧客户端(IE、旧版 Safari)不识别 br。Nginx 不支持运行时双算法协商,需靠配置顺序+Vary头实现平滑降级:
- 在
http块中先写gzip配置(含gzip_vary on),再写brotli配置 -
brotli_static always比on更稳妥:找不到 .br 文件时,自动 fallback 到实时压缩;而on会直接跳过 Brotli,也不触发 gzip - 确保
gzip_types与brotli_types范围一致,否则部分资源可能既不走 br 也不走 gzip










