当前位置:首页 > 科技  > 软件

首屏时间,你说你优化了,那你倒是计算出来给我看啊!

来源: 责编: 时间:2024-04-15 18:17:11 315观看
导读前言大家好,我是林三心,用最通俗易懂的话讲最难的知识点是我的座右铭,基础是进阶的前提是我的初心背景当我们在做项目的性能优化的时候,优化首屏时间是一个避不过去的优化方向,但是又有多少人想过这两个东西的区别呢:白屏时

前言

大家好,我是林三心,用最通俗易懂的话讲最难的知识点是我的座右铭,基础是进阶的前提是我的初心AEJ28资讯网——每日最新资讯28at.com

背景

当我们在做项目的性能优化的时候,优化首屏时间是一个避不过去的优化方向,但是又有多少人想过这两个东西的区别呢:AEJ28资讯网——每日最新资讯28at.com

  • 白屏时间
  • 首屏时间

并且这两个时间的计算方式又有什么区别呢?接下来我就给大家讲一下吧!AEJ28资讯网——每日最新资讯28at.com

白屏时间

是什么?

白屏时间指的是:页面开始显示内容的时间。也就是:浏览器显示第一个字符或者元素的时间AEJ28资讯网——每日最新资讯28at.com

图片图片AEJ28资讯网——每日最新资讯28at.com

怎么算?

我们只需要知道浏览器开始显示内容的时间点,即页面白屏结束时间点即可获取到页面的白屏时间。AEJ28资讯网——每日最新资讯28at.com

因此,我们通常认为浏览器开始渲染<body>标签或者解析完<head>标签的时刻就是页面白屏结束的时间点。AEJ28资讯网——每日最新资讯28at.com

  • 浏览器支持performance.timing
<head>  <title>Document</title></head><script type="text/javascript">  // 白屏时间结束点  var firstPaint = Date.now()  var start = performance.timing.navigationStart  console.log(firstPaint - start)</script>
  • 浏览器不支持performance.timing
<head>  <title>Document</title>  <script type="text/javascript">    window.start = Date.now();  </script></head><script type="text/javascript">  // 白屏时间结束点  var firstPaint = Date.now()  console.log(firstPaint - window.start)</script>

首屏时间

是什么?

首屏时间是指用户打开网站开始,到浏览器首屏内容渲染完成的时间。对于用户体验来说,首屏时间是用户对一个网站的重要体验因素。AEJ28资讯网——每日最新资讯28at.com

图片图片AEJ28资讯网——每日最新资讯28at.com

为什么不直接用生命周期?

有些小伙伴会说:为啥不直接在App.vue的mounted生命周期里计算时间呢?大家可以看看,官网说了mounted执行并不代表首屏所有元素加载完毕,所以mounted计算出来的时间会偏短。AEJ28资讯网——每日最新资讯28at.com

图片图片AEJ28资讯网——每日最新资讯28at.com

为什么不直接用nextTick?

nextTick回调的时候,首屏的DOM都渲染出来了,但是计算首屏时间并不需要渲染所有DOM,所以计算出来的时间会偏长AEJ28资讯网——每日最新资讯28at.com

怎么算?

我们需要利用MutationObserver监控DOM的变化,监控每一次DOM变化的分数,计算的规则为: (1 + 层数 * 0.5),我举个例子:AEJ28资讯网——每日最新资讯28at.com

<body>    <div>      <div>1</div>      <div>2</div>    </div></body>

以上DOM结构的分数为:AEJ28资讯网——每日最新资讯28at.com

1.5 + 2 + 2.5 + 2.5 = 8.5(分)AEJ28资讯网——每日最新资讯28at.com

图片图片AEJ28资讯网——每日最新资讯28at.com

其实在首屏的加载中,会涉及到DOM的增加、修改、删除,所以会触发多次MutationObserver,所以会统计出不同阶段的score,我们把这些score存放在一个数组observerData中,后面大有用处AEJ28资讯网——每日最新资讯28at.com

首屏时间实践

现在我们开始计算首屏时间吧!AEJ28资讯网——每日最新资讯28at.com

