资讯文章 资讯 · NEWS
首屏那张图该怎么标:fetchpriority、preload 和 loading=lazy 不是一回事
2026-10-24 约 2,111 字 预计阅读 5 分钟 yiyunkj
首
打开一个目录站的分类页,用户第一眼看到的东西通常不是文字,是那张卡片缩略图或者顶部 banner。它往往就是这一页的 LCP 元素。而 LCP 又是三个 Core Web Vitals 里最容易拖后腿的一个。
于是很多站的做法是把能想到的优化手段全堆上去:preload 加一个,fetchpriority="high" 加一个,loading="lazy" 也留着。这三个属性看着都是「让图片快点」,实际解决的是不同的问题,堆在一起还会互相抵消。

图片来源:网络,版权归原作者所有,侵权请联系删除
三个属性各管一段
浏览器加载一张图,中间可以拆成几步:什么时候发现这个资源、给它排多高的优先级、要不要延迟发起请求。三个属性正好一人管一段。
| 属性 | 解决的问题 | 不管什么 |
|---|---|---|
<link rel=preload> | 提前发现。适合藏在 CSS 背景图、字体、JS 动态引入里的资源 | 不管资源之间的优先级排序 |
fetchpriority | 优先级排序。告诉浏览器这张图比同批资源更重要 | 不管发现早晚,它不产生请求 |
loading=lazy | 推迟请求。等元素接近视口再发起 | 只该用在首屏之外的图 |
web.dev 那篇 Fetch Priority 的文档把这一点说得很直接:preload 提高的是早期发现,fetchpriority 影响的是已经能被发现的资源之间怎么抢带宽。两者互补,不能互换。
为什么首屏图特别需要 fetchpriority
Chrome 对图片的默认处理是:一开始全部按 Low 优先级,等布局算完,再把视口内的提升为 High。也就是说,那张最重要的图在最开始的几十毫秒里,和页脚一个装饰图标享受的是同样待遇。
标上 fetchpriority="high" 之后,它从一开始就是 High,不必等布局那一步。Chrome 官方文档里给过一个例子:Google Flights 用这个属性把 LCP 从 2.6 秒压到 1.9 秒。
写法很简单,就加在 img 标签上:
<img src="/thumb/site-a.jpg" width="240" height="160"
fetchpriority="high" alt="站点 A 缩略图">
浏览器支持方面,这个属性最早叫 Priority Hints,标准化后改名 Fetch Priority。Chrome 与 Edge 从 102 起支持,Firefox 从 132 起,Safari 从 17.2 起。老浏览器不认识这个属性会直接忽略,不会报错,可以放心加。
三个最容易犯的错
- 给一堆图都标 high。MDN 对它的定义是「相对于同类型其他资源的优先级」,你标十张 high,等于告诉浏览器十张都最重要,结果和一张都不标差不多。一页只标一张,就是那个真正的 LCP 候选。
- 首屏图同时写了 preload 和 loading=lazy。这两个是直接冲突的:一个说赶紧下,一个说先别下。真要 lazy,就别 preload;反过来也一样。
- 把首页 banner 做成 CSS 背景图。浏览器的预加载扫描器只读 HTML,读不到 CSS 里的 url()。写在 CSS 里的背景图,必须等 CSS 下载解析完才被发现,天然晚一截。能换成
<img>就换,换不了再考虑给这张具体的图加 preload。
目录站的实际写法
导航站的页面形态很规整,可以按位置一刀切:
- 顶部 banner / 头部大图:真正的
<img>,fetchpriority="high",不加 lazy。 - 首屏卡片里的前几张缩略图:不加任何属性,让浏览器走默认逻辑即可。它们大概率不是 LCP 元素。
- 首屏之外的所有卡片缩略图:
loading="lazy",同时写死 width 和 height 防 CLS。 - 图标、logo、favicon:
fetchpriority="low"是个可选动作,让它们主动让路。
还有一种情况值得单独处理:如果你的列表页最上面几个是「编辑推荐」的宽卡片,而下面的都是小卡片,那么 LCP 元素在宽屏上可能是宽卡片,在手机上可能变成某段文字。LCP 元素会随视口变化,别只按桌面宽度调。用 Lighthouse 或 DevTools 的 Performance 面板在手机尺寸下再看一遍。
别忘了另外三段
LCP 时间可以拆成四段:TTFB、资源加载延迟、资源加载耗时、元素渲染延迟。fetchpriority 只影响第二段。有人的实测是这样的:把 CSS 背景图换成 <img> 加 fetchpriority 之后,加载延迟从 1184 毫秒掉到 37 毫秒,但 LCP 几乎没动——因为渲染延迟涨到了 1185 毫秒,卡在阻塞渲染的 CSS 上。只有把关键 CSS 也内联掉,LCP 才真正降下来。
所以顺序应该是:先看瀑布图找出瓶颈在哪一段,再决定加哪个属性。上来就堆属性,很容易出现「指标没变,但以为自己优化过了」的情况。
上线前检查四件事
- 看服务器实际吐出的 HTML,不是看 DevTools 里的最终 DOM。脚本可能事后改过属性,而预加载扫描器读的是原始 HTML。
- 确认 LCP 元素上 loading 是空值或 eager,而不是 lazy。
- 确认一页只有一个 fetchpriority="high"。
- 顺手把首屏图的宽高写死,别让它加载完之后把下面的内容顶下去。
这几个属性都是一行代码的事,真正的功夫在判断哪一张图才是那个该被优待的。判断对了,一行就够;判断错了,加十行也没用。