白屏检测需在关键路径主动埋点,从dom挂载、资源加载、js执行三维度判断:用mutationobserver监听#app子节点变化,3秒无子节点即预警;结合performance.getentriesbytype('resource')查js/css加载失败;并兜底监听window.onerror和onunhandledrejection上报错误。

白屏检测不是等用户反馈才开始,而是要在页面加载关键路径上埋点监控——最有效的是从 DOM 是否挂载、资源是否加载、JS 是否执行成功三个维度同时判断。
用 MutationObserver 监控根节点是否渲染
页面白屏往往表现为 #app 或 #root 下始终空着,但控制台又没报错。这时候靠 DOMContentLoaded 不够,它只管 HTML 解析完,不管 Vue/React 是否真正挂载成功。
- 必须监听根容器子节点变化,而非只等
document.readyState === 'complete' - 设置 3s 超时:如果
document.querySelector('#app').children.length === 0持续超时,就认为白屏 - 注意:不能在
head里立即执行,要确保 DOM 已存在,建议放在body底部或用document.addEventListener('DOMContentLoaded', ...)
示例精简逻辑:
const root = document.querySelector('#app');
if (!root) return;
const observer = new MutationObserver(() => {
if (root.children.length > 0) {
clearTimeout(timeoutId);
observer.disconnect();
}
});
const timeoutId = setTimeout(() => {
console.warn('白屏预警:#app 3s 内无子节点');
}, 3000);
observer.observe(root, { childList: true });
用 performance.getEntriesByType('resource') 查关键资源失败
很多白屏根本不是 JS 报错,而是 app.js 或 index.css 返回了 404、403 或空响应,浏览器静默失败,连错误都懒得抛。
- 重点过滤
initiatorType === 'script'和name.includes('.js')的条目 - 检查
entry.duration === 0 && entry.transferSize === 0:大概率是资源未加载或被拦截 - 注意:该 API 在 iOS WKWebView 中部分版本不支持,需降级为监听
error事件捕获 script/link 标签加载失败
简单判断逻辑:
const jsEntries = performance.getEntriesByType('resource')
.filter(e => e.initiatorType === 'script' && e.duration > 0);
if (jsEntries.length === 0) {
console.warn('疑似主 JS 资源未加载');
}
在 window.onerror 和 window.onunhandledrejection 里加兜底上报
白屏常由未捕获的 JS 错误引发,比如 ReferenceError: Vue is not defined,但错误发生在异步链路(如 import() 动态加载后),try/catch 压根盖不到。
-
window.onerror能捕获同步脚本错误、资源加载失败(需开启crossorigin) -
window.onunhandledrejection必须加上,否则 Promise 拒绝会静默吞掉错误,Vue Router 导航守卫失败就是典型场景 - 上报时带上
location.href和document.referrer,能快速区分是首屏还是路由跳转白屏
别漏掉这个细节:
<script src="app.js" crossorigin></script>
没有 crossorigin,window.onerror 拿不到脚本内具体的错误行列号,只显示 “Script error.”
真机环境(尤其 iOS WKWebView)要额外检查 webView(_:didFinishNavigation:) 时机
App 内嵌 H5 白屏,80% 是因为 JS 注入太早——WKWebView 还没完成导航,就调用了 evaluateJavaScript,结果脚本执行时 document.body 还不存在,直接报错退出。
- 原生层必须等
webView(_:didFinishNavigation:)回调后再注入业务 JS - 前端 JS 入口不要依赖
document.body,改用document.querySelector('body') || document.documentElement - 禁用
async/defer:iOS 对脚本执行顺序更敏感,动态 import + async 混用极易导致依赖错乱
最容易被忽略的一点:本地调试用 file:// 协议时,fetch 请求默认被 CORS 拦截,但错误不会出现在控制台——要用 loadFileURL:allowingReadAccessToURL: 并传入父目录 URL 才行。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











