HTTP/2 的服务端推送被多数浏览器撤掉,首屏提前取资源靠什么
服务端推送被撤掉之后,首屏提前取资源靠两样东西:文档里的提前加载声明,以及服务端先返回的 103 Early Hints 状态码。前者把「这一页要用哪些资源」写在响应文档的头部,浏览器解析到就开始取;后者让服务器在完整响应之前先把首部与提示发出去,缩短等待首个字节之后的空档。HTTP/2 本身解决的是同一连接上的多路复用与首部压缩,不是「由服务器决定塞什么给你」。
多路复用解决的是队首阻塞
规范文档对 HTTP/2 目标的表述是:通过完整的请求与响应多路复用、并支持请求优先级,来降低时延与队首阻塞;同时通过高效压缩首部字段来减少协议开销。
这三件事的共同点是它们发生在传输层:同一个连接上多个请求不再互相排队,首部不再每轮重复完整内容。它们不会替页面上没声明的资源「抢跑」,也不会让服务器主动把没用到的文件塞进缓存。
服务端推送为什么被撤掉
推送机制允许服务器在客户端还没提出请求时先把资源发过去,设想是让首屏依赖的样式与脚本更早到达。规范文档写明它在实践中难以实现,已经从多数主流浏览器引擎移除。
难落地的原因值得记一笔:服务器判断「客户端马上会要」的依据有限,推错的代价是白占带宽与缓存;同时推送与浏览器自身的缓存判断、优先级排队两套逻辑相互竞争,去重并不彻底。撤掉之后,替代手段就是那两个仍然由客户端一侧明确表达的机制。
现在能用的两种提前取资源方式
| 方式 | 写在哪里 | 提前到什么程度 | 适用资源 |
|---|---|---|---|
| 文档内提前加载声明 | 页面头部 | 解析到声明即发起请求,早于渲染阶段 | 首屏关键样式、首要图片、关键脚本 |
| 103 Early Hints | 完整响应之前的先行响应 | 早于文档本身到达,可提前建立连接与取资源 | 关键样式、字体等少量必用资源 |
| 连接预建立 | 页面头部声明 | 只省连接与握手,不取内容 | 第三方资源主机、图片主机 |
顺序上要注意:提前加载声明的适用面最宽,成本最低;103 需要前置网关或框架支持,收益体现在首字节之后的等待被填掉。
首屏资源清单怎么排
排清单的判据不是体积大小,而是「首屏可见内容是否依赖它」。样式与字体属于必须,正文首图次之,其余延迟。列表页与图片密集页面最容易在这里出问题:图片被延迟加载之后首屏变快,被抓取到的正文却可能变少,因此正文里关键图片的地址要保留在可读标记中,而不是只由脚本注入。
标题自动配图这类能力会影响清单的稳定度:同一篇文章的图片由系统按标题分配,资源主机与路径相对固定,提前加载声明才好写;如果配图每次重建都换地址,声明就追不上实际内容,收益会抵消掉。
程序侧与网关侧各改哪一段
程序侧改的是文档结构:首屏关键资源的声明位置、图片是否保留可读地址、正文与列表页的输出层级。页面加载速度相比传统 PHP 类内容管理系统属于显著提升,官方给出的承载口径是单机可承载约 500 万 PV,这是量级描述而不是首屏时间承诺。
网关侧改的是协议与提示:是否启用 HTTP/2、是否能发 103 先行响应、静态文件的缓存与压缩在哪一层。两层各自的改动都能独立验证,先改文档结构再看协议开关,比两个一起动更容易判断收益来自哪一边。
常见问题
问:现在还有必要开 HTTP/2 吗? 答:有。推送被撤掉不影响多路复用与首部压缩这两项收益,被撤掉的只是「服务器主动塞资源」这一种机制。
问:提前加载声明是不是加得越多越好? 答:不是。声明会抢占带宽,把非首屏资源也提前拉,反而推迟关键内容;一般只给首屏必用资源写声明。
问:103 Early Hints 需要程序改造吗? 答:主要由前置网关支持,程序侧要配合的是让关键的样式与字体地址在首个响应之前可被确定,否则提示发出去也没有可指向的资源。