link rel="preload"的真实作用是让浏览器在html解析早期优先获取关键资源并存入缓存,但不执行、不渲染、不触发事件;它仅预加载,需后续通过img标签或image对象显式使用才能展示。

什么是 link rel="preload" 的真实作用
link rel="preload" 不是“自动加载图片”的开关,它只是告诉浏览器:这个资源很可能马上要用,优先 fetch,但不执行解析或渲染。图片不会自动插入 DOM,也不会触发 load 事件,更不会显示出来——它只进缓存。
- 预加载后仍需手动创建
<img>或用 JS 设置src才能真正展示 - 如果预加载的 URL 和后续
src值不完全一致(比如 query 参数顺序不同、大小写差异),浏览器不会复用缓存,等于白忙 - 只对当前导航生命周期有效;页面跳转后缓存可能被丢弃(尤其在 Safari 中较保守)
如何让预加载的图片真正“自动显示”
关键不是靠 preload 自己,而是配合 JS 监听其完成状态,并触发 DOM 插入。浏览器提供 document.addEventListener('DOMContentLoaded') 不够快,应监听 link 元素的 load 事件(注意:只有成功 fetch 才触发,失败会触发 error):
<link rel="preload" as="image" href="/hero.jpg" id="preloaded-hero"><div id="target-container"></div>
然后 JS:
const link = document.getElementById('preloaded-hero');
link.addEventListener('load', () => {
const img = new Image();
img.src = link.href; // 复用已缓存资源
img.onload = () => document.getElementById('target-container').appendChild(img);
});
link.addEventListener('error', () => console.warn('Preload failed for', link.href));
- 必须用
new Image()或<img>标签触发解码和渲染,不能仅靠link - 不要直接改已有
<img>的src—— 这会重新触发网络请求,绕过预加载缓存(除非 URL 完全相同且 CORS 等配置一致) -
as="image"是必须的,否则 Chrome 会忽略预加载(报 warning:“A preload for ‘xxx’ is found, but a resource of type ‘image’ is expected.”)
哪些情况会让 preload 彻底失效
- HTTP/2 Server Push 已废弃,别指望它配合
preload
- 在
外写 link(比如塞在 底部),部分浏览器延迟解析,失去预加载意义
- 跨域图片未加
crossorigin 属性:link 能预加载,但后续 Image() 实例无法复用缓存(CORS mismatch)
- 使用
srcset 或 sizes 的响应式图片时,preload 只能指定一个固定 URL,无法动态匹配设备 DPR 或视口宽度
替代方案比 preload 更简单可靠
preload 外写 link(比如塞在 底部),部分浏览器延迟解析,失去预加载意义 crossorigin 属性:link 能预加载,但后续 Image() 实例无法复用缓存(CORS mismatch) srcset 或 sizes 的响应式图片时,preload 只能指定一个固定 URL,无法动态匹配设备 DPR 或视口宽度 preload 更简单可靠如果目标只是“图片尽快出现”,多数场景下直接用原生 loading="eager" + 合理的 decoding="async" 更省事:
@@##@@
-
loading="eager"显式关闭懒加载(尤其在 Lighthouse 提示“Offscreen images”时) -
decoding="async"避免图片解码阻塞主线程,实测对长页面首屏渲染有可感提升 - 不依赖 JS,无缓存复用风险,兼容性好(Chrome 78+、Firefox 69+、Safari 15.4+)
预加载真正有价值的场景其实很窄:比如 Web Worker 中需要图像数据、或动画帧序列需提前解码。普通页面首图,别为 preload 多写三行 JS。

前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











