瀏覽器渲染邏輯和重繪、迴流解析

瀏覽器從輸入url 到 渲染出界面 中間經歷的過程

1 DNS 查詢

2 TCP 連接

3 HTTP 請求即響應

4 服務器響應

5 客戶端渲染

瀏覽器是如何渲染UI的?(客戶端的渲染)

1 瀏覽器接收到 html 和 css 文件 ,並對html進行解析,生成 DOM 樹 (遇到link,script 會造成阻塞)

2 同時對css進行解析,生成 CSSOM 樹

3 將DOM樹 和 CSSOM樹 合成 Render 樹(渲染樹)

4 根據渲染樹來佈局,以計算每個節點的幾何信息。(定位座標和大小,是否換行,各種position, overflow, z-index屬性)

5 調用GPU進行繪圖,遍歷render tree的每個節點,將元素顯示到屏幕上

css的加載和解析不會阻塞html文檔的解析
css的解析會阻塞js的執行,必須等到CSSOM生成後才能執行js
js的執行會阻塞html文檔的解析
html一邊解析一邊顯示
css必須完全解析完畢才能進入生成渲染樹環節

重繪

Repaint——屏幕的一部分要重畫,比如某個CSS的背景色變了。但是元素的幾何尺寸沒有變。

迴流、重排

Reflow——意味着元件的幾何尺寸變了,我們需要重新驗證並計算Render Tree。是Render Tree的一部分或全部發生了變化。這就是Reflow,或是Layout。(HTML使用的是flow based layout,也就是流式佈局,所以,如果某元件的幾何尺寸發生了變化,需要重新佈局,也就叫reflow)reflow 會從這個root frame開始遞歸往下,依次計算所有的結點幾何尺寸和位置,在reflow過程中,可能會增加一些frame,比如一個文本字符串必需被包裝起來。

迴流的原因:
1 Initial。網頁初始化的時候。

2 Incremental。一些Javascript在操作DOM Tree時。

3 Resize。其些元件的尺寸變了。

4 StyleChange。如果CSS的屬性發生變化了。

5 Dirty。幾個Incremental的reflow發生在同一個frame的子樹上。

注: 一般來說,瀏覽器會把這樣的操作積攢一批,然後做一次reflow,這又叫異步reflow或增量異步reflow。但是有些情況瀏覽器是不會這麼做的,比如:resize窗口,改變了頁面默認的字體,等。對於這些操作,瀏覽器會馬上進行reflow。

link 標籤會阻塞html的解析
script 標籤會阻塞html的解析
由於 DOM樹和CSSOM才能生出渲染樹,所以 css越早提供越好,一般推薦link標籤寫到head中,script 標籤寫到文檔底部
script標籤異步加載 defer 、 async屬性,不會影響DOM樹的構建

阻塞問題
script標籤會阻塞DOM樹的構建
CSSOM 的構建會阻塞 script標籤中js的執行 (假如瀏覽器發現js中)

defer
<script src="app1.js" defer></script>
<script src="app2.js" defer></script>
<script src="app3.js" defer></script>

defer 屬性表示延遲執行引入的 JavaScript,即這段 JavaScript 加載時 HTML 並未停止解析,這兩個過程是並行的。整個 document 解析完畢且 defer-script 也加載完成之後(這兩件事情的順序無關),會執行所有由 defer-script 加載的 JavaScript 代碼,然後觸發 DOMContentLoaded 事件。

defer 不會改變 script 中代碼的執行順序,示例代碼會按照 1、2、3 的順序執行。所以,defer 與相比普通 script,有兩點區別:載入 JavaScript 文件時不阻塞 HTML 的解析,執行階段被放到 HTML 標籤解析完成之後。

async
<script src="app.js" async></script>
<script src="ad.js" async></script>
<script src="statistics.js" async></script>

async 屬性表示異步執行引入的 JavaScript,與 defer 的區別在於,如果已經加載好,就會開始執行——無論此刻是 HTML 解析階段還是 DOMContentLoaded 觸發之後。需要注意的是,這種方式加載的 JavaScript 依然會阻塞 load 事件。換句話說,async-script 可能在 DOMContentLoaded 觸發之前或之後執行,但一定在 load 觸發之前執行。

從上一段也能推出,多個 async-script 的執行順序是不確定的。值得注意的是,向 document 動態添加 script 標籤時,async 屬性默認是 true

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章