国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

首屏?xí)r間,你說你優(yōu)化了,那你倒是計算出來給我看啊!

開發(fā) 前端
我們只需要知道瀏覽器開始顯示內(nèi)容的時間點,即頁面白屏結(jié)束時間點即可獲取到頁面的白屏?xí)r間。因此,我們通常認為瀏覽器開始渲染<body>標簽或者解析完<head>標簽的時刻就是頁面白屏結(jié)束的時間點。

前言

大家好,我是林三心,用最通俗易懂的話講最難的知識點是我的座右銘,基礎(chǔ)是進階的前提是我的初心

背景

當(dāng)我們在做項目的性能優(yōu)化的時候,優(yōu)化首屏?xí)r間是一個避不過去的優(yōu)化方向,但是又有多少人想過這兩個東西的區(qū)別呢:

  • 白屏?xí)r間
  • 首屏?xí)r間

并且這兩個時間的計算方式又有什么區(qū)別呢?接下來我就給大家講一下吧!

白屏?xí)r間

是什么?

白屏?xí)r間指的是:頁面開始顯示內(nèi)容的時間。也就是:瀏覽器顯示第一個字符或者元素的時間

圖片圖片

怎么算?

我們只需要知道瀏覽器開始顯示內(nèi)容的時間點,即頁面白屏結(jié)束時間點即可獲取到頁面的白屏?xí)r間。

因此,我們通常認為瀏覽器開始渲染<body>標簽或者解析完<head>標簽的時刻就是頁面白屏結(jié)束的時間點。

  • 瀏覽器支持performance.timing
<head>
  <title>Document</title>
</head>
<script type="text/javascript">
  // 白屏?xí)r間結(jié)束點
  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">
  // 白屏?xí)r間結(jié)束點
  var firstPaint = Date.now()
  console.log(firstPaint - window.start)
</script>

首屏?xí)r間

是什么?

首屏?xí)r間是指用戶打開網(wǎng)站開始,到瀏覽器首屏內(nèi)容渲染完成的時間。對于用戶體驗來說,首屏?xí)r間是用戶對一個網(wǎng)站的重要體驗因素。

圖片圖片

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

有些小伙伴會說:為啥不直接在App.vue的mounted生命周期里計算時間呢?大家可以看看,官網(wǎng)說了mounted執(zhí)行并不代表首屏所有元素加載完畢,所以mounted計算出來的時間會偏短。

圖片圖片

為什么不直接用nextTick?

nextTick回調(diào)的時候,首屏的DOM都渲染出來了,但是計算首屏?xí)r間并不需要渲染所有DOM,所以計算出來的時間會偏長

怎么算?

我們需要利用MutationObserver監(jiān)控DOM的變化,監(jiān)控每一次DOM變化的分數(shù),計算的規(guī)則為: (1 + 層數(shù) * 0.5),我舉個例子:

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

以上DOM結(jié)構(gòu)的分數(shù)為:

1.5 + 2 + 2.5 + 2.5 = 8.5(分)

圖片圖片

其實在首屏的加載中,會涉及到DOM的增加、修改、刪除,所以會觸發(fā)多次MutationObserver,所以會統(tǒng)計出不同階段的score,我們把這些score存放在一個數(shù)組observerData中,后面大有用處

首屏?xí)r間實踐

現(xiàn)在我們開始計算首屏?xí)r間吧!

前置準備

  • 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:計算首屏?xí)r間的文件
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)
  // 加到數(shù)組 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) {
      // 遞歸計算分數(shù)
      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')

// 模擬請求數(shù)據(jù)渲染列表
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 () => {
  // 模擬請求數(shù)據(jù)渲染列表
  await renderList()
  // 模擬對列表進行輕微修改
  addList()
})()

observerData

當(dāng)我們一切準備就緒后運行代碼,我們獲得了observerData,我們看看它長什么樣?

計算首屏?xí)r間

我們怎么根據(jù)observerData來計算首屏?xí)r間呢?我們可以這么算:下次分數(shù)比上次分數(shù)增加幅度最大的時間作為首屏?xí)r間

很多人會問了,為什么不是取最后一項的時間來當(dāng)做首屏?xí)r間呢?大家要注意了:首屏并不是所有DOM都渲染,我就拿剛剛的代碼來舉例吧,我們渲染完了列表,然后再去增加一個li,那你是覺得哪個時間段算是首屏呢?應(yīng)該是渲染完列表后算首屏完成,因為后面只增加了一個li,分數(shù)的漲幅較小,可以忽略不計

