预取、预加载、预浏览

Avatar of Robin Rendle
Robin Rendle

DigitalOcean 提供适合您旅程每个阶段的云产品。 立即开始使用 $200 免费信用额度!

当我们谈论前端性能时,我们想到的是诸如合并、压缩、缓存或服务器上压缩资产之类的操作,以便页面加载更快,用户能够尽快完成目标。

资源预取是另一种提高性能的技术。 我们可以用它来告诉浏览器用户将来可能需要的资产——甚至在他们需要之前。

Patrick Hamann 解释

预取是一种向浏览器暗示将来肯定或可能使用资源的方式,有些暗示适用于当前页面,有些适用于可能的未来页面。

作为开发人员,我们比浏览器更了解我们的应用程序。 我们可以利用此信息告知浏览器有关核心资源的信息。

这种在用户需要之前猜测他们需求的做法被称为预浏览。 但它不仅仅是一种技术,它可以分解为多种不同的技术:dns-prefetchsubresource、标准的prefetchpreconnectprerender

DNS 预取

这将通知客户端,我们稍后将需要来自特定 URL 的资产,以便浏览器能够尽快解析 DNS。 假设我们需要来自 URL example.com的资源,例如图像或音频文件。 在文档的<head>中,我们将编写

<link rel="dns-prefetch" href="//example.com">

然后,当我们从该 URL 请求文件时,将不再需要等待 DNS 查找。 如果我们使用来自第三方或社交网络的代码,或者从<script>加载小部件,这将特别有用。

在他的关于前端性能的精彩文章中,Harry Roberts 建议使用这种技术

这一行简单的代码将告诉支持的浏览器在实际需要之前的一小段时间内开始预取该域的 DNS。 这意味着在浏览器命中实际请求小部件的脚本元素时,DNS 查找过程将已在进行中。 这只是让浏览器提前了一小步。

这看起来像是微不足道的性能改进,可能并不重要,但这并非一定如此——Chrome 一直在做类似的事情。 如果你在 URL 栏中输入一个域的小部分,它将自动预解析 DNS(有时甚至会预渲染页面),从而为每个请求节省宝贵的毫秒。

预连接

与 DNS 预取方法类似,预连接将解析 DNS,但它还将进行 TCP 握手和可选的 TLS 协商。 它可以像这样使用

<link rel="preconnect" href="https://css-tricks.org.cn">

有关更多信息,Ilya Grigorik 撰写了一篇关于这种便捷资源提示的精彩文章

现代浏览器尽其所能预判网站在实际请求发出之前将需要哪些连接。 通过尽早启动“预连接”,浏览器可以提前设置必要的套接字,并从实际请求的关键路径中消除代价高昂的 DNS、TCP 和 TLS 往返。

好消息是,我们终于可以帮助浏览器了;我们可以告诉浏览器,在启动实际请求之前,我们将需要哪些套接字,这可以通过在 Firefox 39 和 Chrome 46 中发布的新的预连接提示来实现!

预取

如果我们确定将来会需要特定资源,那么我们可以要求浏览器请求该项目并将其存储在缓存中以供以后参考。 例如图像或脚本,或者任何可以被浏览器缓存的内容

<link rel="prefetch" href="image.png">

与 DNS 预取不同,我们实际上是在请求和下载该资产并将其存储在缓存中。 但是,这取决于许多条件,因为预取可能会被浏览器忽略。 例如,客户可能会放弃在缓慢的网络上请求大型字体文件。 Firefox 只有在“浏览器空闲时”才会预取资源。

正如Bram Stein 在他的文章中解释的那样,这对网络字体来说可能有巨大的性能优势。 目前,字体文件必须等待 DOM 和 CSSOM 建立后才能开始下载。 但是,如果我们预取它们,那么就可以轻松地绕过这一瓶颈。

注意:虽然以前预取资产有点难以测试,但 Chrome 和 Firefox 现在将在 Network 面板中显示预取的资源。 此外,请记住,链接预取没有同源策略限制。

子资源(参见注意)

另一种预取技术有助于识别优先级最高的资源,这些资源应该在预取项目之前请求。 例如,在 Chrome 和 Opera 中,我们可以将以下内容添加到文档的head

<link rel="subresource" href="styles.css">

根据 Chromium 文档,它的工作原理如下

“LINK rel=subresource”提供了一种新的链接关系类型,其语义与 LINK rel=prefetch 不同。 虽然 rel=prefetch 提供了对后续页面上将使用资源的低优先级下载,但 rel=subresource 允许尽早加载当前页面内的资源。

所以:如果资产是当前页面所需的,或者如果尽快需要,那么最好使用subresource,否则坚持使用prefetch

重要说明:Andy Davies 澄清了它们实际的工作方式。 似乎它也将从 Chrome 中移除

预渲染页面

这是终极手段,因为prerender使我们能够抢先加载某个文档的所有资产,例如

<link rel="prerender" href="https://css-tricks.org.cn">

Steve Souders 撰写了一篇关于这种技术的精彩解释

这就像在一个隐藏的选项卡中打开 URL——所有资源都已下载、DOM 已创建、页面已布局、CSS 已应用、JavaScript 已执行,等等。 如果用户导航到指定的href,那么隐藏页面将被切换到视图,使其看起来是立即加载的。 Google 搜索多年来一直使用名为即时页面的功能。 微软最近宣布他们将在 IE11 上的必应中以类似的方式使用预渲染。

但要注意!你应该确定用户会点击该链接,否则客户端将毫无理由地下载渲染页面所需的所有资产。

Souders 继续说道

与所有这些预先工作一样,存在预测错误的风险。 如果预先工作很昂贵(例如,从其他进程中窃取 CPU、消耗电池或浪费带宽),那么就需要谨慎。 似乎很难预测用户接下来会访问哪个页面,但确实存在高置信度场景

  • 如果用户进行了一次搜索,并有明显的结果,那么该结果页面很可能在下一步加载。
  • 如果用户导航到登录页面,那么登录后的页面很可能在下一步加载。
  • 如果用户正在阅读多页文章或分页结果集,那么当前页面后的页面很可能在下一步加载。

最后,页面可见性 API可用于防止脚本在它们在用户屏幕上呈现之前执行。

好的,现在我们已经排除了这些设计考虑因素,我们可以谈谈规范中可能令人感兴趣的未来添加内容。

未来选项:预加载

名为preload的新规范建议,有时最好始终下载资产,而不管浏览器是否认为这是一个好主意。 与可以被忽略的预取资产不同,预加载资产必须被浏览器请求。

<link rel="preload" href="image.png">

所以,虽然预加载目前不受任何浏览器的支持,但它背后的理念确实很有趣。

总结

预测用户接下来会做什么很困难,这肯定需要大量的计划和测试。 但是,性能优势绝对值得追求。 如果我们愿意尝试这些预取技术,那么我们一定会以明显的方式改善用户体验。

关于预取、预加载、预浏览技术的更多信息