網頁渲染必須在很早的階段進行,可以早到頁面布局剛剛定型。因為樣式和腳本都會對網頁渲染產生關鍵性的影響。所以專業開發者必須了解一些技巧,從而避免在實踐的過程中遇到性能問題。
Webkit渲染主要流程如下:
Mozilla的Gecko渲染引擎主要流程如下:
由圖可以發現,兩個引擎過程基本相同。主要有三個步驟:
1.解析。瀏覽器會解析HTML/SVG/XHTML,事實上,webkit有三個C++的類對應這三類文檔。瀏覽器解析這三種文件會產生一個DOM Tree;解析CSS,產生style rules;解析Javacript,主要通過DOM API和CSSOM API來操作DOM Tree和CSS Rule Tree
2.解析完成后,瀏覽器引擎會通過DOM Tree和CSS Rule Tree來構造Rendering Tree。
3.調用操作系統Native GUI的API繪制。
兩者的語義差別:
webkit把可視化好的可視元素成為Render Tree,用Layout來表示元素的布局
Gecko把可視化好的可視元素成為Frame Tree,每個元素就是一個frame,元素的布局成為Reflow
還有一個細小的差別差別在于:Gecko在HTML與DOM樹之間還多一個層content Sink,這是創建DOM對象的工廠。
1.解析 HTML 標簽, 構建 DOM 樹
一個是HTML/SVG/XHTML,事實上,Webkit有三個C++的類對應這三類文檔。解析這三種文件會產生一個DOM Tree。創建一棵由一組待生成渲染的對象組成的渲染樹(在Webkit中這些對象被稱為渲染器或渲染對象,而在Gecko中稱之為“frame”。)渲染樹反映了文檔對象模型的結構,但是不包含諸如<head>標簽或含有display:none屬性的不可見元素。在渲染樹中,每一段文本字符串都表現為獨立的渲染器。每一個渲染對象都包含與之對應的DOM對象,或者文本塊,還加上計算過的樣式。換言之,渲染樹是一個文檔對象模型的直觀展示。
2.解析 CSS 標簽, 構建 CSSOM 樹
解析CSS會產生CSS規則樹。
3.解析JavaScript,腳本
主要是通過DOM API和CSSOM API來操作DOM Tree和CSS Rule Tree.
4.把 DOM 和 CSSOM 組合成 渲染樹 (render tree)
Rendering Tree 渲染樹并不等同于DOM樹,因為一些像Header或display:none的東西就沒必要放在渲染樹中了。
CSS 的 Rule Tree主要是為了完成匹配并把CSS Rule附加上Rendering Tree上的每個Element。也就是DOM結點。也就是所謂的Frame。
5.在渲染樹的基礎上進行布局, 計算每個節點的幾何結構
6.把每個節點繪制到屏幕上 (painting)
Repaint重繪
當改變那些不會影響元素在網頁中的位置的元素樣式時,譬如background-color(背景色), border-color(邊框色), visibility(可見性),瀏覽器只會用新的樣式將元素重繪一次(這就是重繪,或者說重新構造樣式)。
Reflow重排
當改變影響到文本內容或結構,或者元素位置時,重排或者說重新布局就會發生。reflow 會從<html>這個root frame開始遞歸往下,依次計算所有的結點幾何尺寸和位置,在reflow過程中,可能會增加一些frame,比如一個文本字符串必需被包裝起來。這些改變通常由以下事件觸發:
- DOM操作(元素添加,刪除,修改,或者元素順序的改變);
- 容變化,包括表單域內的文本改變;
- CSS屬性的計算或改變;
- 添加或刪除樣式表;
- 更改“類”的屬性;
- 瀏覽器窗口的操作(縮放,滾動);
- 偽類激活(:懸停)。
注:display:none會觸發reflow,而visibility:hidden只會觸發repaint,因為沒有發現位置變化。
瀏覽器如何優化渲染
瀏覽器盡可能將重繪/重構 限制在被改變元素的區域內。比如,對于位置固定或絕對的元素,其大小改變只影響元素本身及其子元素,然而,靜態定位元素的大小改變會觸發后續所有元素的重流。
另一種優化技巧是,在運行幾段JavaScript代碼時,瀏覽器會緩存這些改變,在代碼運行完畢后再將這些改變經一次通過加以應用。