美文网首页
白屏骨架屏监控

白屏骨架屏监控

作者: Roseska | 来源:发表于2020-12-19 19:14 被阅读0次

调研过程

  1. 发现了几个有意思的api
  • Document.elementsFromPoint():可以获取到当前视口内指定坐标处,由里到外排列的所有元素
  • HTMLElement.innerTextinnerText 很容易与Node.textContent混淆, 但这两个属性间实际上有很重要的区别. 大体来说, innerText 可操作已被渲染的内容, 而 textContent 则不会
  • Node.nodeType只读属性Node.nodeType 表示的是该节点的类型
  • Document.getElementsByClassName():返回一个包含了所有指定类名的子元素的类数组对象
  • CanvasRenderingContext2D.measureText():返回一个关于被测量文本TextMetrics 对象包含的信息(例如它的宽度)
     let ctx = this.container.getContext('2d'); // canvas 上下文
     let width= ctx.measureText(name).width;
    
  1. 前端监控几个方法
  • 如果每次都去遍历新增元素并计算是否可见是非常消耗性能的。实际上采用的是深度优先算法,如果子元素可见,那父元素可见,不再计算。 同样的,如果最后一个元素可见,那前面的兄弟元素也可见。通过深度优先算法,性能有了大幅的提升

  • mutationObserver:通过这个API可以获得页面状态变化

  • 加载白屏时间可以通过first meaningful paint来判定,(first meaning paint, 也就是主要内容可见时间)

  • Hook宿主方APP里所有UIWebViewdelegate事件,获取网页加载结束的时机。截取网页图像,然后将完整的图像压缩成一定比例,一般取横向7个像素,纵向根据原比例得出,比如原网页视图700*1000,压缩之后的图像大小:7*10。遍历图像上的像素,是否全为白色点,以此确定网页是否白屏,埋点上报

我的思路:

以下是判断白屏、骨架屏方法:

  • 首先调查下目前的骨架屏方案有哪些,如果都是dom节点,就遍历所有的dom判断里边是否有文字,由于这种方案会同时判断白屏,可以通过形状来把白屏和骨架屏区分开,或者判断不是白屏就是骨架屏

注意点:

  1. 有的页面顶部有走马灯,这样可能会影响骨架屏的判断
  2. 有的插件引入后会中带有默认文字,这样会影响骨架屏的判断,可以动态传入页面id来解决
let root = typeof self == 'object' && self.self === self && self || typeof global == 'object' && global.global === global && global || window || {};
setTimeout(() => {
  skeletonscreen()
}, 5000);

//  递归函数,获取页面dom数组
function countNodes (node, deepArr) {
  node = node || document.body
  //  计算自身
  let arr = deepArr ? deepArr : []
  //  判断是否存在子节点
  if (node.hasChildNodes()) {
    //  获取子节点
    var cnodes = node.childNodes;
    //  对子节点进行递归统计
    for (var i = 0; i < cnodes.length; i++) {
      countNodes(cnodes.item(i), arr)
    }
  } else {
    arr.push(node)
  }
  return arr;
}

//  统计body的节点
let nodesArr = countNodes()
console.log('nodesArr', nodesArr)

let isNoTxt = nodesArr.some((item, index) => {
  return item.nodeValue && item.nodeValue.replace(/\s*/g, "")
})


let seletonseletonCoordinates = []

//计算每个色块的面积
const linkSum = (i, j, num) => {
  //走过的路就置0
  coordinates[i][j] = 0;

  num++;
  //向上
  if ((i + 1 < h) && coordinates[i + 1][j] == 1) {
    num = linkSum(i + 1, j, num);
  }
  //向右
  if ((j + 1 < w) && coordinates[i][j + 1] == 1) {
    num = linkSum(i, j + 1, num);
  }
  //向下
  if ((i - 1 >= 0) && coordinates[i - 1][j] == 1) {
    num = linkSum(i - 1, j, num);
  }
  //向左
  if ((j - 1 >= 0) && coordinates[i][j - 1] == 1) {
    num = linkSum(i, j - 1, num);
  }
  return num;
}


