1. 程式人生 > >首屏、白屏時間如何計算

首屏、白屏時間如何計算

取數 生存 解析 文檔加載 sts 請求 操作 star navig

“聞之我也野, 視之我也饒, 行之我也明” —- 前段時間感覺自己看的書比較多, 其中關於性能優化方面, 雖然知道一些 對於 web 頁面的性能優化手段, 像雅虎性能十四條這樣的業界金規玉律, 但是對於其中為什麽這樣做以及什麽時候這樣 做腦海始終有點模糊, 所以寫篇博文來讓自己理解性能方面的知識. 為什麽要監測性能因為在開發中, 性能是非常重要的部分, 我們在開發中可以不需要理會太多的性能問題, 正如那句老話: “不要過早地考 慮性能問題”, 但是在生產環境, 面對成百上千的 pv 量, 如何提高用戶體驗如何加快頁面內容加載速度對於一個產品來 說非常重要, 一句話說: 性能既是金錢. 當然, 我們也已經有了很多工具來測試頁面的性能, 個人比較常用的是 webpagetest, yslow 等等這些, 但是這些工具 測量的指標都比較單一而且測試環境比較單一, 如果我們需要比較詳細的性能測量報告就無法做到了, 因為用戶所用的 網絡環境實在是非常復雜. 所以我們會建立性能監測系統通過上報的數據分析出頁面的真實整體性能是如何的.確定測量目標在開始測量之前, 我們需要知道, 我們要測量什麽時間, 不然根本無法下手.性能指標白屏時間首屏時間用戶可操作時間資源總下載時間DNS 解析時間TCP 鏈接時間HTTP 請求時間HTTP 響應時間CSS 渲染時間Javascript 執行時間以上這些指標對於我們性能優化都非常有用.我們需要關註這些指標.測量工具準備W3C 性能小組提供了三個 API 供我們獲取頁面的詳細性能信息.Navigation Timing APIperformance.timing 返回的是一個對象, 包含了頁面加載的所有信息. 這裏不再細講每個字段的值的含義, 下面添加一個個人畫的圖幫助大家理解.Resource Timing APIperformance.getEntries() 返回的是數組, 每一個元素就是一個對象, 包含了每一個請求的靜態資源的加載信息. 註意這裏返回來的數組對象存儲的 Performance Resource 對象不僅僅是圖片, css, script 這種靜態資源, 還包括了像 XMLHttpRequest 對象這種.根據請求資源的原因, Reource timing 也會根據不同的原因進行記錄:如果有兩個相同 url img 圖片標簽, 那麽瀏覽器只會請求一次, 然後將記錄記錄到一個 resource object 中.如果 img src 屬性被 script 改變, 那麽 img 前後兩個請求都會被記錄到 resource object 中.當然如果 src 屬性是 base64 格式的值, 則不會被記錄到 resource object 中.如果一個資源請求因為網絡中斷或者另外諸如 DNS 查詢失敗, TCP 握手失敗, TLS 握手失敗, 那麽請求時間也會被記錄到 resourcce object 中, 只是時間值會被記錄成之前步驟所用時間, 例如 TCP 握手失敗會記錄 DNS 查詢時間如果一個資源因為資源位置丟失或者跨域失敗那麽將不會被記錄到 resource timging 中.下面是自己畫得一個圖:(PS:字比較醜不要見怪),建議大家可以也畫一下,可能會幫助理解. Performance API也即是 window.performance 接口, 提供精細的接口供我們知道網頁加載的詳細信息. memory : 用於監測網頁使用的內存情況, 如果 usedJSHeapSize

大於 totalJSHeapSize就會可能存在內存泄漏.navigation: 保存了網頁文檔加載的類型, TYPE_RELOAD, TYPE_BACK_FORWARD, TYPE_NAVIGATE 這些文檔加載類型, redirectionCount 只能記錄同源重定向的次數.timing: 記錄了頁面加載各個步驟的詳細時間.之前在面試的時候也有做過類似的一道題,就是計算打開一個頁面的時間, 計算時間就可以使用上面這三個 API 進行計算計算指標其中有兩個可以幫助我們檢測真實用戶環境下的頁面加載 Timing 和頁面資源加載 Timing : Navigation Timing 和 Resource Timing。 這兩個API非常有用,可以幫助我們獲取頁面的Domready時間、onload時間、白屏時間等,以及單個頁面資源在從發送請求到獲取到rsponse各階段的性能參數。 按照文檔上面所說的, 在 window 對象構建出來之前, 該 Navigation timing 與 Resource timing 都不可用.因此, 使用這兩個API時需要在頁面完全加載完成之後才能使用,最簡單的辦法是在window.onload事件中讀取各種數據,因為很多值必須在頁面完全加載之後才能得出。Navigation TimingNavigation Timing API 能夠幫助網站開發者檢測真實用戶數據(RUM),例如帶寬、延遲或主頁的整體頁面加載時間。用法如下: var timinhObj = performance.timing;
一般來說,我們需要獲取到的頁面性能參數包括:DNS查詢耗時、TCP鏈接耗時、request請求耗時、解析dom樹耗時、白屏時間、domready時間、onload時間等,而這些參數是通過上面的 performance.timing 各個屬性的差值組成的. DNS 查詢時間: domainlookupEnd - domainlookupstartTCP 鏈接時間: connectEnd - connectStart請求時間: requestEnd - requestStart響應時間: responseEnd - responseStartDOM 解析時間: domloadedEventEnd - navigationStart白屏時間: responseStart - navigationStart首屏時間: loadEventEnd - navigationStart
Resource Timing API如果要獲取個別資源(例如JS、圖片)的性能指標,就需要使用 Resource Timing.瀏覽器獲取網頁時,會對網頁中每一個靜態資源(腳本文件、樣式表、圖片文件等等)發出一個HTTP請求。 Resource Timing 可以獲取到單個靜態資源從開始發出請求到獲取響應之間各個階段的Timing。用法如下: var resourcesObj = performance.getEntries();附錄什麽是直出直出也就是數據直出, 為什麽會有這個概念呢? 其實還是為了優化頁面性能, 前後端分離帶來了開發便利與效率,但是 也帶來了一些性能問題, 前後端分離在首屏的時候, 首屏需要的數據仍然需要 ajax 去獲取, 這時候需要 TCP 鏈接等等 的延遲,所以對於網絡不好的用戶等待的時間比較長, 所以有了使用 node 作為中間層作為數據直出加快頁面渲染.

