link[rel=preload]可通过绑定load/error事件监听加载完成,需先创建元素、再绑定事件、最后插入dom;而link[rel=prefetch]无事件可监听,仅能通过devtools验证。

link[rel=preload] 加载完成怎么监听
用 link 标签做资源预加载(rel="preload")时,它本身不触发标准事件,但可以监听其 load 和 error 事件——前提是该 link 已插入 DOM 且浏览器支持。
常见错误现象:link.onload = handler 不执行、控制台无报错但回调没进;或在 document.head.appendChild(link) 前就绑定事件,导致监听丢失。
正确做法:
- 必须先创建
link元素,再绑定load/error,最后插入 DOM(顺序不能颠倒) -
rel="preload"的link只对as指定类型有效(如script、style、font、image),对as="fetch"或未声明as的请求无效 - Chrome/Firefox 支持
load,Safari 对as="font"的load事件支持不稳定,建议加兜底超时(比如 5s 后强制 resolve)
示例:
const link = document.createElement('link');
link.rel = 'preload';
link.as = 'script';
link.href = '/assets/main.abc123.js';
link.addEventListener('load', () => console.log('preload script loaded'));
link.addEventListener('error', () => console.error('preload failed'));
document.head.appendChild(link); // 必须放最后
link[rel=prefetch] 能监听成功吗
不能。浏览器不提供 prefetch 的 JS 可读事件接口,load 和 error 都不会触发。
原因在于:prefetch 是后台静默预取,不阻塞渲染、不参与主资源调度,也不暴露加载状态给脚本层。
验证是否生效只能靠外部手段:
- 打开 DevTools → Network 面板,筛选
Initiator: prefetch,看请求是否发出、是否返回200 (from memory cache) - 不能依赖
document.querySelector('link[rel=prefetch]').sheet—— 它是 null,prefetch 不解析 CSSOM - 别试图用
fetch()模拟 prefetch 行为,两者缓存策略、优先级、CORS 处理完全不同
动态插入的 link 标签,DOMContentLoaded 后还能监听吗
能,但必须确保监听逻辑在 link 插入后立即绑定,而不是等某个全局事件(比如 window.onload)后再补绑。
容易踩的坑:
- 把
link插入 DOM 后,过几帧才去绑load,此时加载可能已完成,事件已错过(尤其小资源) - 用
document.querySelector('link[rel=preload]')找元素再绑事件,但该link是异步插入的,查询时机不对就会返回null - 多个
link共享同一个变量名(比如都叫link),后插入的覆盖前一个的事件监听器
推荐写法:封装成函数,创建即绑定即插入:
function preloadResource(href, as) {
const link = document.createElement('link');
link.rel = 'preload';
link.as = as;
link.href = href;
link.addEventListener('load', () => console.log(`${href} preloaded`));
link.addEventListener('error', () => console.warn(`${href} preload failed`));
document.head.appendChild(link);
}
preloadResource('/fonts/inter.woff2', 'font');
preloadResource('/styles/main.css', 'style');
为什么 getComputedStyle() 在 link 加载完后仍拿不到样式
因为 link[rel=stylesheet] 的加载完成(load 事件) ≠ CSSOM 就绪。浏览器解析 CSS 并构建 CSSOM 是异步过程,可能滞后几十毫秒。
典型表现:监听了 link.onload,立刻调用 getComputedStyle(el),结果返回空值或初始值。
解决思路:
- 若需精确布局计算(如
getBoundingClientRect()),应等待requestAnimationFrame下一帧,或监听document.fonts.load()(针对字体) - 不要依赖
link.onload判断样式是否可用,它只表示文件下载完成,不表示 CSSOM 已合并进渲染树 - 对关键样式,更稳妥的做法是用
rel="stylesheet"同步加载,或用media="print"+ JS 动态改media触发重载(但会闪)
真正可控的样式就绪判断,往往得组合多个信号:link load + RAF + check computed style loop(最多 3 次)。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