//计算总块数和灰色区域总面积
const getCountAndArea = () => {
  let sum = [];
  let count = 0;
  for (let i = 0; i < h; i++) {
    for (let j = 0; j < w; j++) {
      //连续1的个数
      if (seletonCoordinates[i][j] == 1) {
        let buf = 0;
        buf = linkSum(i, j, buf);
        count++;
        sum.push({
          index: count,
          area: buf
        });
      }
    }
  }
  return {
    count,
    sum
  };
}

//根据颜色判断
function skeletonscreen () {
  if (root.html2canvas) {
    html2canvas(document.body, {
      backgroundColor: null,   //设置截图的背景色
      useCORS: true, // 如果截图的内容里有图片,可能会有跨域的情况,加上这个参数,解决文件跨域问题
      allowTaint: false, //允许跨域(图片跨域相关)
      taintTest: true, //是否在渲染前测试图片
    }).then((canvas) => {
      let ctx = canvas.getContext("2d");
      const ratio = root.devicePixelRatio
      const width = document.body.clientWidth * ratio
      const height = document.body.clientHeight * ratio / 3
      let img = ctx.getImageData(0, 0, width, height);
      let sumPx = 0
      const imgdata = img.data
      let r, g, b
      let x = 0, y = 0
      //设置二维数组
      for (let i = 0; i < height; i++) {
        seletonCoordinates[i] = []
      }
      for (var i = 0; i < imgdata.length; i += 4) {
        r = imgdata[i];
        g = imgdata[i + 1];
        b = imgdata[i + 2];
        if (r === 255 && g === 255 && b === 255) {
          sumPx += 1
          seletonCoordinates[y][x] = 0
        } else {
          seletonCoordinates[y][x] = 1
        }
        x++
        if (x > width) {
          x = 0
          y++
        }
      }
   
      let rst = getCountAndArea();
      if (rst.count > 3 && !isNoTxt) {
        console.log('页面骨架屏')
      }
    })
  } 
}

相关文章

  • 白屏骨架屏监控

    调研过程 发现了几个有意思的api Document.elementsFromPoint()[https://de...

  • SPA应用性能优化问题

    解决空白屏问题 组件懒加载和路由懒加载 骨架屏 骨架屏(skeleton screen)已经不是什么新奇的概念,他...

  • 前端监控系统

    前端的监控主要分为三个方面: 性能监控 白屏时间; 首屏时间; 用户可交互时间; 总下载时间; TCP连接时间;...

  • vue-cli3 配置骨架屏方案

    vue-cli3配置骨架屏方案 前言 最近在学vue,准备使用vue写一个移动端项目。考虑到首页白屏优化,需要实现...

  • iOS常用库列表

    1、TABAnimated 骨架屏参考链接 CocoaPods pod 'TABAnimated' 骨架屏自动生成...

  • 骨架屏( Skeleton Screen )

    骨架屏 什么是骨架屏 骨架屏英文叫 Skeleton Screen,也被称为加载占位图。它是在页面数据尚未加载前先...

  • 浅析前端异常与性能监测

    浅析前端异常与性能监测 1. 接口加载时间和是否成功监控 2. 页面性能(dns解析等) 白屏时间和首屏时间有争议...

  • 骨架屏

    一、简介 1.1 骨架屏 SPA应用,由于初始的html内部只有一个空的div,需要等待 js、css加载编译完成...

  • 骨架屏

    https://www.jb51.net/article/140019.htm

  • 骨架屏

    一、什么是骨架屏? 骨架屏可以理解为是在需要等待加载内容的位置提供一个占位图形组合,描绘了当前页面的大致框架的骨架...

网友评论

      本文标题:白屏骨架屏监控

      本文链接:https://www.haomeiwen.com/subject/cimcnktx.html