1. 白屏時間

白屏時間指的是瀏覽器開始顯示內容的時間。因此我們只需要知道是瀏覽器開始顯示內容的時間點,即頁面白屏結束時間點即可獲取到頁面的白屏時間。

技術分享圖片

2. 計算白屏時間

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

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>白屏</title>
  <script type="text/javascript">
    // 不兼容performance.timing 的瀏覽器,如IE8
    window.pageStartTime = Date.now();
  </script>
  <!-- 頁面 CSS 資源 -->
  <link rel="stylesheet" href="common.css">
  <link rel="stylesheet" href="page.css">
  <script type="text/javascript">
    // 白屏時間結束點
    window.firstPaint = Date.now();
  </script>
</head>
<body>
  <!-- 頁面內容 -->
</body>
</html>

因此白屏時間則可以這樣計算出:

2.1. 可使用 Performance API 時

白屏時間 = firstPaint - performance.timing.navigationStart;

2.2. 不可使用 Performance API 時

白屏時間 = firstPaint - pageStartTime;

3. 首屏時間

首屏時間是指用戶打開網站開始,到瀏覽器首屏內容渲染完成的時間。對於用戶體驗來說,首屏時間是用戶對一個網站的重要體驗因素。通常一個網站,如果首屏時間在5秒以內是比較優秀的,10秒以內是可以接受的,10秒以上就不可容忍了。超過10秒的首屏時間用戶會選擇刷新頁面或立刻離開。

通常計算首屏的方法有

  • 首屏模塊標簽標記法
  • 統計首屏內加載最慢的圖片的時間
  • 自定義首屏內容計算法

3.1. 1、首屏模塊標簽標記法

首屏模塊標簽標記法,通常適用於首屏內容不需要通過拉取數據才能生存以及頁面不考慮圖片等資源加載的情況。我們會在 HTML 文檔中對應首屏內容的標簽結束位置,使用內聯的 JavaScript 代碼記錄當前時間戳。如下所示:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>首屏</title>
  <script type="text/javascript">
    window.pageStartTime = Date.now();
  </script>
  <link rel="stylesheet" href="common.css">
  <link rel="stylesheet" href="page.css">
</head>
<body>
  <!-- 首屏可見模塊1 -->
  <div class="module-1"></div>
  <!-- 首屏可見模塊2 -->
  <div class="module-2"></div>
  <script type="text/javascript">
    window.firstScreen = Date.now();
  </script>
  <!-- 首屏不可見模塊3 -->
  <div class="module-3"></div>
    <!-- 首屏不可見模塊4 -->
  <div class="module-4"></div>
</body>
</html>

此時首屏時間等於 firstScreen - performance.timing.navigationStart;

事實上首屏模塊標簽標記法 在業務中的情況比較少,大多數頁面都需要通過接口拉取數據才能完整展示,因此我們會使用 JavaScript 腳本來判斷首屏頁面內容加載情況。

3.2. 2、統計首屏內圖片完成加載的時間

通常我們首屏內容加載最慢的就是圖片資源,因此我們會把首屏內加載最慢的圖片的時間當做首屏的時間。

由於瀏覽器對每個頁面的 TCP 連接數有限制,使得並不是所有圖片都能立刻開始下載和顯示。因此我們在 DOM樹 構建完成後將會去遍歷首屏內的所有圖片標簽,並且監聽所有圖片標簽 onload 事件,最終遍歷圖片標簽的加載時間的最大值,並用這個最大值減去 navigationStart 即可獲得近似的首屏時間。

此時首屏時間等於 加載最慢的圖片的時間點 - performance.timing.navigationStart;

3.3. 3、自定義模塊內容計算法

由於統計首屏內圖片完成加載的時間比較復雜。因此我們在業務中通常會通過自定義模塊內容,來簡化計算首屏時間。如下面的做法:

  • 忽略圖片等資源加載情況,只考慮頁面主要 DOM
  • 只考慮首屏的主要模塊,而不是嚴格意義首屏線以上的所有內容

部分來源

https://zhangxiang958.github.io/2017/05/20/%E7%BB%86%E8%AF%B4%20window.performance/

首屏、白屏時間如何計算