瀏覽器渲染引擎
主要模塊
- 一個渲染引擎主要包括:HTML解析器,CSS解析器,javascript引擎,佈局layout模塊,繪圖模塊
- HTML解析器:解釋HTML文檔的解析器,主要作用是將HTML文本解釋成DOM樹。
- CSS解析器:級聯樣式表的解析器,它的作用是爲DOM中的各個元素對象計算出樣式信息,爲佈局提供基礎設施
- Javascript引擎:使用Javascript代碼可以修改網頁的內容,也能修改css的信息,javascript引擎能夠解釋javascript代碼,並通過DOM接口和CSSOM接口來修改網頁內容和樣式信息,從而改變渲染的結果。
- 佈局(layout):在DOM創建之後,Webkit需要將其中的元素對象同樣式信息結合起來,計算他們的大小位置等佈局信息,形成一個能表達這所有信息的內部表示模型
- 繪圖模塊(paint):使用圖形庫將佈局計算後的各個網頁的節點繪製成圖像結果
以上這些模塊依賴很多其他的基礎模塊,包括要使用到網絡 存儲 2D/3D圖像 音頻視頻解碼器 和 圖片解碼器。
所以渲染引擎中還會包括如何使用這些依賴模塊的部分。
渲染過程
-
瀏覽器渲染頁面的整個過程:瀏覽器會從上到下解析文檔。
-
遇見 HTML 標記,調用HTML解析器解析爲對應的 token (一個token就是一個標籤文本的序列化)並構建 DOM 樹(就是一塊內存,保存着tokens,建立它們之間的關係)。
-
遇見 style/link 標記 調用css解析器 處理 CSS 標記並構建 CSSOM 樹。
-
遇見 script 標記 調用 javascript解析器 處理script標記,綁定事件、修改DOM樹/CSSOM樹 等
-
將 DOM 與 CSSOM 合併成一個渲染樹。
-
根據渲染樹來佈局,以計算每個節點的幾何信息。
-
將各個節點繪製到屏幕上。
需要明白,這五個步驟並不一定按順序執行完成。如果 DOM 或 CSSOM 被修改,以上過程需要重複執行,這樣才能計算出哪些像素需要在屏幕上進行重新渲染。
實際頁面中,CSS 與 JavaScript 往往會多次修改 DOM 和 CSSOM -
阻塞渲染
- css阻塞
- css 在head中引入會阻塞頁面的渲染
爲什麼?
避免閃屏現象 - css 阻塞js的執行,不阻塞js等其他資源的加載
- css 在head中引入會阻塞頁面的渲染
- js阻塞
- 直接引入的js會阻塞頁面的渲染
爲什麼?
Javascript代碼可能會修改DOM樹的結構 - js順序執行,阻塞後續js邏輯的執行,不阻塞js等其他資源的加載
爲什麼?
維護依賴關係 - 預解析
WebKit 和 Firefox 都進行了這項優化。在執行js腳本時,其他線程會解析文檔的其餘部分,
找出並加載需要通過網絡加載的其他資源。通過這種方式,資源可以在並行連接上加載,
從而提高總體速度。請注意,預解析器不會修改 DOM 樹,而是將這項工作交由主解析器處理;
預解析器只會解析外部資源(例如外部腳本、樣式表和圖片)的引用。
- 直接引入的js會阻塞頁面的渲染
在上述的過程中,網頁在加載和渲染過程中會發出“DOMContentloaded”和“onload”事件
分別在DOM樹構建完成之後,以及DOM樹構建完並且網頁所依賴的資源都加載完之後發生、
因爲某些資源的加載並不會阻礙DOM樹的創建,所以這兩個事假多數是不同時發生的 - css阻塞
-
-
從DOM樹到可視化圖像
- CSS文件被CSS解析器解釋成內部表示結構(CSSDOM)
- CSS解析器工作完成之後,在DOM樹上附加解釋後的樣式信息,這就是RenderObject樹
- RenderObject在創建的同時,Webkit會根據網頁的結構創建RenderLayer,同時構建一個繪圖上下文
- 根據繪圖上下文生成最終的圖像(這一過程需要依賴圖形庫)
-
上面介紹的是一個完整的渲染過程,但現代網頁很多都是動態的,這意味着在渲染完成之後,由於網頁的動畫或者用戶的交互,
瀏覽器其實一直在不停地重複執行渲染過程。(重繪重排),以上的數字表示的是基本順序,這不是嚴格一致的,
這個過程可能重複也可能交叉