优先级与解码:fetchpriority、preload 与 decoding
前几页处理的是「下载哪一张」和「何时开始下载」。对首屏主图,还有两个时间段会推迟它出现在屏幕上:请求发出后在网络队列里排多久,字节到齐后解码要多久。这两段分别由优先级与解码时机决定。
1 · fetchpriority
浏览器给每个请求分配一个优先级,带宽紧张时高优先级先走。据 web.dev 对 Chrome 的描述,图片默认从 Low 起步,布局完成后位于视口内的图片被提升为 High;Chrome 117 起前 5 张大图以 Medium 起步。问题在于「布局完成后」:这之前主图与屏外图片同为 Low,排在样式表与同步脚本之后(核对于 2026-09)。
fetchpriority 让作者直接给出提示,取值为 high、low 与缺省的 auto。首屏主图写 fetchpriority="high",从请求发出起就是 High,不必等布局;轮播里暂不可见的后几张写 low,把带宽让给当前那一张。Chrome 101(2022-04)、Safari
17.2(2023-12)、Firefox 132(2024-10)先后支持(兼容性据 MDN BCD,核对于 2026-09)。
这个属性是相对的提示。所有图片都写 high 等于都没写;它也不改变选哪张候选、不绕过懒加载,loading="lazy" 配 fetchpriority="high" 仍然要等到进入提前量才请求。本页没有实测各档优先级:DevTools 协议给出的请求记录里没有优先级字段,本地 dev server 的响应在
30ms 内全部返回,排队差异无从观察。
2 · preload 与响应式候选
preload scanner 只能发现写在 HTML 里的 <img>。CSS background-image 里的主图、由框架在客户端渲染出的 <img>,都要等样式或脚本执行后才被发现。<link rel="preload" as="image"> 把请求提前到
<head> 解析的时刻。
对响应式图片,preload 不能只写一个 href,否则会预加载一张与 <img> 最终选择不同的图,下载两次。imagesrcset 与 imagesizes 两个属性照搬 <img> 的 srcset 与 sizes,由同一套算法选出同一张候选:
<link rel="preload" as="image" fetchpriority="high"
imagesrcset="hero-640.jpg 640w, hero-1280.jpg 1280w, hero-1920.jpg 1920w"
imagesizes="100vw">
两处的候选与 sizes 必须逐字一致,任何一处改了而另一处没改,preload 就变成一次额外下载。imagesizes 不支持 auto:preload 发生在布局之前,没有布局宽度可取。preload 也不认识 <picture> 的 type 与 media 协商,art direction
或格式切换的主图只能配合 <link> 自己的 media 与 type 属性逐条写。
3 · 解码是另一段时间
图片的 load 事件在字节全部到齐时触发,此时位图不一定已经解码。解码在需要绘制时才进行,而绘制在主线程的渲染步骤里。
src 到 load 与 load 到 decode() 兑现的耗时。可切换三档尺寸,读数取决于本机 CPU。
作者的机器上(macOS,Chrome 154),一张 4000 × 3000 的噪点 JPEG 从 blob URL 加载,load 在 6ms 触发,随后的 img.decode() 还要 87ms 才兑现;1000 × 750 的同类图是 1ms 与 6ms。在 load 回调里把缩略图换成大图,这 87ms
就会落进下一帧,页面在切换那一刻卡顿,或者短暂显示空白(核对于 2026-09)。
img.decode() 返回一个 Promise,在位图解码完成、可以立即绘制时兑现,解码失败则拒绝。先 await img.decode() 再把图片插入文档或替换 src,切换就发生在一帧之内:
const full = new Image();
full.src = largeUrl;
await full.decode(); // 解码在后台完成
thumb.replaceWith(full); // 插入时已可直接绘制
decoding 属性是同一件事的声明式版本,取值 sync、async 与缺省的 auto。async 允许浏览器把这张图的解码与其余内容的绘制分开,先画出文字、图片稍后出现;sync
要求它与其余内容在同一帧出现。规范把它定为提示,浏览器可以忽略。实践中,首屏主图不必写(或写 sync,避免主图晚于文字一帧出现),大量缩略图的列表可以写 async,避免一次滚动里几十张图的解码阻塞同一帧。
4 · 图片元素的状态读取
几个只读属性描述图片的当前状态,调试选择与加载时常用:
| 属性 | 含义 |
|---|---|
currentSrc |
当前选中候选的绝对 URL;未选定时为空串 |
complete |
没有待处理的请求,且图片已完全可用或已确定损坏 |
naturalWidth / naturalHeight |
经密度校正的天然尺寸(见 x 描述符与像素密度 §2);未加载时为 0 |
width / height(IDL) |
已渲染时为渲染尺寸,未渲染时为属性值 |
complete 为真不代表加载成功:损坏的图片 complete 同样为真,需要再看 naturalWidth 是否大于 0。