前置准备

  • index.html:html页面
<!DOCTYPE html><html lang="en">  <head> </head>  <body>    <div>      <div>        <div>1</div>        <div>2</div>      </div>      <div>3</div>      <div>4</div>    </div>    <ul id="ulbox"></ul>  </body>  <script src="./computed.js"></script>  <script src="./request.js"></script></html>
  • computed.js:计算首屏时间的文件
const observerData = []let observer = new MutationObserver(() => {  // 计算每次DOM修改时,距离页面刚开始加载的时间  const start = window.performance.timing.navigationStart  const time = new Date().getTime() - start    const body = document.querySelector('body')  const score = computedScore(body, 1)  // 加到数组 observerData 中  observerData.push({    score,    time  })})observer.observe(  document, {    childList: true,    subtree: true  })function computedScore(element, layer) {  let score = 0  const tagName = element.tagName  // 排除这些标签的情况  if (    tagName !== 'SCRIPT' &&    tagName !== 'STYLE' &&    tagName !== 'META' &&    tagName !== 'HEAD'  ) {    const children = element.children    if (children && children.length) {      // 递归计算分数      for (let i = 0; i < children.length; i++) {        score += computedScore(children[i], layer + 1)      }    }    score += 1 + 0.5 * layer  }  return score}
  • request.js:模拟请求修改DOM
// 模拟请求列表const requestList = () => {  return new Promise((resolve) => {    setTimeout(() => {      resolve(        [1, 2, 3,          4, 5, 6,          7, 8, 9        ]      )    }, 1000)  })}const ulbox = document.getElementById('ulbox')// 模拟请求数据渲染列表const renderList = async () => {  const list = await requestList()  const fragment = document.createDocumentFragment()  for (let i = 0; i < list.length; i++) {    const li = document.createElement('li')    li.innerText = list[i]    fragment.appendChild(li)  }  ulbox.appendChild(fragment)}// 模拟对列表进行轻微修改const addList = async () => {  const li = document.createElement('li')  li.innerText = '加上去'  ulbox.appendChild(li)}(async () => {  // 模拟请求数据渲染列表  await renderList()  // 模拟对列表进行轻微修改  addList()})()

observerData

当我们一切准备就绪后运行代码,我们获得了observerData,我们看看它长什么样?AEJ28资讯网——每日最新资讯28at.com

计算首屏时间

我们怎么根据observerData来计算首屏时间呢?我们可以这么算:下次分数比上次分数增加幅度最大的时间作为首屏时间AEJ28资讯网——每日最新资讯28at.com

很多人会问了,为什么不是取最后一项的时间来当做首屏时间呢?大家要注意了:首屏并不是所有DOM都渲染,我就拿刚刚的代码来举例吧,我们渲染完了列表,然后再去增加一个li,那你是觉得哪个时间段算是首屏呢?应该是渲染完列表后算首屏完成,因为后面只增加了一个li,分数的涨幅较小,可以忽略不计AEJ28资讯网——每日最新资讯28at.com

所以我们开始计算吧:AEJ28资讯网——每日最新资讯28at.com

const observerData = []let observer = new MutationObserver(() => {  // 计算每次DOM修改时,距离页面刚开始加载的时间  const start = window.performance.timing.navigationStart  const time = new Date().getTime() - start  const body = document.querySelector('body')  const score = computedScore(body, 1)  observerData.push({    score,    time  })  // complete时去调用 unmountObserver  if (document.readyState === 'complete') {    // 只计算10秒内渲染时间    unmountObserver(10000)  }})observer.observe(  document, {    childList: true,    subtree: true  })function computedScore(element, layer) {  let score = 0  const tagName = element.tagName  // 排除这些标签的情况  if (    tagName !== 'SCRIPT' &&    tagName !== 'STYLE' &&    tagName !== 'META' &&    tagName !== 'HEAD'  ) {    const children = element.children    if (children && children.length) {      // 递归计算分数      for (let i = 0; i < children.length; i++) {        score += computedScore(children[i], layer + 1)      }    }    score += 1 + 0.5 * layer  }  return score}// 计算首屏时间function getFirstScreenTime() {  let data = null  for (let i = 1; i < observerData.length; i++) {    // 计算幅度    const differ = observerData[i].score - observerData[i - 1].score    // 取最大幅度,记录对应时间    if (!data || data.rate <= differ) {      data = {        time: observerData[i].time,        rate: differ      }    }  }  return data}let timer = nullfunction unmountObserver(delay) {  if (timer) return  timer = setTimeout(() => {    // 输出首屏时间    console.log(getFirstScreenTime())    // 终止MutationObserver的监控    observer.disconnect()    observer = null    clearTimeout(timer)  }, delay)}

计算出首屏时间1020msAEJ28资讯网——每日最新资讯28at.com

总结

我这个计算方法其实很多漏洞,没把删除元素也考虑进去,但是想让大家知道计算首屏时间的计算思想,这才是最重要的,希望大家能理解这个计算思想。AEJ28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-83640-0.html首屏时间,你说你优化了,那你倒是计算出来给我看啊!

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 改造 console.log!也能提高团队开发效率?

下一篇: 阿里一面:如何将重复性比较高的 String 类型的地址信息从 20GB 降到几百兆?

标签:
  • 热门焦点
  • 影音体验是真的强 简单聊聊iQOO Pad

    大公司的好处就是产品线丰富,非常细分化的东西也能给你做出来,例如早先我们看到了新的vivo Pad2,之后我们又在iQOO Neo8 Pro的发布会上看到了iQOO的首款平板产品iQOO Pad。虽
  • 三言两语说透设计模式的艺术-简单工厂模式

    一、写在前面工厂模式是最常见的一种创建型设计模式,通常说的工厂模式指的是工厂方法模式,是使用频率最高的工厂模式。简单工厂模式又称为静态工厂方法模式,不属于GoF 23种设计
  • 之家push系统迭代之路

    前言在这个信息爆炸的互联网时代,能够及时准确获取信息是当今社会要解决的关键问题之一。随着之家用户体量和内容规模的不断增大,传统的靠"主动拉"获取信息的方式已不能满足用
  • 每天一道面试题-CPU伪共享

    前言:了不起:又到了每天一到面试题的时候了!学弟,最近学习的怎么样啊 了不起学弟:最近学习的还不错,每天都在学习,每天都在进步! 了不起:那你最近学习的什么呢? 了不起学弟:最近在学习C
  • 年轻人的“职场羞耻感”,无处不在

    作者:冯晓亭 陶 淘 李 欣 张 琳 马舒叶来源:燃次元&ldquo;人在职场,应该选择什么样的着装?&rdquo;近日,在网络上,一个与着装相关的帖子引发关注,在该帖子里,一位在高级写字楼亚洲金
  • OPPO K11样张首曝:千元机影像“卷”得真不错!

    一直以来,OPPO K系列机型都保持着较为均衡的产品体验,历来都是2K价位的明星机型,去年推出的OPPO K10和OPPO K10 Pro两款机型凭借各自的出色配置,堪称有
  • 联想YOGA 16s 2022笔记本将要推出,屏幕支持触控功能

    联想此前宣布,将于11月2日19:30召开联想秋季轻薄新品发布会,推出联想 YOGA 16s 2022 笔记本等新品。官方称,YOGA 16s 2022 笔记本将搭载 16 英寸屏幕,并且是一
  • AI艺术欣赏体验会在上海梅赛德斯奔驰中心音乐俱乐部上演

    光影交错的镜像世界,虚实幻化的视觉奇观,虚拟偶像与真人共同主持,这些场景都出现在2019世界人工智能大会的舞台上。8月29日至31日,“AI艺术欣赏体验会”在上海
  • 外交部:美方应停止在网络安全问题上不负责任地指责他国

      中国外交部今天(16日)举行例行记者会。会上,有记者问,美国情报官员称,他们正在阻拦来自中国以及其他国家的黑客获取相关科研成果。 中方对此有何评论?对此
Top