白屏检测需在html文档层面主动埋点,聚焦dom挂载、资源加载、js执行三环节:用mutationobserver监听#app子节点变化并设3秒超时;用performance.getentriesbytype('resource')检测js/css加载失败;以window.onerror和window.onunhandledrejection兜底捕获框架级错误。

白屏检测不能只靠用户反馈或等页面加载完再判断,必须在 HTML 文档层面主动埋点——核心是抓住 DOM 是否真实挂载、关键资源是否加载、JS 是否执行成功这三个不可跳过的环节。
MutationObserver 监控 #app 子节点变化
白屏最常见表现就是 #app 或 #root 容器下始终没有子节点,但控制台无报错。此时 DOMContentLoaded 早已触发,它只代表 HTML 解析完成,不等于 Vue/React 已完成挂载。
必须用 MutationObserver 实时监听根容器结构变化,并配合超时机制:
- 确保
document.querySelector('#app')存在后再初始化 observer,否则直接跳过 - 观察选项必须设为
{ childList: true },不需subtree: true,避免误触发深层变动 - 超时时间建议设为
3000,太短会误报(如 SSR 首屏慢、hydration 延迟),太长失去预警意义 - 一旦发现
root.children.length > 0,立即clearTimeout并observer.disconnect(),避免内存泄漏
performance.getEntriesByType('resource') 检查 JS/CSS 加载状态
很多白屏根本不是 JS 报错,而是 app.js 或 index.css 返回了 404、空响应或被 CDN 拦截,浏览器静默失败,连 error 事件都不抛。
用 Performance API 是目前最轻量、最可靠的资源层检测方式:
- 过滤条件要写全:
e.initiatorType === 'script' || e.initiatorType === 'link',不能只看.js后缀(ESM 动态 import 可能无后缀) - 关键判断依据是:
e.duration === 0 && e.transferSize === 0,表示资源未发起请求或被拦截;e.responseEnd === 0表示没收到响应 - iOS WKWebView 低版本(iOS 14.5 以下)不支持该 API,需降级:给
<script></script>和<link>标签加onerror回调兜底 - 不要依赖
performance.timing,它已被废弃,且无法反映现代构建产物的资源加载路径
window.onerror + window.onunhandledrejection 兜底捕获框架级错误
Vue 的 mount 失败、React 的 hydrateRoot 抛出 ReferenceError: React is not defined,这类错误常发生在异步链路中,try/catch 完全覆盖不了。
这两个全局监听器是最后一道防线:
-
window.onerror能捕获同步脚本错误、资源加载失败(event.target是script或link元素)、以及部分跨域脚本错误(需crossorigin属性) -
window.onunhandledrejection必须监听,因为现代框架大量使用import()、createApp().mount()等 Promise 链,拒绝未处理就会中断渲染 - 上报前建议加简单过滤:排除已知监控 SDK 错误、排除
ResizeObserver loop completed这类非致命警告 - 注意:Safari 对
onunhandledrejection的兼容性较弱,需配合Promise.prototype.catch在关键入口手动包裹
真正难的不是写几个监听器,而是把这三套逻辑在 HTML 文档里「对齐时机」:MutationObserver 要在 底部或 DOMContentLoaded 后立即注册;Performance 数据要在所有资源加载完成后(比如 window.addEventListener('load', ...))才稳定可读;而错误监听必须在任何业务 JS 执行前就挂上——顺序错了,整套检测就形同虚设。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











