现在该延迟加载屏幕外 iframe 了!

艾迪·奥斯曼尼
Addy Osmani

延迟加载 <iframe> 元素会将屏幕外 iframe 推迟加载,直到用户滚动到它们附近为止。这可以节省数据,加快页面其他部分的加载速度,并减少内存用量。

浏览器支持

  • 77
  • 79
  • 121
  • 16.4

您可以使用 loading 属性向浏览器指明要延迟加载 iframe,具体方式与延迟加载图片相同。

<iframe src="https://example.com"
        loading="lazy"
        width="600"
        height="400"></iframe>

以下 <iframe loading=lazy> 演示展示了延迟加载视频嵌入:

为何要延迟加载 iframe?

第三方嵌入适用于各种用例,从视频播放器到社交媒体帖子再到广告,不一而足。通常情况下,此类内容不会立即在用户视口中显示。而是仅在用户进一步向下滚动页面时才会看到。尽管如此,用户仍需为每一帧下载数据和支付高昂的 JavaScript 费用,即使用户不滚动到相应帧也是如此。

对 iframe 使用 iframe 延迟加载可节省的数据。在此示例中,Eager 加载会增加 3 MB 内存,而延迟加载只有在用户滚动到 iframe 附近之后才会提取此代码。

根据 Chrome 对为流量节省程序用户自动延迟加载屏幕外 iframe 的研究,使用延迟加载 iframe 可使流量节省中位数达到 2-3%,将 First Contentful Paint 减少 1-2%(达到中位数),并在第 95 百分位减少 2% First Input Delay (FID) 改进。

此外,延迟加载屏幕外 iframe 还可以给 Largest Contentful Paint (LCP) 带来好处。LCP 候选版本,例如依赖于网页字体的图片或文本,以便进行渲染。由于 iframe 通常需要大量的带宽来加载其所有子资源,因此延迟加载屏幕外 iframe 可以显著减少网络受限设备上的带宽争用,留下更多带宽来加载有助于页面 LCP 的资源。

iframe 的内置延迟加载功能是如何运作的?

借助 loading 属性,浏览器可以将加载屏幕外 iframe 和图片的时间推迟到用户滚动到它们附近时再加载。loading 支持两个值:

  • lazy:非常适合延迟加载。
  • eager:不适合进行延迟加载。立即加载。

在 iframe 上使用 loading 属性的运作方式如下:

<!-- Lazy-load the iframe -->
<iframe src="https://example.com"
        loading="lazy"
        width="600"
        height="400"></iframe>

<!-- Eagerly load the iframe -->
<iframe src="https://example.com"
        width="600"
        height="400"></iframe>

完全不指定该属性所产生的影响与显式快速加载资源相同。

如果您需要通过 JavaScript 动态创建 iframe,也支持在元素上设置 iframe.loading = 'lazy'

var iframe = document.createElement('iframe');
iframe.src = 'https://example.com';
iframe.loading = 'lazy';
document.body.appendChild(iframe);

如果网页发生变化,默认延迟加载屏幕外 iframe,则显示效果将如下所示:

延迟加载 YouTube 视频嵌入内容(初始网页加载时节省约 500KB):

<iframe src="https://www.youtube.com/embed/YJGCZCaIZkQ"
        loading="lazy"
        width="560"
        height="315"
        frameborder="0"
        allow="accelerometer; autoplay;
        encrypted-media; gyroscope;
        picture-in-picture"
        allowfullscreen></iframe>

趣闻:在为 Chrome.com 改用延迟加载 YouTube 嵌入功能后,我们的网页在移动设备上可互动的时间缩短了 10 秒。我向 YouTube 提出了一个内部错误,旨在讨论将 loading=lazy 添加到其嵌入代码中。

通过延迟加载 YouTube 视频嵌入,Chrome.com 将可交互时间缩短了 10 秒

延迟加载 Instagram 嵌入内容(初始加载时以 gzip 压缩后节省约 100 KB)

Instagram 嵌入代码提供了一个标记块和一个脚本,用于将 iframe 注入您的网页。延迟加载此 iframe,可避免必须加载嵌入所需的所有脚本。由于此类嵌入在大多数文章中通常显示在视口下方,因此延迟加载其 iframe 似乎是合理的候选对象。

