http/2 server push 已被 chrome 96+、firefox 90+、edge 96+ 全面废弃,浏览器直接忽略 push_promise 帧;替代方案是 或 link: ; rel=preload; as=y 响应头。

HTTP/2 Server Push 在现代浏览器中已基本不可用
直接说结论:Chrome 96+、Firefox 90+、Edge 96+ 全部移除了对 HTTP/2 Server Push 的支持,且没有回退开关。不是配置问题,不是 Nginx 版本低,而是协议层被浏览器主动废弃了。你看到的“推送失败”“资源没被接收”“Network 面板里看不到 push 流”,都是预期行为。
Nginx 的 http2_push 指令现在只起心理安慰作用
即使你在 Nginx 配置里写了:
location / {
http2_push /style.css;
http2_push /script.js;
proxy_pass http://backend;
}
现代浏览器收到后会直接忽略这些 PUSH_PROMISE 帧。Wireshark 或 nghttp 工具仍能抓到推送帧,但 Chrome DevTools 的 Network 面板不再显示,performance.getEntries() 也不会记录被推送的资源。
真正生效的替代方案是:
-
<link rel="preload">(推荐):由 HTML 主动声明,语义明确、可控性强、全浏览器支持 -
Link: ; rel=preload; as=styleHTTP 响应头:服务端在响应 HTML 时带出,效果等同于<link preload> - 不依赖推送,靠 HTTP/2 多路复用 + 更小的首字节延迟,本身已比 HTTP/1.1 快很多
如果你非要验证 Server Push 是否“发出”,得绕过浏览器
用命令行工具确认服务端是否真发了 PUSH_PROMISE:
安装 nghttp(来自 nghttp2):
nghttp -nv https://yoursite.com/
观察输出中是否有类似这样的行:
[ 0.123] recv PUSH_PROMISE frame <stream_id><promised_stream_id></promised_stream_id></stream_id>
注意:recv 表示服务器发出了,不代表客户端收了或用了。Chrome/Firefox 现在收到后直接丢弃,不建立流、不缓存、不触发 fetch 事件。
常见误判点:
- 用
curl -v --http2看不到 push,因为 curl 默认不处理 PUSH_PROMISE - 在 Chrome Network 面板里右键“Copy as cURL”,再执行——还是看不到,因为 cURL 不模拟浏览器 push 消费逻辑
- Nginx 日志里有
$http2变量为h2,只说明用了 HTTP/2,和 push 无关
真正该做的:用 preload 替代 push,且注意 as 值必须准确
<link rel="preload"> 不是万能的,as 属性错会导致浏览器降级为普通 fetch,失去优先级提升和预加载优势:
<link rel="preload" href="/style.css" as="style"><link rel="preload" href="/logo.svg" as="image"><link rel="preload" href="/main.js" as="script"><link rel="preload" href="/data.json" as="fetch" crossorigin>
关键细节:
-
as="script"和as="fetch"本质不同:前者走 JS 解析流水线,后者走 fetch API 调度器 - 带
crossorigin的资源(如 CDN 上的字体、JSON),as必须匹配,否则被忽略 - 不要 preload 太多资源:浏览器有并发 preload 限制(通常 ≤6),超出的会被丢弃
- 服务端发送
Link头时,语法必须严格:Link: ; rel=preload; as=style,空格和分号缺一不可
Server Push 是个已被淘汰的优化手段;现在所有“预加载”逻辑,都应该落在 HTML 结构、HTTP 响应头或构建时注入的 preload 上。别再花时间调 http2_push_preload on 这类已失效指令。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











