图片和 <iframe>
元素通常比其他类型的资源消耗更多带宽。对于 <iframe>
元素,加载和渲染其中的页面可能涉及相当多的额外处理时间。
对于延迟加载图片,延迟加载初始视口之外的图片有助于减少初始视口内更关键资源的带宽争用。在网络连接较差的情况下,这可以在某些情况下改进页面的最大内容ful 绘制 (LCP),并且重新分配的带宽可以帮助LCP 候选元素更快地加载和绘制。
就 <iframe>
元素而言,通过延迟加载它们,可以在启动期间改进页面的与下一次绘制的交互 (INP)。这是因为 <iframe>
是一个完全独立的 HTML 文档,具有自己的子资源。虽然 <iframe>
元素可以在单独的进程中运行,但它们与其它线程共享进程的情况并不少见,这可能会导致页面对用户输入的响应速度降低。
因此,延迟加载屏幕外图片和 <iframe>
元素是一项值得追求的技术,并且只需相对较少的精力即可获得相当不错的性能回报。本模块介绍了如何在页面关键启动期间延迟加载这两种类型的元素,以获得更快、更好的用户体验。
使用 loading
属性延迟加载图片
可以将 loading
属性添加到 <img>
元素,以告知浏览器应如何加载它们
"eager"
通知浏览器应立即加载图片,即使它在初始视口之外也是如此。这也是loading
属性的默认值。"lazy"
延迟加载图片,直到它位于距可见视口一定距离内。此距离因浏览器而异,但通常设置为足够大,以便在用户滚动到图片时加载图片。
还值得注意的是,如果您使用的是 <picture>
元素,则 loading
属性仍应应用于其子 <img>
元素,而不是 <picture>
元素本身。这是因为 <picture>
元素是一个容器,其中包含指向不同图片候选项的其他 <source>
元素,并且浏览器选择的候选项直接应用于其子 <img>
元素。
不要延迟加载初始视口中的图片
您应该仅将 loading="lazy"
属性添加到位于初始视口之外的 <img>
元素。但是,在页面渲染之前,很难知道元素相对于视口的精确位置。必须考虑不同的视口大小、宽高比和设备。
例如,桌面视口可能与手机上的视口大相径庭,因为它渲染了更多的垂直空间,这可能会容纳初始视口中的图片,而这些图片不会出现在物理尺寸较小的设备的初始视口中。以纵向模式使用的平板电脑也显示了相当大的垂直空间,甚至可能比某些桌面设备还要多。
但是,在某些情况下,很明显您应该避免应用 loading="lazy"
。例如,在英雄图片的情况下,或者在 <img>
元素可能出现在首屏或任何设备上的布局顶部附近的其他图片用例中,您绝对应该省略 loading="lazy"
属性。对于可能成为 LCP 候选元素的图片,这一点甚至更为重要。
延迟加载的图片需要等待浏览器完成布局,才能知道图片的最终位置是否在视口内。这意味着,如果可见视口中的 <img>
元素具有 loading="lazy"
属性,则仅在下载、解析所有 CSS 并将其应用于页面之后才请求它,而不是在预加载扫描器在原始标记中发现它时立即获取它。
由于 <img>
元素上的 loading
属性在所有主流浏览器上都受支持,因此无需使用 JavaScript 来延迟加载图片,因为向页面添加额外的 JavaScript 以提供浏览器已提供的功能会影响页面性能的其他方面,例如 INP。
图片延迟加载演示
延迟加载 <iframe>
元素
延迟加载 <iframe>
元素直到它们在视口中可见可以节省大量数据,并改进加载顶级页面所需的关键资源。此外,由于 <iframe>
元素本质上是在顶级文档中加载的整个 HTML 文档,因此它们可以包含大量子资源(尤其是 JavaScript),如果这些帧中的任务需要大量的处理时间,则可能会严重影响页面的 INP。
第三方嵌入是 <iframe>
元素的常见用例。例如,嵌入式视频播放器或社交媒体帖子通常使用 <iframe>
元素,并且它们通常需要大量子资源,这也可能导致顶级页面的资源带宽争用。例如,延迟加载 YouTube 视频的嵌入在初始页面加载期间节省了超过 500 KiB,而延迟加载 Facebook “赞”按钮插件节省了超过 200 KiB,其中大部分是 JavaScript。
无论如何,只要页面上有首屏下方的 <iframe>
,如果它不是预先加载的关键元素,您都应强烈考虑延迟加载它,因为这样做可以显着改善用户体验。
<iframe>
元素的 loading
属性
<iframe>
元素上的 loading
属性在所有主流浏览器中也受支持。loading
属性的值及其行为与使用 loading
属性的 <img>
元素相同
"eager"
是默认值。它通知浏览器立即加载<iframe>
元素的 HTML 及其子资源。"lazy"
延迟加载<iframe>
元素的 HTML 及其子资源,直到它位于距视口的预定义距离内。
延迟加载 iframe 演示
外观模式
您可以根据用户交互按需加载嵌入,而不是在页面加载期间立即加载嵌入。这可以通过显示图片或其他适当的 HTML 元素来完成,直到用户与之交互。一旦用户与元素交互,您就可以将其替换为第三方嵌入。此技术称为外观模式。
外观模式的常见用例是来自第三方服务的视频嵌入,其中嵌入可能涉及加载许多额外的且可能昂贵的子资源(例如 JavaScript)以及视频内容本身。在这种情况下,除非有合法的需求让视频自动播放,否则视频嵌入需要用户在播放前通过单击播放按钮与之交互。
这是一个展示与视频嵌入在视觉上相似的静态图片并节省大量带宽的绝佳机会。一旦用户单击图片,它将被实际的 <iframe>
嵌入替换,这将触发第三方 <iframe>
元素的 HTML 及其子资源开始下载。
除了改进初始页面加载之外,另一个关键优势是,如果用户从不播放视频,则永远不会下载交付视频所需的资源。这是一个很好的模式,因为它确保用户仅下载他们实际想要的内容,而不会对用户的需求做出可能错误的假设。
聊天小部件是外观模式技术的另一个出色用例。大多数聊天小部件都会下载大量 JavaScript,这可能会对页面加载和对用户输入的响应速度产生负面影响。与预先加载任何内容一样,成本是在加载时产生的,但对于聊天小部件而言,并非每个用户都打算与之交互。
另一方面,使用外观模式,可以将第三方的“开始聊天”按钮替换为虚假按钮。一旦用户有意义地与其交互(例如将指针在其上方悬停一段时间,或单击),则在用户需要时,实际的功能性聊天小部件将滑入到位。
虽然当然可以构建自己的外观模式,但对于更受欢迎的第三方,也有开源选项可用,例如用于 YouTube 视频的 lite-youtube-embed
、用于 Vimeo 视频的 lite-vimeo-embed
以及用于聊天小部件的 React Live Chat Loader。
JavaScript 延迟加载库
如果您需要延迟加载 <video>
元素、<video>
元素 poster
图片、CSS background-image
属性加载的图片或其他不受支持的元素,您可以使用基于 JavaScript 的延迟加载解决方案(例如 lazysizes 或 yall.js)来执行此操作,因为延迟加载这些类型的资源不是浏览器级功能。
特别是,没有音轨的自动播放和循环播放 <video>
元素是比使用动画 GIF 更高效的替代方案,动画 GIF 通常比视觉质量相当的视频资源大数倍。即便如此,这些视频在带宽方面仍然可能很大,因此延迟加载它们是另一种优化,可以大大减少浪费的带宽。
这些库中的大多数都使用 Intersection Observer API,如果页面的 HTML 在初始加载后发生更改,则还会使用 Mutation Observer API,以识别元素何时进入用户的视口。如果图片可见(或即将进入视口),则 JavaScript 库会将非标准属性(通常为 data-src
或类似属性)替换为正确的属性,例如 src
。
假设您有一个视频取代了动画 GIF,但您想使用 JavaScript 解决方案延迟加载它。使用 yall.js 可以通过以下标记模式实现
<!-- The autoplay, loop, muted, and playsinline attributes are to
ensure the video can autoplay without user intervention. -->
<video class="lazy" autoplay loop muted playsinline width="320" height="480">
<source data-src="video.webm" type="video/webm">
<source data-src="video.mp4" type="video/mp4">
</video>
默认情况下,yall.js 观察所有类为 "lazy"
的合格 HTML 元素。一旦 yall.js 在页面上加载并执行,视频将不会加载,直到用户将其滚动到视口中。届时,<video>
元素的子 <source>
元素上的 data-src
属性将交换为 src
属性,这会发送请求以下载视频并自动开始播放它。
测试您的知识
<img>
和 <iframe>
元素的 loading
属性的默认值是什么?
“eager”
“lazy”
何时可以合理地使用基于 JavaScript 的延迟加载解决方案?
loading
属性不受支持的资源,例如旨在替换动画图像的自动播放视频,或延迟加载 <video>
元素的 poster 图片的情况。何时外观模式是一种有用的技术?
下一步:预取和预渲染
现在您已经掌握了延迟加载图片和 <iframe>
元素,您可以很好地确保页面可以更快地加载,同时尊重用户的需求。但是,在某些情况下,资源的推测性加载可能是可取的。在下一个模块中,了解预取和预渲染,以及这些技术(在谨慎使用时)如何通过提前加载后续页面来显着加速到后续页面的导航。