如何捕获并上报“因MIME类型不匹配被浏览器拒绝执行脚本”问题?
关于MIME类型校验导致脚本拒绝执行的客户端检测方案
结论先行
这类浏览器层面的MIME类型校验拦截脚本加载的错误,是可以在客户端检测到并完成上报的。你提到的window.onerror确实只能捕获JavaScript运行时错误,无法捕获资源加载类的拦截错误,需要用其他方案实现检测。
可用的检测方案
1. 全局资源加载错误监听
通过window.addEventListener绑定error事件,必须开启捕获模式(第三个参数设为true),因为资源加载错误不会向上冒泡,默认模式下无法监听到:
window.addEventListener('error', (e) => { // 筛选script标签加载失败的场景 if (e.target && e.target.tagName === 'SCRIPT') { const failedScriptSrc = e.target.src // 尝试请求资源头判断是否为MIME类型问题 fetch(failedScriptSrc, { method: 'HEAD' }).then(res => { const contentType = res.headers.get('content-type') // 校验返回的MIME类型是否符合脚本执行要求 if (!contentType || !contentType.includes('javascript')) { // 触发上报逻辑 reportError({ errorType: 'MIME_SCRIPT_REFUSED', scriptUrl: failedScriptSrc, returnContentType: contentType, pageUrl: window.location.href }) } }).catch(() => { // 跨域等场景无法获取响应头时,可先上报脚本加载失败基础信息 reportError({ errorType: 'SCRIPT_LOAD_FAILED', scriptUrl: failedScriptSrc, pageUrl: window.location.href }) }) } }, true)
2. 动态创建脚本的主动监听
如果你的应用存在动态创建script标签加载脚本的场景,可以单独给每个动态脚本绑定onerror回调:
const dynamicScript = document.createElement('script') dynamicScript.src = '你的脚本地址' dynamicScript.onerror = (e) => { // 复用上述校验和上报逻辑 } document.head.appendChild(dynamicScript)
3. Performance API辅助校验
可以通过Performance API拉取历史资源加载记录,做补充校验:
const allResources = performance.getEntriesByType('resource') allResources.forEach(res => { if (res.initiatorType === 'script' && res.responseStatus >= 400) { // 异常脚本加载记录上报逻辑 } })
注意事项
- 上报逻辑优先使用
navigator.sendBeacon接口实现,既不会阻塞页面主线程运行,也能避免页面卸载时上报请求被中断丢失 - 若跨域脚本无法拿到
Content-Type响应头,可先上报脚本加载失败的基础信息,再配合服务端日志共同定位MIME类型问题 - 内联脚本如果因type属性不合法被拦截,可以通过MutationObserver监听DOM中插入的script标签,提前校验type属性合法性
内容的提问来源于stack exchange,提问作者Greg Tomasik
相关产品推荐
相关产品推荐

