前端性能的幾個基礎指標
先開門見山的羅列前端性能相關的幾個基礎指標名詞。
- 白屏時間
- 首屏時間
- 用戶可操作時間
- 頁面總下載時間
為何會選擇這幾個時間節點以及各自的含義可以參考這篇文章 七天打造前端性能監控系統
另外本文搜集性能相關數據是用了高級瀏覽器的Performance Api
,大家可以參考這篇文章先行了解初探erformancep
正文
上圖看了有和感受?當頁面刷新后可視區域長時間停留在白屏狀態,當一個階段后頁面突然全部刷出,而不是我們追崇的逐步加載顯示的狀態。
上圖顯示的是視口上部分已經展示,但是由於某種原因頁面下部分的視圖被阻塞,一段時間后,剩余頁面突然刷出,也不符合頁面逐步顯示的體驗。
上圖的現象是可交互的區域已經出現在視口中了,用戶也已經在可點擊的地方進行狂點,但是圖片資源沒有加載完可導致點擊事件沒有綁定,點擊無效。這種交互體驗也是不能容忍的。
上面幾個例子正好可以帶出兩個性能指標 白屏時間
和 用戶可操作時間
白屏時間: 用戶從打開頁面開始到有頁面開始呈現為止。
用戶可操作時間: 用戶可以進行正常的事件輸入交互操作。
接下來我們通過Performance Api
看看如何得到這兩個指標的數據。
http://www.w3.org/TR/navigati...
上圖來自官方,從左到右代表了瀏覽器打開一個頁面內部的一系列狀態。左邊紅線代表的是網絡傳輸層面的過程,這篇文章不過多講述,右邊紅線代表了服務器傳輸回字節后瀏覽器的各種事件狀態,也就是上圖中的responseEnd
之后。這個階段包含了瀏覽器對文檔的解析,dom樹構建,布局,繪制等等。下面詳細說明。
在瀏覽器console中輸入performance.timing
,返回的各字節跟上圖performance流程的各狀態一一對應,並返回時間。
上圖簡單說明了一下performance timing api
在幾個流程下所代表的含義。至於為何到達domInteractive
狀態時代表了Dom tree 構建完成
我在下文還會解釋到。
上圖演示了一個頁面加載時Chrome的調試工具中的Network
會顯示兩條豎線,一藍一紅,藍的代表document觸發了domContentLoaded
事件,紅線代表了document觸發了load
事件。
理一理
我們說到了當document到達domInteractive
狀態時代表了dom樹的構建完成
,也代表了可以綁定事件,即用戶可交互時間已經到達,也代表了觸發domContentLoaded
事件,也即代表Chrome調試中藍線的出現。
但這一連串因果又是從何得到的呢?
深剖why
上圖說明在瀏覽器拿到文檔首字節之后,即上文提到的responseEnd
之后。瀏覽器將html解析並構建成DOM tree,並同時將css解析成CSSOM。在沒有js的參與下,這個過程是同步的。
但一旦有js的參與,這個平衡就被破壞了。
- 同步的javascript可以改寫文檔在任何節點,因此DOMtree 一旦碰上script標簽(同步)就會停止構建。script也會阻塞img資源的下載。
- javascript能查詢dom對象的可被計算的樣式,CSSOM構建完才能輪到js的執行(僅位於script之前的css文件(內嵌、外鏈)才會阻塞js的執行,若樣式文件在script之后,則此樣式文件不會阻塞script)
由於上面兩個原因,導致html的解析構建與css構建成CSSOM有了依賴關系
然后我們看一下官方文檔
這里解釋了document到達interactive
狀態所代表的含義,我先將其中一塊信息隱藏。根據這個說明,當文檔解析完成但是,一些例如圖片這些資源還沒有加載完成的情況下,document到達interactive
狀態,並且觸發DOMContentLoaded
事件觸發。下面來看一個實例。
結合上面的深剖,CSSOM構建阻塞了js的執行,所以在這幅圖中js早已加載完,還是要等到css的下載完成才能執行,而js的被阻塞,又導致了html文檔的解析DOM樹的構建。再根據官方的說明,dom樹的構建完成才意味着interactive
到達,意味着藍線的出現。
但我們再看下官方說明的原話。
是的,剛剛被我遮蓋掉的是stylesheets
樣式表。這里又明確提到了不等stylesheets
樣式表下載完成,一旦html解析dom樹構建完document就立馬到達interactive
狀態。這不是跟我們剛剛的例子相反了嗎?
再看個例子
這個例子藍線停在了css文件下載完成之前,說明也驗證了后一種說法。那到底是哪個對?
答案當然是都對,我們在最之前就說明了,在沒有js參與的情況下,html的解析DOM樹的構建和CSSOM的構建是平行的,誰也不礙着誰,interactive
狀態的變更直接取決於html的解析完成度,所以在這種情況下,不等css加載完,html一旦解析完成,document狀態立馬變更為interactive
。第二個例子是沒有js引入的。
深剖小結
上述的引入的js只是同步的。也就是不帶defer 或 async的script標簽。一旦引入了帶defer或async的script標簽,js、css的依賴關系又變了。這里就不詳談了,可以看一篇外文Deciphering the Critical Rendering Path
或者我的翻譯版本我的翻譯
總結
現在我們再來看一下domContentLoaded
和load
事件。現在應該能清楚為何domContentLoaded
事件觸發代表了用戶可交互事件,以及
$(function () { })
jquery中的這個寫法就是基於這個事件。
最后,我們回頭看下開頭指出的衡量頁面性能的四個基礎指標,以及各自的求法。
- 白屏時間:除了可以使用現成的
performance api
,我們還可以在head之間頭尾插入兩個script計算時間差
<head> <script> var t = new Date().getTime(); </script> <link src=""> <link src=""> <link src=""> <script> tNow = new Date().getTime() - t; </script> </head>
這樣做可行的原理:第一個script不受css阻塞,最后的script受css阻塞,會等到樣式都下載完才執行,執行完后便是body
的解析,之后是dom tree構建,布局,繪制然后呈現在屏幕上。
- 用戶可交互時間:根據
performance api
在根據之前的講述,可得domContentLoadedEventEnd - navigationStart
參考:
performance api
關鍵路徑
performance api github
分析關鍵呈現路徑性能
初識performance
jscss順序
S 和 CSS 的位置對其他資源加載順序的影響
7 天打造前端性能監控系統
完!
轉自 https://segmentfault.com/a/1190000005784687