Early Hints如何加速网页加载与提升用户体验

W″馨然 优化 阅读 1,704
赞 21 收藏
二维码
手机扫码查看
反馈

我的写法,亲测靠谱

Early Hints(103 Early Hints)这玩意儿我最早是在一个首屏加载特别慢的项目里试水的。当时用户一打开页面,白屏得能煎蛋,Lighthouse 评分惨不忍睹。后来琢磨着用 Early Hints 提前把关键资源推下去,效果确实立竿见影——首屏快了近 400ms。但中间踩的坑也不少,今天就把我现在用的稳定方案和大家唠唠。

Early Hints如何加速网页加载与提升用户体验

我现在的做法是:在服务端响应 HTML 之前,先发一个 103 响应,把关键 CSS、JS、字体这些资源的 Link 头提前告诉浏览器。注意,只推真正关键的,别一股脑全塞进去,否则适得其反。

以下是我用 Node.js + Express 的实际代码(其他语言逻辑类似):

app.get('/page', (req, res) => {
  // 先发 Early Hints
  res.writeEarlyHints({
    link: [
      '</static/main.css>; rel=preload; as=style',
      '</static/app.js>; rel=preload; as=script',
      '</fonts/inter.woff2>; rel=preload; as=font; type="font/woff2"; crossorigin'
    ]
  });

  // 模拟一些异步数据获取(比如查数据库)
  setTimeout(() => {
    const html = 
      &lt;!DOCTYPE html&gt;
      &lt;html&gt;
        &lt;head&gt;
          &lt;link rel=&quot;stylesheet&quot; href=&quot;/static/main.css&quot;&gt;
        &lt;/head&gt;
        &lt;body&gt;
          &lt;div id=&quot;app&quot;&gt;Loading...&lt;/div&gt;
          &lt;script src=&quot;/static/app.js&quot;&gt;&lt;/script&gt;
        &lt;/body&gt;
      &lt;/html&gt;
    ;
    res.send(html);
  }, 200);
});

这里有几个关键点:

  • 只 preload 真正阻塞渲染的资源:比如主样式、核心 JS、首屏用的字体。图片、非关键 JS 别乱加,会浪费带宽还可能触发浏览器的预加载限制。
  • 路径要和 HTML 里的一致:如果 HTML 里写的是 /static/main.css,Early Hints 里也必须完全一样,包括斜杠。不然浏览器会当成两个资源,重复下载。
  • 字体必须加 crossorigin:这点我一开始忘了,结果字体没生效,折腾半天才想起来。所有字体 preload 都得带这个属性,哪怕同源。

这几种错误写法,别再踩坑了

我见过也自己踩过不少 Early Hints 的坑,下面这些写法千万别学:

1. 把所有资源都塞进 Early Hints

有次我图省事,把十几个 JS、CSS、图片全推了,结果 Chrome 直接忽略了后面的 Link 头(因为超过内部限制)。更糟的是,有些资源还没被 HTML 引用,浏览器就提前下载了,纯属浪费流量。现在我严格控制在 3~5 个最关键资源。

2. 用相对路径或错路径

// 错!
res.writeEarlyHints({
  link: ['<main.css>; rel=preload; as=style']
});

浏览器解析时会基于当前 URL 拼接,但如果你的页面是 /user/profile,那它会去请求 /user/main.css,404 了。必须用绝对路径(以 / 开头)。

3. 忘记设置正确的 astype

比如字体不写 as=fonttype="font/woff2",浏览器就不知道怎么处理,可能直接忽略。JS 不写 as=script,可能被当成普通 fetch 请求,优先级不对。

4. 在不支持 Early Hints 的环境硬上

不是所有服务器都支持 103 响应。比如老版本 Nginx、某些 Serverless 平台(Vercel 目前还不支持原生 Early Hints)。我之前在本地开发用 Express 没问题,一上线到某个平台就失效了,查了半天才发现平台根本不透传 103。所以上线前务必确认基础设施支持

实际项目中的坑

除了上面那些,实战中还有几个细节容易翻车:

缓存策略要对齐。Early Hints 推的资源如果缓存时间很短,而 HTML 缓存时间长,用户下次访问时 HTML 从缓存读,但资源又要重新下,反而更慢。我现在统一给关键静态资源设一年缓存(带 hash 文件名),Early Hints 和 HTML 里的引用保持一致。

不要和 HTTP/2 Server Push 混用。虽然 Server Push 也能提前推资源,但它已经被废弃了,而且和 Early Hints 行为冲突。我之前在一个项目里同时开了两个,结果 Chrome 下载了两份 main.css,直接翻车。现在一律只用 Early Hints。

测试要真实环境。本地开发时用 localhost 很难看出效果,因为网络延迟几乎为零。我一般用 WebPageTest 或 Lighthouse 在模拟 3G 网络下跑,才能看到 Early Hints 带来的实际提升。另外,Chrome DevTools 的 Network 面板默认不显示 103 响应,得勾选 “Show all” 才能看到 Early Hints 条目。

还有个小问题:目前 Safari 对 Early Hints 的支持还不完善(截至 2024 年中),所以不能完全依赖它。我的做法是 Early Hints 作为增强,基础体验(比如关键 CSS 内联)依然要做好,保证 Safari 用户也不至于太慢。

要不要用?我的建议

如果你的项目满足以下条件,我建议上 Early Hints:

  • 首屏依赖外部 CSS/JS,且无法内联(比如 CMS 系统、多页面应用)
  • 服务端能控制 HTTP 响应(Node.js、PHP、Go 等都行,但 Serverless 可能受限)
  • 关键资源数量不多(3~5 个以内)

如果只是 SPA,且用了现代打包工具(Vite、Webpack)做了代码分割和预加载,可能收益不大。Early Hints 最适合那种“服务端吐 HTML + 外部静态资源”的传统架构。

最后提醒一句:Early Hints 不是银弹。我见过有人为了用它而重构整个构建流程,结果维护成本飙升,性能提升却微乎其微。**先用 Lighthouse 定位瓶颈,确认是资源发现延迟导致的问题,再考虑 Early Hints**。别为了炫技而加功能。

以上是我踩坑后的总结,希望对你有帮助。Early Hints 虽小,但用对了真能提速。有更好的方案欢迎评论区交流,比如你们在 Cloudflare 或 Nginx 上怎么配的,我也想学学。

本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。
发表评论

暂无评论