link响应头预加载css仅在103 early hints中有效,需服务端支持103、客户端为chrome103+/edge103+/firefox110+且使用http/2或http/3;200响应中的link头会被忽略,因html已开始传输,失去提前调度意义。

直接用 Link 响应头预加载 CSS 是可行的,但必须满足三个硬性条件:服务端支持发送 103 Early Hints、客户端是 Chrome 103+/Edge 103+/Firefox 110+、且走 HTTP/2 或 HTTP/3;否则浏览器会直接忽略该头。
为什么 Link 响应头在 200 响应里不起作用?
HTTP 规范要求 Link: rel=preload 出现在 103 Early Hints 响应中才被浏览器视为“可提前触发下载”的指令。如果把它塞进最终的 200 OK 响应头里(比如 Nginx 的 add_header),浏览器会解析它,但不会发起预加载——因为此时 HTML 已开始传输或已解析完毕,失去提前调度意义。
常见错误现象:
– 开发者在 PHP 中 header('Link: ; rel=preload; as=style') 放在 echo 之后,结果完全没效果
– Nginx 配置了 add_header Link "...";,但日志显示浏览器没发额外请求
– 使用 curl -I 看到 Link 头存在,但 Network 面板里没有提前出现 CSS 请求
Link 头格式必须严格正确
哪怕一个字符错,浏览器也会静默丢弃整个 Link 指令。关键约束包括:
-
href值必须是绝对路径(如/css/main.css),不能是相对路径./main.css或协议相对路径//cdn.com/style.css - 必须显式声明
as=style,不能省略或写成as=stylesheet - 推荐加上
nopush(尤其在使用 HTTP/2 Server Push 的旧环境),避免与 push 冲突 - 多个资源用英文逗号分隔,不是分号或换行
正确示例:Link: /main.css>; rel=preload; as=style; nopush, /inter.woff2>; rel=preload; as=font; crossorigin
错误示例:Link: ./main.css; rel=preload; as=style(相对路径)Link: <main.css>; rel=preload; as=style</main.css>(缺少斜杠)
PHP 中发送 103 Early Hints 的实际限制
不是所有 PHP 环境都能发 103。只有 FrankenPHP、RoadRunner 或自定义 SAPI 才原生支持;传统 FPM/Apache 模式下,header() 调用无法触发真正的 103 响应,最多模拟出一个带 Link 头的 200。
可行路径:
- FrankenPHP 用户:调用
headers_send(103)前执行所有header('Link: ...') - Nginx + 自定义模块(如 nginx-early-hints):需编译启用,并在 location 块中配置
early_hints on; - Cloudflare:开启 Early Hints 功能后,通过 Worker 注入
Link头并返回103
注意:任何 echo、print、输出缓冲开启(ob_start())或空格输出,都会导致 103 发送失败,降级为普通响应。
比起 Link 响应头,<link rel="preload"> 更现实
如果你无法控制服务端或不确定客户端是否支持 103,直接在 HTML 里写:<link rel="preload" href="/css/critical.css" as="style">
再配一个正常引入:<link rel="stylesheet" href="/css/critical.css">
这样兼容性好(Chrome 50+、Firefox 65+、Safari 11.1+)、无需改服务架构、调试直观。唯一代价是比 103 晚几百毫秒——但对多数站点,这比折腾不稳定的 Early Hints 更可靠。
真正容易被忽略的是:预加载只是“下载”,不等于“应用”。rel="preload" 的 CSS 不会自动生效,必须另配 rel="stylesheet",否则白忙一场。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











