咱們可能都知道瀏覽器含有一個渲染引擎,用來渲染窗口所展現的內容。默認狀況下,渲染引擎能夠顯示html、xml文檔及圖片,它也能夠藉助插件(一種瀏覽器擴展)顯示其餘類型數據,例如使用PDF閱讀器插件,用於顯示PDF格式。可是其具體的渲染原理和流程估計也有不少人都不知道或者不清楚吧。這些天研究了一下瀏覽器的渲染原理,有了些心得,在這裏跟你們分享一下,這裏只討論渲染引擎最主要的用途——顯示應用了CSS以後的html及圖片。html
渲染引擎簡介web
本文所討論的瀏覽器——Firefox、Chrome和Safari是基於兩種渲染引擎構建的,Firefox使用Geoko——Mozilla自主研發的渲染引擎,Safari和Chrome都使用webkit。後端
渲染主流程瀏覽器
渲染引擎首先經過網絡得到所請求文檔的內容,一般以8K分塊的方式完成。下面是渲染引擎在取得內容以後的基本流程:網絡
解析html以構建dom樹 -> 構建render樹 -> 佈局render樹 -> 繪製render樹數據結構
這裏先解釋一下幾個概念,方便你們理解:dom
DOM Tree:瀏覽器將HTML解析成樹形的數據結構。異步
CSS Rule Tree:瀏覽器將CSS解析成樹形的數據結構。佈局
Render Tree: DOM和CSSOM合併後生成Render Tree。字體
layout: 有了Render Tree,瀏覽器已經能知道網頁中有哪些節點、各個節點的CSS定義以及他們的從屬關係,從而去計算出每一個節點在屏幕中的位置。
painting: 按照算出來的規則,經過顯卡,把內容畫到屏幕上。
reflow(迴流):當瀏覽器發現某個部分發生了點變化影響了佈局,須要倒回去從新渲染,內行稱這個回退的過程叫 reflow。reflow 會從 <html> 這個 root frame 開始遞歸往下,依次計算全部的結點幾何尺寸和位置。reflow 幾乎是沒法避免的。如今界面上流行的一些效果,好比樹狀目錄的摺疊、展開(實質上是元素的顯 示與隱藏)等,都將引發瀏覽器的 reflow。鼠標滑過、點擊……只要這些行爲引發了頁面上某些元素的佔位面積、定位方式、邊距等屬性的變化,都會引發它內部、周圍甚至整個頁面的從新渲 染。一般咱們都沒法預估瀏覽器到底會 reflow 哪一部分的代碼,它們都彼此相互影響着。
repaint(重繪):改變某個元素的背景色、文字顏色、邊框顏色等等不影響它周圍或內部佈局的屬性時,屏幕的一部分要重畫,可是元素的幾何尺寸沒有變。
注意:(1)display:none 的節點不會被加入Render Tree,而visibility: hidden 則會,因此,若是某個節點最開始是不顯示的,設爲display:none是更優的。
(2)display:none 會觸發 reflow,而 visibility:hidden 只會觸發 repaint,由於沒有發現位置變化。
(3)有些狀況下,好比修改了元素的樣式,瀏覽器並不會馬上reflow 或 repaint 一次,而是會把這樣的操做積攢一批,而後作一次 reflow,這又叫異步 reflow 或增量異步 reflow。可是在有些狀況下,好比resize 窗口,改變了頁面默認的字體等。對於這些操做,瀏覽器會立刻進行 reflow。
來看看webkit的主要流程:
再來看看Geoko的主要流程:
Gecko 裏把格式化好的可視元素稱作「幀樹」(Frame tree)。每一個元素就是一個幀(frame)。 webkit 則使用」渲染樹」這個術語,渲染樹由」渲染對象」組成。webkit 裏使用」layout」表示元素的佈局,Gecko則稱爲」reflow」。Webkit使用」Attachment」來鏈接DOM節點與可視化信息以構建渲染樹。一個非語義上的小差異是Gecko在HTML與DOM樹之間有一個附加的層 ,稱做」content sink」,是建立DOM對象的工廠。
儘管Webkit與Gecko使用略微不一樣的術語,這個過程仍是基本相同的,以下:
1. 瀏覽器會將HTML解析成一個DOM樹,DOM 樹的構建過程是一個深度遍歷過程:當前節點的全部子節點都構建好後纔會去構建當前節點的下一個兄弟節點。
2. 將CSS解析成 CSS Rule Tree 。
3. 根據DOM樹和CSSOM來構造 Rendering Tree。注意:Rendering Tree 渲染樹並不等同於 DOM 樹,由於一些像Header或display:none的東西就不必放在渲染樹中了。
4. 有了Render Tree,瀏覽器已經能知道網頁中有哪些節點、各個節點的CSS定義以及他們的從屬關係。下一步操做稱之爲layout,顧名思義就是計算出每一個節點在屏幕中的位置。
5. 再下一步就是繪製,即遍歷render樹,並使用UI後端層繪製每一個節點。
注意:上述這個過程是逐步完成的,爲了更好的用戶體驗,渲染引擎將會盡量早的將內容呈現到屏幕上,並不會等到全部的html都解析完成以後再去構建和佈局render樹。它是解析完一部份內容就顯示一部份內容,同時,可能還在經過網絡下載其他內容。