预加载自适应图片

您可以预加载自适应图片,这样可以帮助浏览器在渲染 img 标记之前从 srcset 中识别正确的图片,从而显著加快图片加载速度。

自适应图片概览

浏览器支持

  • Chrome:73。
  • Edge:79。
  • Firefox:78.
  • Safari:17.2。

假设您在宽度为 300 像素的屏幕上浏览网页,而网页请求的图片宽度为 1500 像素。由于您的屏幕无法使用所有这些额外的分辨率,因此该网页浪费了大量移动流量。理想情况下,浏览器会提取比屏幕尺寸略宽的图片版本,例如 325 像素。这样可确保高分辨率图片不会浪费数据,并加快图片加载速度。

自适应图片可让浏览器为不同设备提取不同的图片资源。如果您不使用图片 CDN,请为每张图片保存多个尺寸,并在 srcset 属性中指定这些尺寸。w 值会告知浏览器每个版本的宽度,以便浏览器为任何设备选择适当的版本:

<img src="small.jpg" srcset="small.jpg 500w, medium.jpg 1000w, large.jpg 1500w" alt="…">

预加载概览

浏览器支持

  • Chrome:50.
  • Edge:≤79。
  • Firefox:85.
  • Safari:11.1。

来源

您可以通过预加载告知浏览器您想要尽快加载的关键资源,在浏览器在 HTML 中发现这些资源之前。这对于不易发现的资源特别有用,例如样式表中包含的字体、背景图片或从脚本加载的资源。

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

imagesrcsetimagesizes

<link> 元素使用 imagesrcsetimagesizes 属性预加载自适应图片。将它们与 <link rel="preload"> 搭配使用,并使用 <img> 元素中的 srcsetsizes 语法。

例如,如果您想预加载使用以下代码指定的自适应图片:

 <img src="wolf.jpg" srcset="wolf_400px.jpg 400w, wolf_800px.jpg 800w, wolf_1600px.jpg 1600w" sizes="50vw" alt="A rad wolf">

为此,您可以将以下代码添加到 HTML 的 <head> 中:

<link rel="preload" as="image" href="wolf.jpg" imagesrcset="wolf_400px.jpg 400w, wolf_800px.jpg 800w, wolf_1600px.jpg 1600w" imagesizes="50vw">

这会使用 srcsetsizes 使用的相同资源选择逻辑发起请求。

使用场景

以下是预加载响应式图片的一些用例。

预加载动态注入的自适应图片

假设您要将主推图片作为幻灯片的一部分动态加载,并且您知道哪张图片将首先显示。在这种情况下,您可能希望尽快显示该图片,而不是等待幻灯片脚本加载该图片。

您可以在包含动态加载的图片库的网站上检查此问题:

  1. 在新标签页中打开此幻灯片演示
  2. Control+Shift+J(在 Mac 上,按 Command+Option+J)打开 DevTools。
  3. 点击网络标签页。
  4. 节流下拉列表中,选择 Fast 3G
  5. 停用停用缓存复选框。
  6. 重新加载页面。
Chrome DevTools Network 面板,显示了在 JavaScript 执行完毕后才开始下载 JPEG 资源的瀑布图。
如果不预加载,图片会在浏览器运行完脚本后开始加载。对于第一张图片,则无需延迟。

在此处使用 preload 可让图片提前开始加载,以便在浏览器需要显示图片时可以立即显示。

Chrome DevTools 的 Network 面板,显示了与一些 JavaScript 并行下载 JPEG 资源的瀑布图。
预加载第一张图片可让其与脚本同时开始加载。

如需了解预加载带来的差异,请按照第一个示例中的步骤检查同一动态加载的图库,但预加载第一张图片

使用 image-set 预加载背景图片

如果您为不同的屏幕密度提供了不同的背景图片,则可以在 CSS 中使用 image-set 语法指定这些图片。然后,浏览器可以根据屏幕的 DPR 选择要显示的哪个版本。

background-image: image-set( "cat.png" 1x, "cat-2x.png" 2x);

CSS 背景图片存在的问题是,浏览器只有在下载并处理网页 <head> 中的所有 CSS 后,才会发现这些图片。

您可以在包含响应式背景图片的示例网站上检查此问题。

Chrome DevTools 的 Network 面板,显示了一个瀑布图,其中 JPEG 资源仅在下载一些 CSS 后才开始下载。
在此示例中,系统会等到 CSS 完全下载后才开始下载图片,导致图片显示出现不必要的延迟。

借助自适应图片预加载功能,您可以更快地加载这些图片。

<link rel="preload" as="image" imagesrcset="cat.png 1x, cat-2x.png 2x">

通过省略 href 属性,您可以确保那些不支持 <link> 元素上的 imagesrcset,但支持 CSS 中的 image-set 的浏览器下载正确的来源。不过,在这种情况下,它们无法从预加载中受益。

您可以在响应式背景预加载演示版中检查上例在使用预加载的响应式背景图片时的行为。

Chrome DevTools 的 Network 面板,显示了在某些 CSS 并行下载时 JPEG 资源的瀑布图。
在此示例中,图片和 CSS 会同时开始下载,从而加快图片加载速度。

预加载自适应图片的实用效果

从理论上讲,预加载自适应图片可以加快其加载速度,但在实践中又会有什么效果呢?

为了回答这个问题,我创建了演示版 PWA 商店的两个副本:一个不预加载图片,另一个预加载部分图片。由于该网站使用 JavaScript 延迟加载图片,因此预加载初始视口中显示的图片可能会有所帮助。

这产生了以下结果:不预加载图片预加载

WebPageTest 影片条比较,显示预加载的图片的显示速度提高了约 1.5 秒。
预加载图片后,图片的传送速度会显著加快,从而极大地改善用户体验。

预加载和 <picture>

Web 性能工作组正在讨论为 srcsetsizes 添加等效的预加载,但不为处理“艺术指导”用例的 <picture> 元素添加等效的预加载。

预加载 <picture> 仍有许多技术问题需要解决,但与此同时,我们提供了一些权宜解决方法:

<picture>
    <source srcset="small_cat.jpg" media="(max-width: 400px)">
    <source srcset="medium_cat.jpg" media="(max-width: 800px)">
    <img src="large_cat.jpg">
</picture>

<picture> 元素的图片来源选择逻辑会按顺序遍历 <source> 元素的 media 属性,找到第一个匹配的属性,然后使用附加的资源。

由于响应式预加载不存在“顺序”或“首次匹配”的概念,因此您需要将断点转换为如下内容:

<link rel="preload" href="small_cat.jpg" as="image" media="(max-width: 400px)">
<link rel="preload" href="medium_cat.jpg" as="image" media="(min-width: 400.1px) and (max-width: 800px)">
<link rel="preload" href="large_cat.jpg" as="image" media="(min-width: 800.1px)">

预加载和 type

<picture> 元素还支持按第一个 type 进行匹配,以便您提供不同的图片格式,以便浏览器可以选择其支持的第一个图片格式。预加载不支持此用例。

对于使用类型匹配的网站,我们建议避免预加载,而是让预加载扫描器<picture><source> 元素中提取图片。无论如何,这都是最佳实践,尤其是在使用提取优先级来帮助确定适当图片的优先级时。

对 Largest Contentful Paint (LCP) 的影响

由于图片可能是 Largest Contentful Paint (LCP) 候选项,因此预加载图片可以改善您网站的 LCP。

无论您预加载的图片是否响应迅速,在初始标记载荷中无法发现图片资源时,预加载效果最好。此外,与从服务器发送完整标记的网站相比,在客户端渲染标记的网站上,LCP 的改进幅度也会更大。