页面空白常因Brotli配置错误:模块未编译启用、响应头与体不匹配(如声明br但未压缩或文件缺失)、静态.br文件路径/权限错误、CDN干扰等,需逐项验证。

页面空白往往不是没响应,而是响应内容被浏览器拒绝解析——Brotli 配置错误时,Nginx 可能返回了 .br 文件但未正确声明编码,或返回了未压缩内容却带了 Content-Encoding: br,导致浏览器解压失败后静默丢弃整个响应体。
确认 Brotli 模块已加载且启用
Nginx 必须显式编译并启用 ngx_http_brotli_filter_module,仅安装 brotli 库或配置语法正确但模块未加载,会导致配置被忽略、无报错、无效果。
- 运行
nginx -V 2>&1 | grep brotli,输出中应含--with-http_brotli_module - 若无该字样,说明模块未编译进 Nginx,需重新编译或换用已集成该模块的发行版(如 OpenResty 1.25+)
- 检查配置中是否真有
brotli on;,且不在被注释或条件块内;它必须出现在http、server或location块中,且作用域覆盖目标资源路径
验证响应头与响应体严格匹配
浏览器只信任“头声明什么,体就是什么”。常见错配:Nginx 返回了原始 HTML,却因配置残留或 CDN 干预加了 Content-Encoding: br;或返回了 .br 文件但漏设 Content-Encoding,浏览器当普通二进制处理而触发下载或白屏。
- 用
curl -I -H "Accept-Encoding: br" https://yoursite.com/app.js查看响应头:必须同时存在Content-Encoding: br和Content-Type: application/javascript - 再执行
curl -H "Accept-Encoding: br" https://yoursite.com/app.js | zstd -d -t 2>/dev/null || echo "not valid br"(注意:brotli 解压需brotili工具,非zstd;正确命令为curl ... | brotli -d -t 2>/dev/null)——验证响应体能否真正解压 - 若头中有
br但体无法解压,说明 Nginx 实际未启用 Brotli,而是透传了上游未压缩内容(例如反向代理后端未压缩,又误加了 Vary/Accept-Encoding 头)
检查静态文件服务路径与 .br 文件存在性
Brotli 静态压缩依赖真实存在的 .br 文件。Nginx 不会自动压缩响应,brotli_static on 仅查找同名 .br 文件并直接返回——文件缺失、权限不足、路径不匹配都会导致 fallback 失败或 404/403,最终白屏。
- 确认请求的资源路径(如
/js/app.abc123.js)在磁盘上对应有/path/to/js/app.abc123.js.br,且属主可读(ls -l /path/to/js/app.abc123.js.br) -
brotli_static on必须放在具体location块内(如location ~ \.js$),不能只写在http块;否则不生效 - 若同时启用了
gzip_static on,确保二者不冲突;建议对同一资源只启用一种静态压缩,避免因匹配顺序导致意外 fallback
排查 CDN 或中间代理干扰
CDN 回源时若携带 Accept-Encoding: br, gzip,而源站 Nginx 未限制或未清空该头,可能触发错误压缩决策;更常见的是 CDN 缓存了带 br 头的空响应或乱码体,后续请求直接返回损坏内容。
- 在 Nginx
http块顶部添加map规则,对已知 CDN UA 强制清空Accept-Encoding:map $http_user_agent $bypass_br { ~*(Cloudflare|AliYun|AWSALB) ""; default $http_accept_encoding; }
然后在location中设proxy_set_header Accept-Encoding $bypass_br; - 临时禁用 CDN,直连源站测试;或使用
curl --resolve绕过 DNS 直击源 IP,排除 CDN 缓存污染 - 检查响应中是否有
Vary: Accept-Encoding—— 若有,且 CDN 未按此头做多版本缓存,则必然乱码;此时应统一禁用 Brotli 或确保 CDN 全链路支持











