高效加载第三方 JavaScript

Milica Mihajlija
Milica Mihajlija

如果某个第三方脚本降低了网页加载速度,您可以通过以下两种方式提高性能:

  • 如果它无法为您的网站带来明确价值,请将其移除。
  • 优化加载流程。

本文介绍了如何使用以下技术优化第三方脚本的加载过程:

  • <script> 标记使用 asyncdefer 属性
  • 与必需的源建立早期连接
  • 延迟加载
  • 优化第三方脚本的提取方式

使用 asyncdefer

由于同步脚本会延迟 DOM 构建和渲染,因此您应始终异步加载第三方脚本,除非脚本必须在页面渲染之前运行。

asyncdefer 属性会告知浏览器,它可以在后台加载脚本时继续解析 HTML,然后在脚本加载后执行该脚本。这样,脚本下载不会阻止 DOM 构建或页面呈现,让用户可以在所有脚本都加载完毕之前看到页面。

<script async src="script.js">

<script defer src="script.js">

asyncdefer 属性的区别在于浏览器执行脚本的时间。

async

具有 async 属性的脚本会在下载完成后、窗口的 load 事件之前,在有机会时执行。这意味着,async 脚本可能不会按其在 HTML 中的显示顺序运行。这也意味着,如果在解析器仍在运行时下载完成,则可以中断 DOM 构建。

包含 async 属性的解析器阻塞脚本示意图
包含 async 的脚本仍可能会阻止 HTML 解析。

defer

具有 defer 属性的脚本会在 HTML 解析完全完成之后,但在 DOMContentLoaded 事件之前执行。defer 可确保脚本按其在 HTML 中的显示顺序运行,并且不会阻塞解析器。

包含具有 defer 属性的脚本的解析器流程示意图
带有 defer 的脚本会等到浏览器完成 HTML 解析后再运行。
  • 如果您希望脚本在加载过程中尽早运行,请使用 async
  • 对重要性较低的资源(例如折叠线下方的视频播放器)使用 defer

使用这些属性可以显著加快网页加载速度。例如,Telegraph 推迟了所有脚本的加载时间,包括广告和分析脚本,平均缩短了广告加载时间 4 秒。

尽早建立与必需源的连接

通过尽早与重要的第三方来源建立连接,您可以节省 100-500 毫秒的时间。

此时,两个 <link> 类型 preconnectdns-prefetch 可以派上用场:

preconnect

<link rel="preconnect"> 会告知浏览器您的网页想要与另一个起点建立连接,以及您希望尽快启动该过程。当浏览器从预连接的来源请求资源时,下载会立即开始。

<link rel="preconnect" href="https://cdn.example.com">

dns-prefetch

<link rel="dns-prefetch> 只处理 <link rel="preconnect"> 处理的一小部分内容。建立连接涉及 DNS 查询和 TCP 握手,对于安全来源,还涉及 TLS 协商。dns-prefetch 会告知浏览器仅在明确调用特定网域之前解析其 DNS。

preconnect 提示最好仅用于最重要的连接。对于不太重要的第三方网域,请使用 <link rel=dns-prefetch>

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

浏览器对 dns-prefetch 的支持与对 preconnect 的支持略有不同,因此 dns-prefetch 可以作为不支持 preconnect 的浏览器的后备方案。请使用单独的链接标记安全地实现此操作:

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

延迟加载第三方资源

如果嵌入的第三方资源构建不当,可能会显著降低网页加载速度。如果这些资源不是必需的,或者位于可见区域下方(即用户必须滚动屏幕才能看到它们),则延迟加载是一种提高网页速度和绘制指标的好方法。这样,用户可以更快地获取主页内容,并获得更好的体验。

一张示意图,显示了在移动设备上显示的网页,其中可滚动内容超出了屏幕。折叠线下方的内容未加载,因此会呈现低饱和度。
延迟加载非首屏内容。

一种有效的方法是在主页面内容加载完毕后延迟加载第三方内容。广告非常适合这种方法。

广告是许多网站的重要收入来源,但用户是为了内容而来。通过延迟加载广告并更快地提交主要内容,您可以提高广告的总体可见度百分比。例如,MediaVine 改用延迟加载广告后,网页加载速度提高了 200%。Google Ad Manager 提供了有关如何延迟加载广告的文档。

您还可以将第三方内容设置为仅在用户首次滚动到页面相应部分时加载。

Intersection Observer 是一种浏览器 API,可高效检测元素何时进入或退出浏览器的视口,您可以使用它来实现此技术。lazysizes 是一个用于延迟加载图片和 iframes 的热门 JavaScript 库。它支持 YouTube 嵌入内容和微件。它还可选支持 Intersection Observer。

使用 loading 属性延迟加载图片和 iframe 是 JavaScript 技术的绝佳替代方案,最近已在 Chrome 76 中推出!

优化第三方脚本的提取方式

以下是一些关于优化第三方脚本使用方式的建议策略。

第三方 CDN 托管

第三方供应商通常会提供其托管的 JavaScript 文件的网址(通常托管在内容分发网络 [CDN] 上)。这种方法的好处在于,您可以快速上手(只需复制并粘贴网址即可),并且无需维护开销。第三方供应商负责处理服务器配置和脚本更新。

但是,由于这些资源与您的其他资源不在同一来源,因此从公共 CDN 加载文件会产生网络费用。浏览器需要执行 DNS 查找、建立新的 HTTP 连接,并在安全来源上与供应商的服务器执行 SSL 握手。

使用第三方服务器中的文件时,您很少能控制缓存。依赖于他人的缓存策略可能会导致过于频繁地从网络中不必要地重新提取脚本。

自行托管第三方脚本

自行托管第三方脚本是一种选项,可让您更好地控制脚本的加载过程。通过自行托管,您可以:

  • 缩短 DNS 查找和往返时间。
  • 改进了 HTTP 缓存标头。
  • 利用 HTTP/2 或较新的 HTTP/3。

例如,Casper 通过自行托管 A/B 测试脚本,成功缩短了 1.7 秒的加载时间。

不过,自行托管有一个很大的缺点:脚本可能会过时,并且在发生 API 更改或安全修复时不会自动更新。

使用服务工作器缓存来自第三方服务器的脚本

您可以使用服务工件缓存来自第三方服务器的脚本,作为自行托管的替代方案。这样,您就可以更好地控制缓存,同时保留第三方 CDN 的优势。

您可以控制从网络重新提取脚本的频率,并创建一个加载策略,以限制对非必需第三方资源的请求,直到用户到达网页上的关键互动点。借助 preconnect,您可以提前建立连接,还可以帮助降低网络费用。