CDN 上 JS 运行时错误捕获

解决跨域脚本 Script error 问题,获取完整错误信息

问题

当 JavaScript 文件托管在 CDN 上时,使用 window.onerror 捕获错误只能得到 "Script error." 这样的简略信息,无法获取详细的错误堆栈。如何解决?

解答

问题原因

浏览器出于安全考虑,对跨域脚本的错误信息做了限制。当脚本与页面不同源时,window.onerror 只会返回 "Script error.",不会暴露具体错误内容。

解决方案

需要同时满足两个条件:

1. script 标签添加 crossorigin 属性

<!-- 添加 crossorigin="anonymous" -->
<script src="https://cdn.example.com/app.js" crossorigin="anonymous"></script>

2. CDN 服务器配置 CORS 响应头

Access-Control-Allow-Origin: *

或指定具体域名:

Access-Control-Allow-Origin: https://your-site.com

完整的错误捕获代码

// 捕获同步错误和资源加载错误
window.onerror = function(message, source, lineno, colno, error) {
  console.log('错误信息:', message);
  console.log('脚本地址:', source);
  console.log('行号:', lineno);
  console.log('列号:', colno);
  console.log('错误对象:', error);
  console.log('堆栈信息:', error?.stack);
  
  // 上报错误到监控系统
  reportError({
    message,
    source,
    lineno,
    colno,
    stack: error?.stack
  });
  
  // 返回 true 阻止默认错误处理
  return true;
};

// 捕获未处理的 Promise 错误
window.addEventListener('unhandledrejection', function(event) {
  console.log('Promise 错误:', event.reason);
  
  reportError({
    message: event.reason?.message || String(event.reason),
    stack: event.reason?.stack,
    type: 'unhandledrejection'
  });
});

// 捕获资源加载失败(图片、脚本等)
window.addEventListener('error', function(event) {
  // 判断是否为资源加载错误
  if (event.target && (event.target.src || event.target.href)) {
    console.log('资源加载失败:', event.target.src || event.target.href);
  }
}, true); // 使用捕获阶段

function reportError(data) {
  // 发送到错误监控服务
  navigator.sendBeacon('/api/error-log', JSON.stringify(data));
}

动态加载脚本时的处理

function loadScript(url) {
  const script = document.createElement('script');
  script.src = url;
  script.crossOrigin = 'anonymous'; // 关键:设置 crossOrigin
  document.head.appendChild(script);
}

loadScript('https://cdn.example.com/lib.js');

关键点

  • 跨域脚本默认只返回 "Script error.",这是浏览器的安全策略
  • 需要 script 标签添加 crossorigin="anonymous" 属性
  • CDN 必须返回 Access-Control-Allow-Origin 响应头,两者缺一不可
  • window.onerror 捕获同步错误,unhandledrejection 捕获 Promise 错误
  • 资源加载错误需要在捕获阶段监听 error 事件