高效加载第三方 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 的脚本仍然可以阻止 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 支持略有不同,因此在不支持 preconnect 的浏览器中,dns-prefetch 可作为后备方案。请使用单独的链接标记安全地植入代码:

<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 发生更改或进行安全修复程序时,脚本可能会过时,并且无法自动更新。

使用 Service Worker 缓存来自第三方服务器的脚本

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

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