🔍 js如何检测白屏?有哪些方法

📅 发布于 2026年3月 | 👤 作者:博主 | 🏷️ 标签:白屏检测, DOM检测, 像素采样, FCP, 性能监控, Web开发, 前端, 面试

欢迎来到我的博客文章!所有文章都是满满的前端干货,文章简明扼要。

一句话总结:白屏检测没有"银弹",生产环境通常采用 "DOM 节点检查 + 关键像素采样 + 错误监控"组合拳

方案对比总览

方案 原理 准确率 性能消耗 适用场景
1. DOM 节点检测 检查根节点是否有内容 ⭐⭐⭐⭐ 最推荐,SPA 首选
2. 像素采样检测 Canvas 取点判断颜色 ⭐⭐⭐⭐⭐ 对视觉要求高的场景
3. 性能 API 检测 监控 FCP/FP 时间 ⭐⭐⭐ 辅助判断加载慢
4. 错误监控 捕获 JS 报错 ⭐⭐ 定位原因,非直接检测

方案一:DOM 节点检测(最实用🔥)

原理:在页面加载后(如 3 秒),检查应用根节点(如 #app)是否有子元素或特定内容。

function detectWhiteScreenByDOM() {
  const rootElement = document.getElementById('app');
  
  // 设定阈值时间,比如 3 秒后检查
  setTimeout(() => {
    if (!rootElement || 
        rootElement.innerHTML.trim() === '' || 
        rootElement.children.length === 0) {
      reportWhiteScreen('DOM_EMPTY');
    }
    
    // 进阶:检查是否有特定关键元素(如导航栏、底部栏)
    const criticalEl = document.querySelector('.main-content');
    if (!criticalEl) {
      reportWhiteScreen('CRITICAL_ELEMENT_MISSING');
    }
  }, 3000);
}

// 排除 Loading 状态(避免误报)
// 如果页面有 <div id="loading">,需先确认它已消失

优点:实现简单,性能消耗极低,准确率高。

缺点:如果根节点里有"加载中..."文字,可能误判为有内容。

方案二:像素采样检测(最直观👁️)

原理:利用 Canvas 截取屏幕关键点的像素,判断是否全为白色(或背景色)。

function detectWhiteScreenByPixel() {
  setTimeout(() => {
    const canvas = document.createElement('canvas');
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    const ctx = canvas.getContext('2d');
    
    // 通用替代方案:采样 9 个点
    const points = [
      { x: 0.1, y: 0.1 }, { x: 0.5, y: 0.1 }, { x: 0.9, y: 0.1 },
      { x: 0.1, y: 0.5 }, { x: 0.5, y: 0.5 }, { x: 0.9, y: 0.5 },
      { x: 0.1, y: 0.9 }, { x: 0.5, y: 0.9 }, { x: 0.9, y: 0.9 }
    ];
    
    let whiteCount = 0;
    points.forEach(p => {
      const x = Math.floor(window.innerWidth * p.x);
      const y = Math.floor(window.innerHeight * p.y);
      // 实际需配合 html2canvas 或后端截图服务
      // if (isWhitePixel(x, y)) whiteCount++;
    });
    
    if (whiteCount >= 8) { // 9 个点 8 个是白色
      reportWhiteScreen('PIXEL_ALL_WHITE');
    }
  }, 3000);
}

生产环境最佳实践(组合方案)

在真实项目中,建议采用以下分层检测策略:

1. 上报策略(关键!)

使用 navigator.sendBeacon 发送数据,即使页面白屏卡死,数据也能发出。

function reportWhiteScreen(type) {
  const data = JSON.stringify({
    type,
    url: location.href,
    ua: navigator.userAgent,
    time: Date.now()
  });
  
  // 优先 sendBeacon,不支持则 fallback 到 fetch
  if (navigator.sendBeacon) {
    navigator.sendBeacon('/api/monitor/white-screen', data);
  } else {
    fetch('/api/monitor/white-screen', { 
      method: 'POST', 
      body: data, 
      keepalive: true 
    });
  }
}

2. 排除误报

3. 完整代码示例(可直接用)

class WhiteScreenMonitor {
  constructor(options = {}) {
    this.delay = options.delay || 3000;
    this.rootId = options.rootId || 'app';
  }
  
  init() {
    // 1. DOM 检测
    setTimeout(() => this.checkDOM(), this.delay);
    // 2. FCP 检测
    this.observeFCP();
    // 3. 错误监听
    this.listenErrors();
  }
  
  checkDOM() {
    const root = document.getElementById(this.rootId);
    if (!root || root.innerHTML.trim() === '') {
      this.report('DOM_EMPTY');
    }
  }
  
  observeFCP() {
    let fcpTriggered = false;
    new PerformanceObserver((list) => {
      fcpTriggered = true;
      const fcp = list.getEntries().pop();
      if (fcp.startTime > 5000) this.report('FCP_SLOW');
    }).observe({ entryTypes: ['paint'] });
    
    setTimeout(() => {
      if (!fcpTriggered) this.report('NO_FCP');
    }, this.delay + 2000);
  }
  
  listenErrors() {
    window.onerror = (msg) => this.report('JS_ERROR', { msg });
  }
  
  report(type, extra = {}) {
    console.warn(`⚠️ 白屏预警:${type}`, extra);
    // 调用 sendBeacon 上报
  }
}

// 使用
new WhiteScreenMonitor().init();

面试回答模板

"白屏检测我通常采用组合策略,因为单一方法有局限:

  1. 首选 DOM 检测:在页面加载 3 秒后,检查根节点是否有内容,这是成本最低且最有效的方法。
  2. 辅以 FCP 监控:通过 Performance API 监听首屏绘制时间,如果超过 5 秒未绘制,视为异常。
  3. 错误兜底:监听 window.onerror 和资源加载失败,因为白屏往往是由 JS 报错引起的。
  4. 上报优化:使用 sendBeacon 发送监控数据,确保即使页面卡死也能上报。

在之前的项目中,我还加了Loading 状态排除,避免用户正常等待时被误报。"

⚠️ 常见坑点

核心总结

← 返回首页