http/2服务器推送已全面失效,chrome 96+、firefox 90+、edge 96+均移除push_promise支持;应改用link rel="preload" as="style"提前加载关键css,并动态注入以确保准确性和安全性。

HTTP/2推送在现代CSS加载中实际失效了
HTTP/2服务器推送(Server Push)对CSS这类关键资源的主动推送,在主流浏览器中已基本被弃用——Chrome 96+、Firefox 90+、Edge 96+ 全部移除了对 push_promise 的支持。不是配置不对,是协议层直接不处理了。
你看到的“推送成功”日志或 curl --http2 -I 中的 PUSH_PROMISE 帧,大概率只是服务器单方面发了,客户端早已静默丢弃。
为什么Nginx/Apache配了http2_push也没用
因为浏览器不再响应 PUSH_PROMISE,即使你正确写了:
location /style.css {
http2_push /main.css;
}
这些配置现在只起两个作用:浪费一次TCP帧、误导运维以为“优化生效了”。真实加载路径仍是:HTML → 解析 → 发起CSS请求 → 等待响应。
立即学习“前端免费学习笔记(深入)”;
常见误判点:
- 用
chrome://net-internals/#http2看到 PUSH_PROMISE 日志 ≠ 浏览器真的接收并缓存了资源 - Wireshark 抓到 PUSH_PROMISE 帧 ≠ 资源提前进入渲染流程
- Lighthouse 仍显示“启用HTTP/2推送可提升FCP” —— 这是过时建议,未同步更新
真正该做的:用preload替代推送
link rel="preload" 是当前唯一可靠、标准化、全浏览器支持的“提前拉取CSS”手段,它由HTML发起,不依赖服务器协议特性。
实操要点:
- 只对首屏强依赖的CSS用,比如
critical.css,别盲目 preload 所有样式表 - 必须加
as="style",否则浏览器不会以高优先级下载,甚至可能阻塞解析 - 配合
onload补丁防止FOUC:<link rel="preload" href="/critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
- 不要和
rel="stylesheet"同时写同一个URL,会造成重复请求
Node.js/Express等后端如何安全注入preload
不能靠模板硬编码,得根据实际输出的CSS路径动态生成,否则容易漏推或错推。
推荐做法:
- 构建时提取关键CSS路径,写入一个轻量JSON(如
preload-manifest.json) - 运行时读取该文件,在HTML模板头部循环插入
<link rel="preload" ...> - 避免在中间件里用正则匹配HTML字符串插入 —— 容易破坏HTML结构,且无法处理流式响应
- 若用 Vite / Webpack,直接启用
build.rollupOptions.output.manualChunks+htmlPlugin插件生成 preload 标签更稳
HTTP/2推送不是“没配好”,是整个机制已被淘汰。现在拼的是谁更快把 preload 放进 ,以及是否真懂 critical CSS 的边界在哪里。










