http/2 server push 已被主流浏览器弃用,现仅能通过 link: rel=preload; as=style; nopush 实现预加载,而关键css应内联以零延迟渲染。

HTTP/2 Server Push 已无法在现代浏览器中可靠工作——Chrome 96+、Firefox 90+、Edge 100+ 全部移除了支持。你现在看到的“推送成功”,大概率是浏览器把它当成了 Link: rel=preload 处理,而非真正的服务器推送。
为什么 Link Header 中的 rel=preload 不等于 Server Push
浏览器收到 Link: ; rel=preload; as=style 时,只做一件事:提前发起 fetch 请求,不阻塞解析,但仍是客户端主动拉取。真正的 Server Push 是服务器在响应 HTML 前,未经请求就把字节流推到客户端连接上——这个通道早在 2021 年起就被各大浏览器逐步关闭。
-
rel=preload是声明式提示,浏览器可结合缓存、网络状态、渲染阶段决定是否加载、何时加载 -
rel=push不存在;HTTP 规范里没有这个值,rel=preload; nopush才是明确告诉浏览器“别推,只预加载” - 如果你在 Nginx 配置了
http2_push /style.css,且用的是较新版本 Chrome,它根本不会触发推送帧,Network 面板里也看不到 push initiator 标识
如何正确用 Link Header 加载 CSS(兼容所有现代浏览器)
唯一被广泛支持且语义清晰的方式,是在返回 HTML 的响应头中注入 Link,并确保:
- 只在
text/html响应里加,不要全局中间件注入(否则 JSON、图片等响应也会带上,引发警告或被忽略) - 路径必须是绝对路径,比如
/static/main.css,不能是./main.css或main.css -
as=style必须显式写出,否则浏览器不会按 CSS 解析逻辑处理,可能降级为普通 fetch - 加上
nopush,避免旧服务端逻辑误触发已废弃的推送机制
Node.js 示例:
app.get('/', (req, res) => {
res.set('Link', '/main.css>; rel=preload; as=style; nopush');
res.sendFile(path.join(__dirname, 'index.html'));
});
比 Link Header 更快的 CSS 加载方式:内联关键 CSS
Link: rel=preload 再快,也要走网络。而首屏渲染最卡脖子的,往往是 CSS 阻塞解析。真正零延迟的方案是把关键样式(Critical CSS)直接写进 的 <style></style> 标签里:
- 它不依赖 HTTP/2、不依赖缓存、不依赖 DNS,HTML 一到达就可解析
- 非关键 CSS 仍可用
<link rel="stylesheet" href="...">异步加载,配合media属性(如media="print"或media="(min-width: 768px)")避免阻塞 - 工具如
critters(Webpack)、penthouse可自动提取 Critical CSS,别手写
容易被忽略的性能细节
即使 Link 头写对了,效果也可能打折:
- 如果
main.css文件超过 15KB 且未启用Brotli压缩,预加载反而增加 TTFB 压力 - 资源放在 HTTP/1.1 连接上时,
rel=preload仍会触发额外请求,失去并行优势 - CDN 或反向代理(如 Nginx、Cloudflare)可能剥离或重写
Link头,需确认其透传配置 -
as=style错写成as=css或漏掉,会导致浏览器不复用该 preload 资源去解析样式表
真正起效的链路是:HTML 响应头含正确 Link → 浏览器发起预加载 → 资源进内存缓存 → <link rel="stylesheet"> 解析时直接复用。任何一环断开,就退回传统模式。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