延迟加载 Spotify 嵌入内容(初始加载时节省 514 KB)

<iframe src="https://open.spotify.com/embed/album/1DFixLWuPkv3KT3TnV35m3"
        loading="lazy"
        width="300"
        height="380"
        frameborder="0"
        allowtransparency="true"
        allow="encrypted-media"></iframe>

虽然前面的嵌入说明了延迟加载媒体内容 iframe 的潜在优势,但对于广告,也可能会看到这些优势。

案例研究:延迟加载 Facebook 的社交插件

Facebook 社交插件允许开发者在其网页中嵌入 Facebook 内容。我们提供了许多此类插件,例如嵌入式帖子、照片、视频、评论...最受欢迎的是 Like 插件,此按钮会显示“顶”过该页面的人数。默认情况下,将“Like”插件嵌入网页(使用 Facebook JSSDK)会拉取大约 215 KB 的资源,其中 197 KB 是 JavaScript。在很多情况下,该插件可能会显示在文章末尾或网页末尾,因此在屏幕外快速加载可能会不太理想。

Facebook“赞”按钮

得益于工程师 Stoyan Stefanov,Facebook 的所有社交插件现在都支持标准化的 iframe 延迟加载。现在,如果开发者通过插件的 data-lazy 配置选择启用延迟加载,则可以避免加载,直到用户滚动到附近为止。这样一来,嵌入内容仍可针对需要它的用户完全正常运行,同时为不会向下滚动页面的用户节省流量。我们希望这只是众多嵌入式功能的第一个工具,旨在探索标准化 iframe 延迟加载在生产环境中的实现方式。

我可以跨浏览器延迟加载 iframe 吗?是

iframe 延迟加载可作为渐进式增强功能加以应用。在 iframe 上支持 loading=lazy 的浏览器会延迟加载 iframe;而在尚不支持 loading 属性的浏览器中,系统会放心地忽略该属性。

您也可以使用 lazysizes JavaScript 库延迟加载屏幕外 iframe。如果您符合以下条件,不妨采用这种方法:

  • 要求的自定义延迟加载阈值比目前的标准化延迟加载阈值更多
  • 希望在各个浏览器中为用户提供一致的 iframe 延迟加载体验
<script src="lazysizes.min.js" async></script>

<iframe frameborder="0"
      class="lazyload"
    allowfullscreen=""
    width="600"
    height="400"
    data-src="//www.youtube.com/embed/ZfV-aYdU4uE">
</iframe>

请使用以下模式检测延迟加载,并在延迟加载不可用时提取延迟大小:

<iframe frameborder="0"
      class="lazyload"
    loading="lazy"
    allowfullscreen=""
    width="600"
    height="400"
    data-src="//www.youtube.com/embed/ZfV-aYdU4uE">
</iframe>

<script>
  if ('loading' in HTMLIFrameElement.prototype) {
    const iframes = document.querySelectorAll('iframe[loading="lazy"]');

    iframes.forEach(iframe => {
      iframe.src = iframe.dataset.src;
    });

  } else {
    // Dynamically import the LazySizes library
    const script = document.createElement('script');
    script.src =
      'https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.2.2/lazysizes.min.js';
    document.body.appendChild(script);
  }

</script>

是否存在具有 loading=lazy 的屏幕外 iframe 仍然加载的实例?

在 Chrome 中针对流量节省程序用户自动延迟加载 iframe 进行的早期实验有一个例外情况,那就是隐藏 iframe 通常用于通信或分析。这些元素不会被延迟加载,而是始终加载,以防破坏这些功能。

使用 loading 属性,选择会回到开发者手中,因此系统不会应用此类启发法,并且应始终遵循 loading 属性,具体取决于距离限制和其他浏览器选项(例如打印)。

总结

如需详细了解延迟加载,请参阅 web.dev 的图片和视频延迟加载集合

感谢 Dom Farolino、Scott Little、Houssein Djirdeh、Simon Pieters、Kayce Basques、Joe Medley 和 Stoyan Stfanov 的点评。