link rel="preload" 是唯一原生支持且 Lighthouse 可验证的图片预加载方式;new Image() 是唯一可控的运行时条件预加载手段;其他如 loading="lazy"、display: none 或 background-image 均不构成真正预加载。

link rel="preload" 是唯一能被浏览器原生识别、语义明确且 Lighthouse 可验证的图片预加载方式;new Image() 是唯一可控的运行时条件预加载手段;其他如 loading="lazy"、display: none 或 background-image 均不构成真正预加载。
用 link rel="preload" 预加载首屏关键图
它只下载不渲染,不占布局,专为「确定马上要用」的图设计(比如 banner、logo、登录页主视觉)。必须写在 <head> 里,且最好放在 <meta charset> 和 <title> 之后、任何 <link rel="stylesheet"> 之前,否则可能被忽略。
-
as="image"缺一不可——缺了浏览器当普通 fetch 处理,失去图片专用缓存和解码策略 - 路径必须静态准确:相对路径基于 HTML 文件位置解析,
./images/hero.jpg在/user/profile.html下会 404,应改用/images/hero.jpg或绝对 URL -
fetchpriority="high"在 Chrome 109+ 有效,抬高请求优先级;旧版忽略无副作用 - 禁止在
href写模板变量,如"/assets/${name}.webp"会被当字面量请求,大概率 404
用 new Image() 实现运行时条件预加载
适合根据用户行为、设备特性或状态决定是否加载的场景,比如 hover 后预载下一页缩略图、按 window.devicePixelRatio 加载 @2x 版本、轮播图只预加载当前 + 相邻 1–2 张。
- 顺序不能错:先绑定
onload/onerror,再赋值src;否则缓存命中时事件同步触发,回调直接跳过 - 必须检查
img.complete:为true说明已缓存,需立刻执行成功逻辑 - 避免密集
new Image():浏览器并发请求数通常仅 6~8 个,建议加队列或限制并发(例如每次最多 4 个) - 不要用
new Image().src = url简写——无法捕获失败,也无法链式等待
别把 loading="lazy" 当预加载用
这是最常踩的坑:loading="lazy" 是推迟加载,不是提前加载。哪怕你给首屏 <img> 显式加上它,Chrome 仍可能等到滚动前 500px 才发请求——完全违背预加载目标。
立即学习“前端免费学习笔记(深入)”;
-
loading="eager"只是默认行为,“不懒”不等于“提前” -
decoding="async"只影响解码时机,和下载无关 - 如果发现某张图“怎么还没出来”,先检查是不是误用了
loading="lazy",而不是急着加预加载 -
display: none或background-image伪预加载无法监听完成状态,且不保证缓存策略一致
WebP 预加载与 fallback 兜底
预加载 WebP 图片时,必须考虑不支持 WebP 的浏览器(如旧版 Safari),不能只 preload 一种格式。
- 不要只写
<link rel="preload" as="image" href="/assets/hero.webp">,否则 fallback 逻辑失效 - 推荐方案:用
<picture>+<source type="image/webp">控制显示,同时对 WebP 和 fallback 格式分别preload - 注意资源优先级:若带宽紧张,优先
preloadfallback 格式(如 JPG),再让 WebP 作为高优可选资源 - 确保预加载 URL 和最终
<img src>或<source srcset>使用**完全一致的 URL**(含参数),否则缓存不命中
真正难的不是写对一行 link 或一个 new Image(),而是判断哪张图该预加载、何时触发、要不要 fallback、以及如何不让它挤占首屏关键资源的带宽——这些决策点,浏览器不会替你做。



















