瀏覽器解析過程


一:瀏覽器高層結構

1.1:瀏覽器結構圖

  • 1:user interface :瀏覽器交互界面
  • 2:browser engine:瀏覽器引擎:接收用戶界面指令傳給解析引擎
  • 3:render engine:呈現引擎:負責顯示請求的內容。如果請求的內容是 HTML,它就負責解析 HTML和 CSS 內容,並將解析后的內容顯示在屏幕上
  • 4:network:網絡,傳輸網絡資源
  • 5:js :javascript interprete js解析器
  • 6:ui backend:用於繪制基本的窗口小部件
  • 7:database :數據存儲引擎

1.2:瀏覽器render引擎

firefox是以gekco引擎,chrome和safari是以webkit引擎 

二:瀏覽器渲染頁面到屏幕上的主流程

2.1:兩種引擎的渲染過程很相似,本文以webkit為例,過程如下:

2.2:如何在瀏覽器中查看上面的過程呢?

結合 chrome的timeline,可以看到網頁解析的過程如下: 

  • 1:receive response,receive data:接收請求返回資源
  • 2:parse html:html dom節點的解析
  • 3:recalculate style :生成渲染樹(渲染樹與dom樹不同的地方在於,dom樹會把所有的dom節點都展示出來,渲染樹只會展示display非none的元素)
  • 4:layout :將渲染樹上的節點,根據它的高度,寬度,位置,為節點生成盒子(layout)。
  • 5:paint:確定渲染樹上的節點的大小和位置后,便可以對節點進行塗鴉(paint)
  • 6:composite layer:合成層;當渲染樹上的節點塗鴉完畢后,便生成位圖(bitmap),瀏覽器把此位圖從CPU傳輸到GPU

跟css相關的部分從layout開始,經過paint,最終再composite layer 生成位圖。

三:影響渲染過程的css屬性

3.1 layout:布局

影響layout布局的css屬性如圖

  • 1:盒子盒模型,所以跟盒模型相關的屬性的修改都會觸發layout
  • 2:位置(postition,float)相關
  • 3:跟獲取client的屬性:clientHeight,clientWidth,clientTop,clientLeft
  • 4:跟獲取offset的屬性:offsetHeight,offsetWidth,offsetTop,offsetLeft
  • 5:跟獲取scroll的屬性:scrollHeight,scrollWidth,scrollTop,scrollLeft

3.2 paint步驟:繪制

3.2.1 paint

paint顧名思義,塗鴉,繪制,所以跟color(fontcolor,background-color)相關 打開chrome的開發者工具,按下“esc”,會彈出如下界面

  • 勾選show paint rectangles選項
  • 可以看到頁面上繪制區域。

3.2.2 主要有2大類交互可觸發paint

  • 1、頁面滾動(scroll,實際上跟layout有關系,layout的改變必定會觸發paint階段:即重繪)
  • 2、互動操作

    • 1).Dom節點被Javascript改變,導致Chrome重新計算頁面的layout。

      • 解析:dom節點增加,刪除,位置移動,展示與否等操作,會引起DOM樹變化(html parse階段)或 CSS 樹變化(dom + css render階段);
    • 2). 用戶交互/激活 CSS 偽類

      • 解析:如hover導致某些元素頁面樣式的變化。而若樣式中有跟paint階段相關的,則會觸發重繪
    • 3). 調整窗口大小 和 改變字體

      • 解析:窗口大小改變時,可看到綠色的重繪區域在變化,截圖如下:
    • 4). 內容變化

      • 簡單腦補(根據 W3C 的 HTML DOM 標准,HTML 文檔中的所有內容都是節點,dom節點中的文本成為文本節點)
      • 解析:比如用戶在input框中輸入文字,修改的是DOM結構,所以觸發的layout,paint和composite layer三個階段
    • 5). 計算 offsetWidth 和 offsetHeight 屬性

      • 解析:offsetxxx,scrollxxx,clientxxx跟元素的位置相關,所以首先觸發的是layout階段,再觸發paint,compostie layer。
    • 6). 增加或者移除樣式表

      • 解析:若修改的樣式表跟css盒模型相關的,會觸發layout階段,paint,composite layer隨即觸發。

3.3 composite layer: 合成圖層

3.3.1 如何創建layer

  • 1):3D 或透視變換(perspective transform) CSS 屬性
  • 2):使用加速視頻解碼的 
  • 3):擁有 3D (WebGL) 上下文或加速的 2D 上下文的 
  • 4):混合插件(如 Flash)
  • 5):對自己的 opacity 做 CSS 動畫或使用一個動畫 webkit 變換的元素
  • 6):擁有加速 CSS 過濾器的元素
  • 7):元素有一個包含復合層的后代節點(換句話說,就是一個元素擁有一個子元素,該子元素在自己的層里)
  • 8):元素有一個 z-index 較低且包含一個復合層的兄弟元素(換句話說就是該元素在復合層上面渲染)
  • 9):在webkit內核的瀏覽器中,如果有上述情況,則會創建一個獨立的layer。

