理解瀏覽器對頁面的渲染過程

瀏覽器對頁面的渲染:

渲染過程

  1. 處理 HTML 標記並構建 DOM 樹。
  2. 處理 CSS 標記並構建 CSSOM 樹。
  3. 將 DOM 與 CSSOM 合併成一個渲染樹。
  4. 根據渲染樹來佈局,計算每一個節點的幾何信息。
  5. 將各個節點繪製到屏幕上。

但上述過程不必定會按順序執行下來, 可能會被阻塞。
假如 DOM CSSOM 被修改, 以上過程會重複執行瀏覽器

阻塞渲染

CSS阻塞

CSS HTML 都是阻塞頁面渲染的因素之一, 由於渲染樹須要同時具備 DOM 樹、 CSSOM樹, 才能開始構建
瀏覽器解析 HTML 時,遇到了 CSS 資源, 會並行解析和構建 CSSOM DOM
因此 CSS 不會阻塞 HTML 的解析, 可是會阻塞渲染樹的構建
因此須要儘量快地提供 CSS 樣式, 儘可能放在 head 標籤內。
可是: CSS 也會阻塞 JS 腳本的執行!!
有這麼一種狀況, CSS 解析不是不影響 HTML 解析嘛, CSS 解析過程當中, HTML 解析到一個 script 標籤, 這時會去加載這個腳本, 但加載完以後必須等到前面的 CSSOM 構建完成纔會執行async

JS阻塞

遇到 JS 腳本的時候, 會阻塞 HTML 解析, 立刻去加載腳本, 加載完後就執行佈局

改變 script 腳本阻塞模式的 defer async

頁面解析時, 遇到 script 腳本會阻塞 HTML 的解析, 立刻去加載腳本, 而且加載完後就立刻執行。
可是瀏覽器會提早偷看後面要下載的資源先進行預加載
defer async 能夠改變這種阻塞模式, 注意: defer async 對 inline-script 無效ip

defer

文檔按順序解析,遇到腳本時下載,下載過程當中文檔繼續解析文檔解析完成後開始執行下載好的腳本,腳本執行前後順序資源

async

文檔按順序解析,遇到腳本時下載,下載過程當中文檔繼續解析下載完成後中止 HTML 解析, 開始執行下載好的腳本,腳本執行前後順序文檔

小結一下

  1. CSS 不會阻塞 DOM 的解析, 但會阻塞 DOM 的渲染, 會阻塞 JS 的執行
  2. JS 會阻塞 DOM 的解析和渲染, 但瀏覽器會偷看後面要下載的資源進行加載, 能夠用 defer async 來避免阻塞。

最佳實踐 :

CSS 資源放在 head 標籤裏儘快加載, 避免阻塞渲染樹的構建, 也避免阻塞 JS 執行, 以及頁面樣式從無到忽然出現閃動。
JS 腳本用 defer async 避免堵塞。
對於不須要操做 DOM , 且互相不依賴 (即無所謂腳本前後執行順序) 的腳本, 用 async
對於須要操做 DOM, 且互相依賴 (在意腳本前後執行順序) 的腳本, 用 deferclass

番外: 普通的 script 標籤爲何要放在 body 底部?

爲了防止 JS 加載執行時阻塞 DOM 的解析, 形成白屏時間過長, 同時也有可能 script 腳本須要操做 DOM, 須要等到 DOM 解析好了才執行。渲染

相關文章
相關標籤/搜索