所以我們開始計算吧:

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時去調(diào)用 unmountObserver
  if (document.readyState === 'complete') {
    // 只計算10秒內(nèi)渲染時間
    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) {
      // 遞歸計算分數(shù)
      for (let i = 0; i < children.length; i++) {
        score += computedScore(children[i], layer + 1)
      }
    }

    score += 1 + 0.5 * layer
  }
  return score
}

// 計算首屏?xí)r間
function getFirstScreenTime() {
  let data = null
  for (let i = 1; i < observerData.length; i++) {
    // 計算幅度
    const differ = observerData[i].score - observerData[i - 1].score
    // 取最大幅度,記錄對應(yīng)時間
    if (!data || data.rate <= differ) {
      data = {
        time: observerData[i].time,
        rate: differ
      }
    }
  }
  return data
}

let timer = null

function unmountObserver(delay) {
  if (timer) return
  timer = setTimeout(() => {
    // 輸出首屏?xí)r間
    console.log(getFirstScreenTime())
    // 終止MutationObserver的監(jiān)控
    observer.disconnect()
    observer = null
    clearTimeout(timer)
  }, delay)
}

計算出首屏?xí)r間1020ms

總結(jié)

我這個計算方法其實很多漏洞,沒把刪除元素也考慮進去,但是想讓大家知道計算首屏?xí)r間的計算思想,這才是最重要的,希望大家能理解這個計算思想。

責(zé)任編輯:武曉燕 來源: 前端之神
相關(guān)推薦

2021-08-11 07:55:10

Go內(nèi)置函數(shù)

2022-02-24 07:56:27

Linux系統(tǒng)ELF

2021-02-14 14:06:24

SQL數(shù)據(jù)庫面試

2015-06-25 10:57:15

推薦系統(tǒng)老婆算出來

2009-11-06 13:54:09

Visual Stud

2022-07-14 08:22:48

Computedvue3

2021-11-09 14:08:45

DockerDockerfileJava

2021-03-01 10:38:13

深度學(xué)習(xí)編程人工智能

2011-08-24 13:32:56

CREATE TABL中文man

2020-03-16 10:42:23

大數(shù)據(jù)IT工具

2020-03-25 10:44:16

位運算操作技巧

2023-11-08 08:09:36

幾何算法解析幾何

2024-12-26 11:49:14

2023-05-08 00:01:29

數(shù)據(jù)分析指標標簽

2009-09-10 16:22:48

LINQ建立數(shù)據(jù)報表

2025-07-01 01:55:00

Redis集群模式

2022-10-12 00:07:25

加密貨幣區(qū)塊鏈比特幣

2012-04-25 22:58:36

2023-12-08 13:16:00

CSSJSXStyleX

2018-12-12 11:11:20

系統(tǒng)可靠性可用性
點贊
收藏

51CTO技術(shù)棧公眾號