3.3.2 拒絕layer泛濫

當對元素創建layer之后,會節省layout和paint階段,但是layer不能泛濫。 layer跟psd中圖層很像,我們知道在psd中圖層越多,psd圖片就會越大。 同理,layer越多,占用的內存就越多,當在內存有限的移動設備上(手機),過多的渲染帶來的開銷超過了它在性能上的改善,得不償失; 白白的給元素添加layer,一般通過* {-webkit-transform: translateZ(0);}為元素添加layer 但創建layer的原則:當且僅當需要的時候才為元素創建渲染層。

四:渲染三階段分別注意的事項

渲染分為三階段:layout,paint,composite layer,修改不同的css屬性會觸發不同的階段,觸發的階段越靠前,渲染的代價越高。

  • 1:盡量避免觸發layout(位置相關的可通過transform代替 top left),paint。 除寫css屬性外,讀取css的位置大小相關屬性會導致觸發layout階段,要分離讀寫,減少layout。
  • 2:應該盡量避免重繪,並且盡可能的使繪制區域最小,以提升頁面性能。 但是有些必須使用的樣式效果還是要用的,比如fixed等重要的是作為前端人員,能夠預估這些代碼所帶來的性能損耗及所造成的影響。
  • 3:避免組合觸發 比如滾動和hover效果,hover中若使用border-shadow,border-style修改,則會損耗較大的性能,有可能會觸發丟幀的現象。 改進辦法:在滾動時,增加計時器,可先把hover效果禁掉,滾動結束后再打開hover效果。

五:setTimeout/setInterval PK requestAniamtionFrame(rAF)

requestAnimationFrame是一個監聽幀的API,即每繪制完一幀后就執行一下requestAnimationFrame函數。

 //setTimeout/setInterval使用方法
var loop = setInterva(function(){
        if(){
            clearInterval(loop);
            loop = null;
        }else{
           //to do
        }
    }, 20);

rAF使用方法

var loop = function(){
        if(){
            // to do
            requestAnimationFrame(loop);//有沒有超簡單?
        }
    };

rAF何時執行下一幀即何時執行回調? rAF不是自己指定回調函數運行的時間,而是跟着瀏覽器內建的刷新頻率來執行回調,這當然就能達到瀏覽器所能實現動畫的最佳效果 rAF PK setTimeout/setInterval?

六:GPU硬件加速

6.1如何開啟GPU硬件加速

CSS的 animations, transforms 以及 transitions 不會自動開啟GPU加速, 而是由瀏覽器的緩慢的軟件渲染引擎來執行。

大部分的瀏覽器提供了觸發GPU加速的CSS規則, 瀏覽器檢測到頁面中某個DOM元素應用了這些CSS規則時就會開啟GPU硬件加速, 最顯著的css規則是元素的3D變換。 所以,網站上會看到某些節點有下面的似乎沒有用的屬性出現:

transformZ(0); transform3d(0,0,0) 不要小看這些屬性,他們可以讓擁有這個屬性的元素生成單獨的composite layer。 這樣,不管這個元素的大小,位置等變換,都不會觸發layout和paint階段,直接執行composite layers (合成圖層)階段,瀏覽器會把這個合成圖層layer當做位圖上傳到GPU。 GPU硬件加速后節省的時間:

  • 1:cpu進行layout,paint的時間;
  • 2:CPU向GPU傳輸位圖的時間

七:如何查看頁面中最耗性能的節點

打開chrome調試工具,再按esc鍵,出現以下界面

  • 1:show paint rectangle :顯示可繪制區域
  • 2:show composited layer borders:顯示layer
  • 3:show FPS borders:顯示一幀耗費的時間(60幀/秒是最優效果,即一幀16.6ms)
  • 4:enable continuous page repainting:使頁面持續重繪
  • 5:show potential scoll bottlenecks:(shows areas of the page that slow down scrolling)展示可能會減慢頁面滾動的區塊

  • 勾選4:enable continuous page repainting

  • 1):打開Elements面板,使用上下左右來切換選擇DOM,然后按下快捷鍵H來hide或者顯示元素,同時觀察每幀渲染時間。

  • 2):如何某個元素按下H鍵后,幀時間會突然下降,則說明這個元素中有比較耗時的css屬性,找到節點中css屬性。

  • 3):依次取消面板中的CSS樣式再觀察每幀渲染時間,找出影響元素渲染幀時間的css屬性。

  • 實踐:用上面的方法,找出這個頁面http://css3exp.com/moon/ 中最消耗性能的節點及樣式

答案:body:background wrap:box-shadow

八:參考資料:

瀏覽器引擎工作機制:http://www.cnblogs.com/luluping/archive/2013/04/05/3000461.html render樹與css:http://www.cnblogs.com/luluping/archive/2013/04/05/3000460.html 瀏覽器工作原理:http://www.html5rocks.com/zh/tutorials/internals/howbrowserswork/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM