如何使用Javascript捕获浏览器中js/css资源的加载错误?
前端JS/CSS错误日志回传后端实现方案
1. 错误捕获实现
1.1 JS错误捕获
覆盖所有常见JS异常场景的捕获方式:
- 全局同步错误、未捕获的异步执行错误:监听
window.onerror事件,可直接获取错误信息、触发错误的文件路径、行列号、完整错误栈等核心字段。 - Promise未捕获的reject错误:监听
window.onunhandledrejection事件,专门处理async/await、Promise未写catch的异常场景。 - 框架层错误:如果使用前端框架,可结合框架自带的错误监听API拿到更精准的业务上下文信息,比如Vue用
app.config.errorHandler,React用错误边界/componentDidCatch。
1.2 CSS错误捕获
CSS错误不会触发全局冒泡的error事件,需针对性处理:
- 外联CSS文件加载错误:监听
window的error事件,必须开启捕获阶段(第三个参数传true,因为资源加载错误不会冒泡),再判断触发事件的元素是否是rel="stylesheet"的link标签即可。 - 内联CSS语法错误:浏览器默认不会抛出可直接捕获的运行时事件,建议在构建阶段加CSS语法校验拦截,运行时如果需要统计,可通过CSSOM API遍历样式表规则做异常检测。
- 样式兼容性类错误:如果需要统计特定样式未生效的场景,需结合业务逻辑自行埋点判断。
2. 日志回传实现要点
- 上报字段建议统一封装:包含错误类型(JS/CSS)、错误信息、错误栈、用户UA、页面URL、发生时间、用户唯一标识(按需),方便后端分类统计。
- 上报API优先选
navigator.sendBeacon():这是浏览器专门为统计上报设计的API,异步执行不阻塞主进程,就算页面关闭也会保证请求完成,性能损耗远低于普通AJAX。低版本浏览器可降级为低优先级XMLHttpRequest、或者1*1像素GIF请求。 - 上报策略优化:高并发线上场景可加采样率(比如10%采样降低后端压力)、错误去重(同一个错误固定周期内只上报1次)、离线缓存(无网络时存在
localStorage,联网后批量上报)、批量上报(攒够N条或者固定间隔上报一次,减少请求量)。
3. 核心代码示例
// 统一上报方法 function reportErrorLog(data) { const fullLog = JSON.stringify({ ...data, timestamp: Date.now(), userAgent: navigator.userAgent, pageUrl: window.location.href }) // 优先用sendBeacon上报 if (navigator.sendBeacon) { navigator.sendBeacon('/api/error/report', fullLog) return } // 低版本浏览器降级方案 const xhr = new XMLHttpRequest() xhr.open('POST', '/api/error/report', true) xhr.setRequestHeader('Content-Type', 'application/json') xhr.send(fullLog) } // 捕获JS全局错误 window.onerror = function (msg, fileUrl, line, col, error) { reportErrorLog({ type: 'js_error', message: msg, fileUrl, line, col, stack: error?.stack || '' }) return true } // 捕获Promise未处理reject window.onunhandledrejection = function (event) { reportErrorLog({ type: 'js_promise_unhandled_reject', message: event.reason?.message || String(event.reason), stack: event.reason?.stack || '' }) event.preventDefault() } // 捕获CSS文件加载错误 window.addEventListener('error', function (event) { const target = event.target if (target.tagName === 'LINK' && target.rel === 'stylesheet') { reportErrorLog({ type: 'css_load_error', fileUrl: target.href, message: '外联CSS文件加载失败' }) } }, true)
内容的提问来源于stack exchange,提问作者tspn
相关产品推荐
相关产品推荐

