1. 程式人生 > >chrome performance看瀏覽器渲染過程

chrome performance看瀏覽器渲染過程

1. 瀏覽器渲染的過程

最近一直想看看瀏覽器渲染以及前端效能優化的內容,可是在網上找到的都是文字描述,所以想通過網上的知識去對應到chrome performance看到的過程。

先看一個非常簡單的頁面程式碼(或者訪問DOM-empty):

<!Doctye html>
<html>
<head>
</head>
<body>
  <div> 
    Test dom load.
  </div>
</body>
</html>

然後開啟chrome performence檢視頁面的渲染過程:


Send Request                傳送網路請求時觸發
Receive Response          響應頭報文到達時觸發
Receive Data                 請求的響應資料到達事件,如果響應資料很大(拆包),可能會多次觸發該事件
Finish Loading              網路請求完畢事件
Parse HTML                  瀏覽器執行HTML解析
Update Layer Tree        (目前還沒有找到具體的說明,後面會繼續去查詢,如果有了解的希望可以告知)。
Paint                              確定渲染樹上的節點的大小和位置後,便可以對節點進行塗鴉(paint)
Composite Layers          合成層;當渲染樹上的節點塗鴉完畢後,便生成點陣圖(bitmap),瀏覽器把此點陣圖從CPU傳輸到GPU

2. Parse Html(without css and js)

今天主要是為了看一下Parse Html的過程,現在講Parse Html的過程放大來看:


然後我們按照時間線從左到右來看一下里面的事情(先說一下,這個圖怎麼看,下面的內容是上面內容的呼叫,這裡也就是上面帶圖中帶有文字說明的內容都是在ParseHtml的週期內呼叫的內容):

readystatechange(第一個)

說這個的時候就需要說一個事件DOM readystatechange, readyState 屬性描述了文件的載入狀態,在整個載入過程中 document.readyState會不斷變化,每次變化都會觸發readystatechange事件。(可以訪問檢視

例子

readyState 有以下狀態:
  loading 載入document 仍在載入。
  interactive 互動文件已經完成載入,文件已被解析,但是諸如影象,樣式表和框架之類的子資源仍在載入。
  complete 完成DOM文件和所有子資源已完成載入。狀態表示 load 事件即將被觸發。

那麼這裡的事件執行的是哪一步呢?

這裡執行的是interactive。因為這個事件後面緊跟著的是 DOMContentLoaded事件,而且如果你親自訪問這個頁面去看一下,在parseHtml前面還有一次readystatechange,那裡應該是loading 。

DOMContentLoaded (構建 DOM 樹成功)

DOM樹渲染完成時觸發DOMContentLoaded事件,此時可能外部資源還在載入。這裡表示DOM樹載入完成。

Recalculate Style(構建 CSSOM 樹)

從文字的字面意義理解也就是重新計算樣式。為什麼是 Re-caculate Style 呢?這是因為瀏覽器本身有 User Agent StyleSheet,所以最終的樣式是我們的樣式程式碼樣式與使用者代理預設樣式覆蓋/重新計算得到的。這裡也是在構建CSSOM樹。

readystatechange(第二個)

從第一個事件的地方可有了解到這裡執行的是complete,表示頁面上的DOM樹和CSSOM樹已經形成並且合併成Render樹。此時頁面上所有的資源都已經載入完成。其實從後面的load事件也可以看出來。

load事件

所有的資源全部載入完成會觸發window 的 load事件。

pageshow事件

當一條會話歷史記錄被執行的時候將會觸發頁面顯示(pageshow)事件。(這包括了後退/前進按鈕操作,同時也會在load事件觸發後初始化頁面時觸發)。

以下示例將會在控制檯列印由前進/後退按鈕以及load事件觸發後引起的pageshow事件:

window.addEventListener('pageshow', function(event) {
    console.log('pageshow:');
    console.log(event);
});

Layout

將渲染樹上的節點,根據它的高度,寬度,位置,為節點生成盒子(layout)。為元素新增盒子模型。上圖中有兩個layout,二者之間的不同是Nodes That Need Layout  1/5 of 5這裡的5代表應該是頁面上的5個node(文字內容是文字節點),但是對於這個1,還是沒有一個明確的說明,但是影響不大,畢竟還是屬於layout。

其實看到這裡:我們想一下ParseHtml做了哪些內容:

構建DOM樹 -> 構建CSSOM樹 -> 構建Render樹 -> 佈局layout

Note: 這裡執行的情況是這樣的,但是當我們加上內部css和內部js的時候這個步驟就有了不一樣的變化。

3. Parse Html(with css and js)

<!Doctye html>
<html>
<head>
  <style type="text/css">
    .div {
      color: blue
    }
  </style>
</head>
<body>
  <div class='div'> 
    Test dom load.
  </div>
  <script type="text/javascript">
    var a = 1 + 1;
  </script>
</body>
</html>
然後以同樣的方式將chorme performence的過程貼出來:


這裡就只說和上面圖中不一樣的地方:

首先是多個兩個黃顏色的js相關的內容,一個叫做Evaluate Script(載入js),另一個是Compile Script(js預編譯處理,可以檢視文章,這裡也已經對js檔案執行了)。

第二個不同的地方是從第二個readystatechange事件起一直到layout都已經不在ParseHtml內部完成了。這裡我簡單的去做了一個測試,只有css或者js存在的情況下,還是和現在一樣的結果,這裡我假設是因為css或者js阻塞了整個頁面的渲染過程,因為js和css都有可能對標籤進行樣式的設定,從而影響了layout的執行。當然這只是我的一個問題,後面我會帶著這個問題繼續學習!

那麼現在ParseHtml就執行了:構建DOM樹 -> 構建CSSOM樹 -> 構建Render樹。

寫在最後:至於說DOM/CSSOM/Render樹是如何的構建,在網上有很多的文章再說,更有How browsers work,可以進行學習。至於paint, Composite Layers其實和前端頁面的渲染有著很大的關係,後面會有文章去學習。