预加载响应式图片

您可以预加载响应式图片,这可以通过帮助浏览器在渲染 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. 在 “节流” 下拉列表中,选择 “快速 3G”。
  5. 取消选中 “停用缓存” 复选框。
  6. 重新加载页面。
Chrome DevTools Network panel showing a waterfall with a JPEG resource only starting to download after some JavaScript.
如果不进行预加载,则图片会在浏览器完成脚本运行后开始加载。对于第一张图片,这种延迟是不必要的。

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

Chrome DevTools Network panel showing a waterfall with a JPEG resource downloading in parallel to some JavaScript.
预加载第一张图片可以让它与脚本同时开始加载。

要查看预加载带来的差异,请按照第一个示例中的步骤检查相同的动态加载图片库,但这次第一张图片已预加载

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

如果您有针对不同屏幕密度的不同背景图片,则可以在 CSS 中使用 image-set 语法指定它们。然后,浏览器可以根据屏幕的 DPR 选择要显示的图片。

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

CSS 背景图片的问题在于,浏览器只有在下载并处理完页面 <head> 中的所有 CSS 后才会发现它们。

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

Chrome DevTools Network panel showing a waterfall with a JPEG resource only starting to download after some CSS.
在此示例中,图片下载直到 CSS 完全下载后才开始,从而导致图片显示出现不必要的延迟。

响应式图片预加载可让您更快地加载这些图片。

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

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

您可以在响应式背景预加载演示中检查之前的示例在预加载响应式背景图片时的行为方式。

Chrome DevTools Network panel showing a waterfall with a JPEG resource downloading in parrallel to some CSS.
在这里,图片和 CSS 同时开始下载,从而加快了图片加载速度。

预加载响应式图片的实际效果

从理论上讲,预加载响应式图片可以加快它们的速度,但实际上会怎样呢?

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

对于不预加载预加载图片,产生了以下结果

WebPageTest filmstrip comparison showing preloaded images are displayed about 1.5 seconds faster.
预加载后,图片到达速度显著加快,极大地改善了用户体验。

预加载和 <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> 元素中拾取图片。无论如何,这都是最佳实践,尤其是在使用 Fetch Priority 来帮助确定适当图片的优先级时。

对最大内容渲染 (LCP) 的影响

由于图片可能是最大内容渲染 (LCP) 候选对象,因此预加载它们可以改善您网站的 LCP。

无论您预加载的图片是否是响应式的,当图片资源在初始标记负载中不可发现时,预加载效果最佳。与从服务器发送完整标记的网站相比,在客户端渲染标记的网站上,您还将获得更多的 LCP 改进。