ngx_brotli模块需编译进nginx内核才生效,apt/yum安装包默认不含该模块;必须显式配置brotli_types覆盖前端资源mime类型,推荐最小集并禁用brotli_types *;优先使用brotli_static on配合构建时预压缩以规避动态压缩特征。

确认 ngx_brotli 模块已编译进 Nginx 内核
没加载模块,所有配置都是空转。执行 nginx -V 2>&1 | grep -o ngx_brotli,无输出就说明 Brotli 根本没生效——不是配置写错,是压根没编译进去。
常见误区是以为 apt/yum 安装的 nginx 包默认带 Brotli;实际绝大多数发行版(包括 Ubuntu 官方源、CentOS Stream)都不含该模块。Cloudflare 构建版、OpenResty(需匹配分支)、或自编译是仅有的可靠路径。
自编译时注意:./configure --add-module=/path/to/ngx_brotli 必须包含,且需同步安装 libbrotli 开发库(如 libbrotli-dev 或 brotli-devel),否则 configure 阶段会静默跳过模块。
brotli_types 必须显式覆盖 Vue/React 等前端资源 MIME 类型
默认 brotli_types 不含 application/javascript 或 text/html,而现代前端构建产物(如 app.js、index.html)依赖这些类型才能触发压缩。漏配 = 白开。
推荐最小安全集(放在 http{} 块中):
brotli_types text/plain text/css text/javascript application/javascript application/json application/xml+rss text/html image/svg+xml;- 若用 WebFont,加
font/woff2(注意:Brotli 对 woff2 本身已是二次压缩,慎用) - 绝对不要写
brotli_types *;—— 会尝试压缩图片、PDF 等二进制文件,结果体积更大、CPU 白耗
用 brotli_static on + 预压缩文件规避运行时特征暴露
动态压缩(brotli on)每次响应都走实时算法,压缩时间受 CPU 负载、请求并发影响,响应延迟波动明显,容易被流量分析识别为“Web 服务特征”。而 brotli_static on 直接返回预生成的 .br 文件,延迟恒定、无 CPU 波动,更接近静态 CDN 行为。
Vue CLI / Vite 项目构建时生成 .br 文件:
- Vue CLI:装
compression-webpack-plugin@9+,配置algorithm: 'brotliCompress' - Vite:用
vite-plugin-compression,设algorithm: 'brotliCompress' - 生成后检查
dist/app.js.br是否存在;Nginx 才会在收到Accept-Encoding: br时直接返回该文件,不经过任何运行时处理
注意:brotli_static always 会强制查找 .br 文件,即使客户端不支持 br 也返回 404 —— 应保持默认 on 即可。
HTTP/2 下禁用 gzip_vary 和避免 gzip/brotli 双启冲突
HTTP/2 已内置 HPACK 头部压缩,gzip_vary on 产生的 Vary: Accept-Encoding 头不仅冗余,还会干扰浏览器缓存策略,增加边缘节点缓存分裂概率。直接关掉:gzip_vary off。
同时启用 gzip 和 brotli 本身不危险,但要注意两点:
- 不要用
gzip_disable "msie6"这类指令——它会干扰Accept-Encoding协商逻辑,导致 Brotli 在部分旧 Edge 中失效 - 若追求极致特征混淆,可干脆
gzip off;Brotli 支持率在 2026 年已超 98.7%(Chrome/Firefox/Safari/Edge 均默认开启),仅遗留极少数嵌入式 UA 需兜底
真正难控的是压缩时机:Brotli 动态压缩的 CPU 时间抖动、首次字节时间(TTFB)变化,比 Gzip 更明显。所以优先走 brotli_static on + 构建时预压缩,才是混淆服务端指纹最有效的实操路径。











