前端监控中如何准确采集 CSS 加载失败的数据?

W″焕焕 阅读 6

我在做前端异常监控,想采集 CSS 文件加载失败的情况,但发现 onerror 事件在 link 标签上不生效。试过动态创建 link 并监听 error,但有些浏览器根本不触发,导致监控漏报。

比如这段样式引入:

/* main.css */
body {
  background-color: #f0f0f0;
  font-family: Arial, sans-serif;
}

实际项目中这个文件如果 404 了,我该怎么可靠地捕获到错误并上报?有没有通用的方案?

我来解答 赞 2 收藏
二维码
手机扫码查看
1 条解答
W″梦玲
link 标签的 onerror 确实很坑,不同浏览器行为不一致,有些压根不触发。这个问题我之前踩过坑,给你几个可靠的方案。

最稳的方案是用 PerformanceObserver 监控资源加载,配合 document.styleSheets 做兜底校验。

先用 PerformanceObserver 捕获资源加载失败:

const cssFailures = new Set();

const observer = new PerformanceObserver((list) => {
const entries = list.getEntries();
entries.forEach((entry) => {
if (entry.initiatorType === 'link' && entry.name.includes('.css')) {
// transferredSize 为 0 且 duration 大于 0 基本可以判定失败
if (entry.transferSize === 0 && entry.duration > 0) {
cssFailures.add(entry.name);
reportCssError(entry.name, 'load_failed');
}
}
});
});

observer.observe({ entryTypes: ['resource'] });


但这有局限性,兼容性要 IE 以上的浏览器,而且有些跨域资源拿不到详细信息。所以需要配合 document.styleSheets 做二次校验:

function checkCssLoaded(linkElement, timeout = 5000) {
return new Promise((resolve) => {
const startTime = Date.now();

const check = () => {
// sheet 属性存在说明加载成功
if (linkElement.sheet && linkElement.sheet.cssRules) {
resolve(true);
return;
}

// 超时判定失败
if (Date.now() - startTime > timeout) {
resolve(false);
return;
}

requestAnimationFrame(check);
};

check();
});
}

// 对关键 CSS 做检测
document.querySelectorAll('link[rel="stylesheet"]').forEach(async (link) => {
const loaded = await checkCssLoaded(link);
if (!loaded) {
reportCssError(link.href, 'timeout_or_failed');
}
});


优化一下,如果你的 CSS 是动态加载的,创建 link 的时候就绑定检测:

function loadCssWithMonitor(url) {
return new Promise((resolve, reject) => {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = url;

// 双保险:onerror + 轮询检测
link.onerror = () => {
reportCssError(url, 'onerror_triggered');
reject(new Error(CSS load failed: ${url}));
};

document.head.appendChild(link);

checkCssLoaded(link).then((success) => {
if (success) {
resolve();
} else {
reportCssError(url, 'sheet_check_failed');
reject(new Error(CSS load failed: ${url}));
}
});
});
}


几个注意点。跨域 CSS 的 cssRules 读取会报安全错误,要 try-catch 包一下。PerformanceObserver 的 entryTypes 兼容性还不错,但移动端 UC 和部分国产浏览器可能有问题,建议做个特性检测再启用。

这套组合拳下来,基本能覆盖 95% 以上的场景,漏报率能压到很低。
点赞 1
2026-02-28 19:03