九九99久久| 国产视频一二三区| 欧美美女在线| 亚洲午夜未删减在线观看| 在线视频中文字幕第一页| 欧美日韩加勒比精品一区| 国产va在线| 中文字幕乱码一区二区免费| 日韩精品一区二区免费| 午夜在线观看免费一区| 国产精成人品localhost| 欧美国产小视频| 国产精品国产亚洲伊人久久 | 国产精品久久久久9999吃药| 久草资源站在线观看| 成人短视频下载| 可以看毛片的网址| 99天天综合性| 欧美亚洲精品一区二区| 26uuu亚洲综合色欧美| 国内外成人免费激情视频| wwww国产精品欧美| 亚洲色图 在线视频| 亚洲免费观看高清完整版在线| 丁香花高清视频完整版在线观看| 亚洲综合色区另类av| 中文字幕在线免费观看| 在线日韩av片| 亚洲无线看天堂av| 亚洲欧美日本另类| 日韩一区二区三区精品| 午夜精品蜜臀一区二区三区免费| 日韩大尺度在线观看| 成人亲热视频网站| 亚洲免费激情| 色哺乳xxxxhd奶水米仓惠香| 久久久久久久久久久久久夜| 4480yy私人影院高清不卡| 欧美三区免费完整视频在线观看| 午夜在线激情影院| 中文字幕亚洲一区二区三区| 麻豆国产欧美一区二区三区r| 国产精品永久免费在线| 一本综合精品| 欧洲精品一区二区三区久久| 亚洲蜜臀av乱码久久精品蜜桃| 国产二区在线播放| 亚洲欧美国产日韩天堂区| 亚洲一区网址| 99国产在线观看| 国精产品一区一区三区mba桃花| 久久久亚洲精品无码| 亚洲一区二区黄色| 免费在线中文字幕| 久久久在线视频| 99视频精品免费观看| 精品无码一区二区三区在线| 五月婷婷久久综合| 日韩理论视频| 国产精品高清网站| 久久精品国产亚洲高清剧情介绍| 精品亚洲一区二区三区四区| 欧美日韩一区二区三区四区| 欧美91在线|欧美| 日韩av手机在线看| 日本aⅴ亚洲精品中文乱码| 搡女人真爽免费午夜网站| 在线视频观看一区| 亚洲精品66| 好吊色欧美一区二区三区四区 | 亚洲高清在线观看一区| 国产日韩欧美精品在线| 午夜免费视频在线国产| 欧美另类99xxxxx| 亚洲高清电影| 欧美成人黄色网址| 亚洲成人亚洲激情| 欧美日韩高清| 国产在线视频在线| 欧洲一区在线观看| 澳门成人av| 亚洲在线视频一区二区| 午夜精品成人在线| 91九色成人| 久久久久一区二区| 中文字幕综合网| 亚洲天堂一区二区| 精品国产一区二区三区日日嗨| 国产精品三级av| 老牛影视精品| 国产精品一区二区欧美黑人喷潮水| 久久久美女艺术照精彩视频福利播放| 国产超级va在线视频| 国产女同一区二区| 国产喷白浆一区二区三区| 动漫一区二区| 5g国产欧美日韩视频| 日韩毛片视频在线看| 成人mm视频在线观看| 日韩中文一区二区三区| 五月天国产精品| 青草久久视频| 欧美 日韩精品| 亚洲国产精品va在线观看黑人| 999国产精品| 亚欧美在线观看| 中文字幕av一区中文字幕天堂| 国产精品久久久久毛片大屁完整版 | 久久综合中文色婷婷| 一区二区理论电影在线观看| 色综合视频一区二区三区44| 亚洲黄色一区二区三区| 日韩欧美在线中文字幕| 网曝91综合精品门事件在线| 99爱视频在线| 国产香蕉97碰碰久久人人| 久热综合在线亚洲精品| jizz亚洲| 999视频在线观看| 精品久久久久久久中文字幕| 日韩有码av| 成年人在线免费观看视频网站| 91精品国产色综合久久不卡蜜臀| 日本wwwcom| 亚洲天堂网站在线观看视频| 欧美精品乱码久久久久久按摩| 亚洲最新av网址| 久久九九亚洲综合| 欧美日本韩国一区二区三区| 日韩免费在线看| 国产激情久久久| 欧美四级电影在线观看| 欧美性感美女h网站在线观看免费| 国产精品一区二区三区四区| 岛国精品在线观看| 一区二区在线视频观看| 9色在线观看| yellow91字幕网在线| 精品精品国产毛片在线看| 9999热视频在线观看| 日本天堂在线观看| 中文字幕色婷婷在线视频| 91精品一区二区三区四区| 欧美图片激情小说| 久久久免费视频网站| 日本福利片在线| 中文字幕大看焦在线看| 国产午夜精品久久久久免费视| 免费一区二区三区在线视频| 精品成人av| 欧洲亚洲精品| 中文在线免费二区三区| 成人视屏在线观看| vam成人资源在线观看| 日韩精品一区二区三区中文| 9色在线视频网站| 亚洲欧洲动漫| 在线h片观看| 国产精品xxx在线观看| 99国内精品久久久久| 欧美乱大交xxxxx潮喷l头像| 国产欧美高清在线| 在线黄色网页| 青草综合视频| 欧美片网站免费| 国产一区二区精品调教| 在线精品国产| 国产成人午夜精品影院观看视频| 高清毛片在线观看| 国产亚洲一区在线播放| 精品福利一区二区三区| 国产成人精品aa毛片| 国产精品22p| 一级片在线免费看| 日韩欧美精品在线不卡| 日韩视频中文字幕| 亚洲一区二区三区三| 国产日本精品| 亚洲精品第一| 美女做暖暖视频免费在线观看全部网址91 | 日韩手机在线| 青青草视频免费在线观看| 做爰高潮hd色即是空| 国产+人+亚洲| 欧美性受xxxx黑人xyx| 国产成人综合在线| 国产va免费精品观看精品视频| 免费在线视频欧美| 欧美日韩一区二区在线免费观看| 国产精品成人免费电影| 日韩一级二级三级| 中文在线一区二区 | 久久久久国产一区二区三区四区 | 91大神福利视频在线| 91.麻豆视频| 欧美国产精品一区二区三区| 亚洲欧美高清| 成人黄色小视频| 日韩av免费| 国产精品剧情|