Early Hints(HTTP 103)必须由后端在200响应前通过协议层主动发送,用于预加载HTML中将引用的资源;其生效依赖服务端正确配置(如Nginx early_hints on、绝对路径Link头)、PHP无提前输出、客户端支持(Chrome 103+)及HTML中href与Link头路径严格一致。

Early Hints(HTTP 103)不能靠 HTML 标签或前端代码触发,必须由后端在主响应(200 OK)发出前,通过协议层主动发送。它不是“让浏览器加载 CSS”,而是“告诉浏览器:等下 HTML 里会用这个 CSS,你先去连、先去下”。能否生效,取决于服务端是否真发出了合法的 103 响应头,且路径、协议、客户端全部对齐。
PHP 中发送 Link 头必须在任何输出前完成
PHP 脚本一旦输出空白、换行、BOM 或 echo,就再也无法发送 HTTP 头——103 更是如此,它比 200 还早,容错为零。
-
header('HTTP/2 103 Early Hints')不推荐手动写状态行,多数 SAPI(如 PHP-FPM)不支持;应依赖 Web 服务器(如 Nginx)或运行时(如 FrankenPHP)自动提升Link头到 103 阶段 - 正确做法是:在 PHP 开头调用
header('Link: </css/critical.css>; rel=preload; as=style; nopush'),且确保此前无echo、print、空白符、UTF-8 BOM - 若用模板引擎(如 Twig),需确认其未提前 flush 输出;可加
ob_start()开头兜底,但不能替代逻辑控制 - 测试是否成功:用
curl -v https://yoursite.com查看响应头中是否出现< HTTP/2 103和< Link:行
Nginx 配置 early_hints on 且 Link 路径必须绝对
Nginx ≥1.21.4 原生支持,但默认关闭;add_header Link 只有在 early_hints on 启用后,才会被自动前置到 103 响应中,否则它只会出现在最终 200 响应头里——那就完全失效了。
- 必须启用
http_v2或http_v3:监听行要含http2,例如listen 443 ssl http2 -
Link中的 URL 必须以/开头(如</css/app.css>),相对路径(css/app.css)会被浏览器直接忽略 - 不要把
add_header Link写在if块、location ~ \.php$内部或proxy_pass后面——Nginx 无法将其提升至 103 阶段 - 最小可行配置示例:
location / {<br> early_hints on;<br> add_header Link "</css/critical.css>; rel=preload; as=style; nopush";<br> proxy_pass http://php_backend;<br>}
Chrome 103+ 才真正解析 103 Link,且只对 HTML 中实际引用的 CSS 生效
浏览器收到 103 后不会立刻下载,而是进入预加载队列;但如果主 HTML 响应里根本没出现对应 <link rel="stylesheet" href="/css/critical.css">,这个提示就白发了——Chrome 会丢弃它,不触发任何加载行为。
立即学习“前端免费学习笔记(深入)”;
- HTML 中的
href必须和Link头里的路径**逐字一致**,包括查询参数(/css/app.css?v=1.2≠/css/app.css) - 不要省略
as=style或写成as=css——只有as=style是规范值,否则降级为低优先级 fetch -
nopush必须带上:避免与 HTTP/2 Server Push 冲突,尤其在 Cloudflare 或某些 Nginx 模块环境下 - Safari 当前(2026 年 9 月)仍不支持 103,Firefox 110+ 支持但默认禁用;别依赖它覆盖全量用户
最容易被忽略的点是:103 的价值完全绑定在「服务器思考时间」上——如果 PHP 查数据库只要 5ms,那 103 几乎没意义;但若主响应延迟来自外部 API、模板渲染或复杂鉴权,这段空窗期才是 103 发挥作用的唯一窗口。别在本地 HTTP/1.1 环境下调试,也别指望加个 Link 头就自动提速,它是一条需要端到端对齐的脆弱链路。


















