图像构成了大多数网站的重要组成部分。它们通常也是页面上最先出现的最大元素,因此成为最大内容绘制(LCP)元素——这是Google核心网页指标中的一个重要指标。当图像加载缓慢时,会使LCP时间变长。这会损害您的核心网页指标得分和整体用户体验。让我们来看看如何让网页上的图像加载更快。
引言
当您向网站添加图像时,幕后发生的事情可能比您想象的要多。从基础开始,将图像添加到页面的最简单方法是使用HTML <img>元素:
您还可以使用CSS背景图像添加图像,这些图像仍然是LCP的候选元素:
一些开发人员改用JavaScript加载图像。这会延迟浏览器开始下载图像的时间,因为JavaScript必须先运行。
事实上,当您有JavaScript文件请求其他JavaScript文件,然后这些文件再请求图像时,JavaScript方法可能会更糟。这被称为请求链,本文后面会解释。为了理解图像加载,我们使用网络请求瀑布图。这些图表显示了页面上所有网络请求的时间安排。像DebugBear这样的现代性能测试工具可以为您生成这些瀑布图,甚至可以识别页面上的LCP元素,如前面屏幕截图中显示的LCP徽章所示。
网页上的图像加载过程
图像在网页上加载时会发生什么?理解这个过程有助于解释为什么某些优化技术有效。当浏览器在加载的HTML中找到图像时,浏览器会:
- 发出网络请求以下载图像:这就像下载任何其他资源(如CSS或JavaScript)一样。
- 为该请求分配优先级(稍后详述):这决定了图像与其他资源相比何时下载。
- 在图像数据到达后对其进行解码:这是将原始图像数据转换为可在屏幕上显示的像素的过程。
- 在页面上渲染图像:浏览器根据页面布局定位并显示图像。
与某些资源(如CSS)不同,图像下载不会阻止页面的其余部分加载。
图像加载如何影响LCP
LCP由多个子部分组成。每个子部分都会对整体LCP得分产生影响。子部分越慢,LCP得分就越慢。以下屏幕截图显示了DebugBear真实用户监控仪表板的一部分,该仪表板已识别出真实页面视图的LCP子部分。
了解每个子部分是理解如何提高LCP得分的关键,因此让我们详细看看这些子部分。
首字节时间(TTFB)
这是服务器开始响应主HTML文档所需的时间。在以下情况下,这可能会明显变慢:
- 服务器和用户之间存在较大的地理距离。
- 存在错误的缓存头或网站使用未优化的缓存策略。
此屏幕截图显示了特定请求的网络计时信息。有趣的是,TTFB花费的时间比下载本身还要长!实际上,其他高亮显示的资源也具有比下载本身更长的TTFB!
资源加载延迟
这是浏览器发现图像并请求图像所需的时间。在以下情况下,这可能会变慢:
- 图像位于请求链中,资源必须加载后才能开始下载图像。
- 图像被延迟加载,这将延迟下载直到图像接近或进入视口。
- 使用JavaScript将图像插入DOM——即使该JavaScript是内联在HTML中的。这是因为浏览器的预解析器必须先解析并执行JavaScript,然后才能发现图像。
资源下载时间
这是图像下载所需的时间,可能就是我们大多数人想到"加载缓慢的图像"时所想到的。在以下情况下,这可能会变慢:
- 图像很大且未优化。
- 离屏图像或其他非关键资源同时下载,导致网络竞争。
以下屏幕截图显示了一组JavaScript文件,其中下载时间远远超过TTFB。DebugBear内的请求瀑布图指示实际内容下载发生在水平蓝色条内的位置。较深的蓝色阴影表示内容下载正在进行中。
资源渲染延迟
这是浏览器解码图像数据并在页面上渲染所需的时间。在以下情况下,这可能会变慢:
- 图像使用高度压缩的格式,需要更多时间解码。
- 渲染阻塞资源仍在下载,这可能会延迟图像渲染。
- 主线程被阻塞,无法将图像渲染到页面。
- 图像使用
<link rel="preload">元素加载,但使用图像的页面元素尚未创建。
现代图像格式和响应式图像
现代图像格式有助于在保持质量的同时减小图像文件大小。使用现代图像格式可以对LCP的资源下载时间子部分产生积极影响。推荐的现代格式有:
- WebP:广泛支持并提供良好的压缩。
- AVIF:较新的格式,具有更好的压缩。
您可以使用Squoosh网络应用程序将图像转换为这些格式。以下是如何提供不同格式供浏览器选择的方法:
以下屏幕截图显示了请求瀑布图中的LCP资源。虽然TTFB很重要,但与图像整整3秒的内容下载时间相比,它不算什么。考虑到实验室测试是使用节流连接运行的,并且考虑到此图像大小为1MB,这就开始说得通了。
将1MB图像放入Squoosh,并将其转换为80%质量的AVIF,可节省95%,得到46KB的文件。这对内容下载时间有积极影响。
在使用现代图像格式时,考虑浏览器支持很重要。您还可以考虑配置服务器以根据浏览器的Accept头提供正确的格式。响应式图像可帮助您为每个屏幕提供合适的大小。这节省了带宽和处理时间。
该示例使用带有srcset和sizes属性的<img>元素(而不是<picture>元素),为不同的视口宽度提供小、中、大图像候选:
- 小屏幕(宽度小于500px)上的小图像。
- 中等屏幕(500px至900px宽)上的中等图像。
- 大屏幕(超过900px宽)上的大图像。
这样,您就不会在小屏幕上浪费大图像的带宽。作为一个实际例子,这个网站在移动视口上下载2.26MB的LCP图像需要很长时间。
经过进一步调查,发现该图像的尺寸为1920×1080。在优化此图像以使用现代图像格式后,开发此网站的开发人员可以生成适合不同视口尺寸的图像的不同版本。
请求链如何影响LCP
有时,由于请求链,图像出现的时间比应有的要晚。当一个或多个资源(主HTML之外)必须加载后才能开始另一个请求时,就会发生请求链:
例如,如果您的JavaScript加载图像,在高层面上,浏览器必须:
- 下载HTML。
- 下载JavaScript:根据JavaScript的加载方式,这也可能阻塞页面渲染。
- 执行JavaScript:JavaScript存在解析和执行成本,在低端设备上通常会加剧。
- 开始下载图像。
这创建了一个延迟图像加载的链。您可以通过以下方式帮助打破这个链:
- 在HTML中直接使用常规的
<img>元素。 - 使用
<link rel="preload">元素更早地下载图像。
预加载提示告诉浏览器尽快下载资源,并放置在HTML的头部:
在此示例中,DebugBear识别出LCP图像是链的一部分,并提供了一个实验来测试修复。
该实验自动将LCP图像的请求链(包括LCP图像本身)预加载到主HTML文档中。运行实验后,可以查看前后比较:
前面的屏幕截图显示:
- LCP请求链中的CSS资源现在被预加载。
- LCP图像本身现在被预加载。
下面的前后LCP得分确认了改进。
在关键图像上使用fetchpriority=high
浏览器为网络请求分配不同的优先级。这决定了资源在竞争带宽时的下载顺序。您可以使用fetchpriority属性提高LCP图像的优先级:
这告诉浏览器相对于其他资源优先下载图像。您还可以将fetchpriority与rel=“preload"属性一起使用:
当LCP是背景图像,并且否则会在页面加载后期(在CSS被下载和解析之后)被发现时,这可能特别有用。此示例显示了Discord上的改进,其中LCP图像的整个请求链被预加载,并标记为fetchpriority=“high”,这有助于改善LCP时间。得分差异:
请求瀑布差异:
前面的屏幕截图显示了Discord的LCP图像如何更早下载。FP=HIGH徽章确认指定了高fetchpriority,因此LCP资源现在保持高优先级,而之前LCP图像开始时是低优先级。
在DebugBear请求瀑布视图中,对于优先级已更改的资源,会出现细红色垂直线。如果浏览器较晚发现需要更改优先级(例如从低优先级到高优先级),您可以通过在适用的资源上应用fetchpriority=“high"来协助浏览器。
延迟加载图像
并非每个图像都需要立即加载。视口下方的图像可以稍后加载,为更重要的资源节省带宽。以下是延迟加载图像的方法:
考虑一个包含10个图像的网页,其中只有第一个图像(LCP元素)在初始视口中可见。在这种情况下,延迟加载其余9个图像有助于改善第一个图像的加载。当您延迟加载首屏以下的图像时,您可以:
- 减少带宽竞争。当您释放带宽时,LCP图像有时可以加载得更快。
- 让浏览器首先专注于加载重要资源。
- 如果用户从不向下滚动,则节省用户的数据。
此示例显示了同一网站的两个不同瀑布图,这些示例试图显示资源竞争对LCP图像的影响。瀑布图1显示了一个大的LCP图像,下载需要很长时间,并且似乎与页面上的其他图像资源竞争带宽。
瀑布图2显示了相同的大LCP图像,但这次使用了DebugBear的请求阻止来阻止不是主要LCP图像的其他图像资源。这是作为测试完成的,以显示带宽竞争如何影响资源下载时间。
如果您仔细观察,RB_8220-Large-1.png图像的实际数据下载(深蓝色块)在第二个瀑布图中更加集中。要理解这对时间的显著影响,请查看瀑布比较视图。对于LCP图像不必竞争带宽的测试运行,图像在不到一半的时间内下载完成!
总结
图像是大多数网站的重要组成部分,并且可能对您的LCP得分产生重大影响。以下是如何为LCP优化图像的总结:
- 使用现代图像格式,如WebP和AVIF。
- 提供响应式图像以节省带宽。
- 使用预加载和fetchpriority来优先处理关键图像。
- 延迟加载首屏以下的图像以减少网络竞争。
- 避免延迟图像加载的请求链。
本文由DebugBear赞助。DebugBear帮助团队优化网页性能和核心网页指标,提供速度洞察和持续监控,以实现更快的网站。