图片预加载必须用置于中且as="image"、href为静态路径;fetchpriority="high"仅对chromium 112+的有效且需src直出、loading="eager",不可与lazy共存;二者不可混用,fallback和跨浏览器兼容性需额外处理。

图片预加载和资源优先级是两件事,不能混用;真要提前加载,必须用 <link rel="preload">;真要调高网络请求优先级,得看浏览器是否支持 fetchpriority,且仅对 <img> 有效。
用 <link rel="preload"> 声明预加载,不是靠 img 标签属性
预加载(preload)是告诉浏览器“这个资源马上要用”,它发生在 HTML 解析早期,不依赖 DOM 插入或视口位置。你不能靠给 <img> 加 loading="eager" 或 fetchpriority="high" 来实现预加载——这些只影响该 <img> 自身的加载时机和调度优先级,不会让它比其他资源更早发起请求。
正确做法是把 <link rel="preload"> 放在 中:
-
as="image"必须写,漏掉或写错(如as="img")会导致浏览器按普通 fetch 处理,Priority 直接降为Low -
href必须是静态路径,不能含 JS 变量、模板语法或相对路径误算(比如 HTML 在/user/profile.html,却写href="./images/hero.jpg") -
fetchpriority="high"对<link>无效,别加;它只对<img>和<iframe></iframe>生效 - WebP 图片需 fallback:
<link>只能预加载一种格式,若需响应式(srcset),得靠 JS 或<picture></picture>配合,但预加载本身不支持sizes或srcset
fetchpriority="high" 只在 Chromium 112+ 对 <img> 有效,且条件苛刻
这个属性不是“强制插队”,而是向 Chromium 提示“这张图比默认更关键”。但它生效有硬门槛:
- 必须是
<img src="...">,且src在 HTML 源码中直出,不能是空、data-src或 JS 后续赋值 - 不能和
loading="lazy"共存,否则 Chrome 强制降级为Low - 必须配
loading="eager"(首屏图默认就是 eager,但显式写上更稳) - Safari 17.2+ 支持,Firefox 完全忽略——它不会报错,也不会降级提示,只是静默失效
- 已用
<link rel="preload">预加载的图,再加fetchpriority="high"无意义,因为 preload 已锁定Highest
别用 loading="lazy" 当预加载,它干的是相反的事
loading="lazy" 是推迟加载,不是提前加载。哪怕你把它加在首屏 banner 上,Chrome 仍可能等滚动前 500px 才发请求——这和预加载目标完全冲突。
常见错误包括:
- 给首屏图加
loading="lazy"还配fetchpriority="high":逻辑自相矛盾,Chrome 会忽略 high - 以为
loading="eager"就等于预加载:它只是让图片在 HTML 解析时触发请求,但没preload那么早,也不保证更高优先级 - 用 CSS
display: none或 JS 动态插入来“伪预加载”:图片未进入渲染树,浏览器可能跳过加载,或延迟到真正显示时才开始
运行时预加载只能用 new Image(),但要注意并发和事件顺序
当你要根据用户行为(如 hover)、设备像素比(window.devicePixelRatio)或模块加载状态来决定预加载哪些图时,new Image() 是唯一可控方式。
关键点:
- 必须先绑定
onload和onerror,再赋值src;否则缓存命中时事件同步触发,回调会被跳过 - 检查
img.complete:若为true,说明已缓存,需立刻执行成功逻辑 - 避免密集循环
new Image():浏览器并发请求数通常只有 6~8 个,建议加节流或 Promise 队列(如每次最多并发 4 个) - 不要长期持有
Image实例引用(如挂全局变量),否则可能内存泄漏;加载完可设img.src = ''清理
真正容易被忽略的是:预加载和优先级都依赖浏览器实现细节,<link rel="preload"> 的 as 值写错、crossorigin 缺失、路径不一致,都会导致静默失效;而 fetchpriority 在非 Chromium 浏览器里根本不存在——别把它当成跨浏览器通用方案。











