根本原因是.br文件缺失、权限不足或gzip_static抢先响应;需检查文件存在性、路径匹配、权限设置,并禁用gzip_static或缩小gzip_types范围以避免干扰。

当 Nginx 配置了 brotli_static on 却没返回 br 压缩内容,反而 fallback 到 gzip 甚至不压缩,说明降级逻辑没按预期走——根本原因通常是 .br 文件缺失、权限不对,或 gzip 抢先响应。排查要从“文件是否存在”和“Nginx 是否真在找它”两头入手。
确认 .br 文件真实存在且路径匹配
Nginx 的 brotli_static on 只认严格同名 + .br 后缀的文件。例如请求 /static/js/app.js,它只查找 /static/js/app.js.br,不会尝试 /static/js/app.br 或 /static/js/app.js.brotli。
- 进服务器,用
ls -l检查对应路径下.br文件是否真的存在,大小不能为 0 - 确保构建工具(如 Vite 的
vite-plugin-compression)已启用algorithm: 'brotliCompress'并输出了.br文件,且deleteOriginalAssets: false - 检查 Nginx 配置中
root或alias路径是否与文件实际位置一致;路径错位会导致“找不到”却无报错
验证 Nginx 是否真正加载了 .br 文件
即使文件存在,Nginx 也可能因权限或配置跳过它,静默回退到原始文件(未压缩)或触发 gzip。
- 用
curl -I -H "Accept-Encoding: br" https://yoursite.com/static/js/app.js查看响应头:
若返回Content-Encoding: br→ 成功;
若返回Content-Encoding: gzip→ gzip 抢先了;
若无Content-Encoding→ 直接回退到未压缩原文件 - 开启 Nginx error log 的
info级别,在error_log /var/log/nginx/error.log info;下复现请求,日志里会明确写 “open() "/path/to/file.br" failed (13: Permission denied)” 或 “no br file found” - 检查
.br文件权限:必须对 Nginx worker 进程用户(如www-data或nginx)可读,常用命令:chown root:www-data *.br && chmod 644 *.br
防止 gzip 抢在 Brotli 前响应
这是最隐蔽的降级失败点:客户端同时支持 br,gzip,但 Nginx 因配置不当优先走了 gzip 流程。
- 禁用
gzip_static on—— 它和brotli_static on共存时,只要.gz文件存在,Nginx 就可能忽略.br直接发 gzip 版 - 缩小
gzip_types范围,只保留极老客户端必需的类型(如text/plain),避免与brotli_types重叠;重叠项会让 gzip 模块“插队” - 确保
brotli_types明确包含application/javascript、text/css等目标类型;漏掉任一 MIME 类型,该类资源就完全绕过 Brotli
用 map 实现可控的降级兜底
不依赖“找不到 .br 就自动试 gzip”,而是显式控制:先查 .br,失败则根据客户端能力决定是上 gzip 还是裸发。
- 定义降级变量:
map $http_accept_encoding $use_gzip {<br> default "";<br> "~*br" "";<br> "~*gzip" "on";<br>} - 在 location 中结合:
gzip on;<br>gzip_static $use_gzip;<br>brotli_static on;
这样只有明确不支持 br 但支持 gzip 的请求,才启用 gzip_static











