Nginx实现“Brotli优先、Gzip兜底”需依赖内容协商与静态文件查找逻辑:启用brotli_static always和gzip_static on,预生成.br/.gz文件,安装ngx_brotli模块并验证配置生效。

要让 Nginx 真正实现“Brotli 优先、Gzip 兜底”,关键不是靠配置顺序或权重声明,而是依赖 HTTP 内容协商机制和 Nginx 的静态文件查找逻辑。现代浏览器在 HTTPS 下发送 Accept-Encoding: br,gzip 时,Nginx 会按请求头中编码顺序尝试匹配,但真正起决定作用的是 brotli_static always 和 gzip_static on 的协同行为——只要存在 .br 文件,就直接返回它,不查 .gz;没有 .br 才查 .gz;两者都无,才考虑动态压缩(应避免)。
确保底层支持:必须安装 ngx_brotli 模块
Nginx 官方不内置 Brotli,必须手动编译集成 google/ngx_brotli 模块,并链接 libbrotli 库。宝塔用户可在「软件管理 → Nginx → 设置 → 编译扩展」中勾选“Brotli 压缩模块”;源码编译用户需在 configure 阶段加入:--add-module=/path/to/ngx_brotli。
安装后重启 Nginx,执行 nginx -V 2>&1 | grep -o brotli 应有输出,否则配置无效。
核心配置:brotli_static always + gzip_static on 共存
在 http 或 server 块中启用双压缩并明确优先级逻辑:
- brotli on; —— 启用 Brotli 压缩能力
-
brotli_static always; —— 强制优先查找同名 .br 文件(如
app.js.br),找到即返回,零 CPU 开销 -
brotli_types 列出文本类 MIME 类型,例如:
text/html text/css application/javascript application/json image/svg+xml - brotli_comp_level 6; —— 静态资源推荐 6 级;若用于 API 响应,可降为 3–4 级以降低延迟
- brotli_min_length 1024; —— 小于 1KB 不压缩,避免负优化
-
brotli_vary on; —— 强制返回
Vary: Accept-Encoding,防止 CDN 缓存错乱 - 同时保留完整 Gzip 配置:
gzip on; gzip_static on; gzip_types ...; gzip_vary on;
⚠️ 注意:brotli_static always 和 gzip_static on 都要求对应压缩文件真实存在且可读(Linux 下检查权限和属主)。若 index.html.br 缺失,Nginx 不会自动 fallback 到 index.html.gz,除非客户端请求头也含 gzip 且 gzip_static 已启用——这正是“优先 Brotli、兜底 Gzip”的实际路径。
构建阶段必须预生成 .br 文件
运行时动态压缩不可靠、不可控、增加延迟。所有静态资源(JS/CSS/HTML/SVG/JSON)应在构建时生成 .br 文件:
- Vite 项目:用
vite-plugin-compression,algorithm: 'brotliCompress',threshold: 1024,deleteOriginFile: false - Webpack 项目:用
compression-webpack-plugin,同样指定algorithm: 'brotliCompress',注意test正则需覆盖/\.(html|js|css|json)$/i - 产出后检查
dist/目录是否包含main.js.br、style.css.br等,文件大小应明显小于原始文件
验证是否生效:三步确认法
仅看配置没用,必须实测响应头:
- 打开 Chrome DevTools → Network → 刷新页面 → 找一个 JS 或 CSS 请求
- 查看 Response Headers 中是否有
Content-Encoding: br - 再检查是否有
Vary: Accept-Encoding(缺它会导致 CDN 缓存污染) - 若始终是
gzip或无压缩,先确认站点已强制 HTTPS(Brotli 在 HTTP 下不会被浏览器声明支持)











