HTTP/2 Server Push 在当前 Nginx 稳定版(1.24.x/1.26.x)及 Chrome 96+、Firefox 97+ 中已彻底失效,应改用 Link: </path>; rel=preload 响应头实现兼容性预加载。

别配 http2_push 了——它在当前 Nginx 稳定版(1.24.x / 1.26.x)中已失效,Chrome 96+、Firefox 97+ 等主流浏览器也早在 2021 年起彻底移除 PUSH_PROMISE 支持。你看到的“配置成功”,基本是服务端单向发帧、客户端静默丢弃。
为什么 http2_push /style.css 不生效
不是路径写错,也不是 SSL 没开,而是协议层已废弃:
- Chrome DevTools Network 面板里根本不会出现 Initiator: Push 的请求
- chrome://net-internals/#http2 中即使看到 PUSH_PROMISE 日志,对应 stream 状态多为 Abandoned
- Nginx 日志若报 push limit exceeded,只说明服务端尝试推送失败,不代表客户端接收到了
- 官方自 1.13.9 起逐步弱化该功能,当前稳定版默认不编译 http2_push 指令
真正能用的替代方案:Link 响应头 + rel=preload
这是现代标准、全浏览器兼容(HTTP/1.1 和 HTTP/2 都行)、语义清晰且可控的预加载方式:
- 在 Nginx 的 location = /index.html 或根 location / 块中添加:
add_header Link '</static/css/app.css>; rel=preload; as=style';- 路径必须以
/ 开头(绝对 URI),as=style 必须准确匹配资源类型
- 该头默认透传,无需额外模块;若后端是 PHP/Node.js,也可由应用层动态生成,更精准
- 宝塔用户注意:别把 add_header Link 放在 server 全局块,否则图片、API 响应也会被误加
容易被忽略的关键细节
预加载不是无脑加,几个点常被跳过:
- 已带 Cache-Control: immutable 或强缓存的 CSS,再预加载就是冗余流量
- 字体文件(.woff2)体积小、首屏关键时才加 as=font;大图、视频一律跳过
- 若用 proxy_pass 或 PHP-FPM,Nginx 不会自动识别 HTML 中的 <link rel="preload">,必须由后端输出 Link 头,Nginx 才能透传
- 验证是否生效:打开 Chrome DevTools → Network → 刷新 → 查看目标 CSS 请求的 Initiator 列是否为 preload,并在响应头中搜索 link:
真正的优化难点不在“怎么推”,而在“推不推”——判断资源是否首屏关键、是否已缓存、是否会被实际使用。盲目套用旧教程里的 http2_push 配置,只会浪费带宽、干扰调试、掩盖真实瓶颈。


















