文檔對象模型(Document Object Model,簡稱DOM)javascript
瀏覽器渲染引擎css
解釋 HTML 文檔的解析器,將 HTML 文本 解析成 DOM 樹html
級聯樣式的解析器,爲 DOM 中的各個元素計算出樣式信息,爲佈局提升基礎設施java
使用 Javascript 代碼能夠修改網頁的內容,也能修改 css 的信息webpack
javascript 引擎可以解釋 javascript 代碼,並經過 DOM 接口和 CSSOM 接口來修改網頁內容和樣式信息,從而改變渲染的結果。web
在 DOM 建立以後,Webkit 須要將其中的元素對象一樣式信息結合起來,gulp
計算他們的大小位置等佈局信息,造成一個能表達這全部信息的內部表示模型瀏覽器
使用 圖形庫 將佈局計算後的各個網頁的節點 繪製成 圖像結果網絡
以上這些模塊依賴不少其餘的基礎模塊,包括要使用到網絡 存儲 2D/3D圖像 音頻視頻解碼器 和 圖片解碼器。異步
因此渲染引擎中還會包括如何使用這些依賴模塊的部分。
1. 碰見 HTML 標記
調用 HTML 解析器解析爲對應的 token (一個 token 就是一個標籤文本的序列化)
並構建 DOM 樹(就是一塊內存,保存着 tokens,創建它們之間的關係)
2. 碰見 style/link 標記 調用 css 解析器 處理 CSS 標記並構建 內部表示結構 CSSOM 樹
CSS 解析器工做完成以後,在 DOM 樹上附加解釋後的樣式信息,這就是 RenderObject 樹
RenderObject 在建立的同時,Webkit 會根據網頁的結構建立 RenderLayer,同時構建一個繪圖上下文
根據 繪圖上下文 生成最終的圖像(這一過程須要依賴圖形庫)
3. 碰見 script 標記 調用 javascript 解析器 處理 script 標記,綁定事件、修改 DOM 樹 / CSSOM樹 等
4. 將 DOM 樹 與 CSSOM 樹 再次合併成一個渲染樹 Render 樹
5. 根據 渲染樹 來佈局,以計算每一個節點的幾何信息____重排
6. 將各個節點繪製到屏幕上____重繪
但現代網頁不少都是動態的,這意味着在渲染完成以後,
因爲網頁的動畫或者用戶的交互,瀏覽器其實一直在不停地重複執行渲染過程。(重繪重排)
以上的數字表示的是基本順序,這不是嚴格一致的,這個過程可能重複也可能交叉
----> 分別在 DOM 樹解析完成後,觸發 "DOMContentLoaded"
----> DOM 樹構建而且網頁全部依賴資源都加載完成以後發生,觸發 "load"
瀏覽器加載資源是異步的
用 <style> 內部樣式表 寫 css,是由 Parse HTML 異步解析的。
一張圖片分屢次解析,其中 Parse HTML 這麼快,體現了其異步執行,只是開啓了一個任務,讓它本身去請求資源並解析
經過 link 進來的樣式 是同步解析的,由 Parse Stylesheet 進行解析
正由於是同步解析,因此 css 解析器 會阻塞頁面的渲染,從而避免了閃屏
這也是爲何推薦使用 <style link='index.css'> 引入外部樣式表
1. 由 html 解析器進行解析
2. 不阻塞瀏覽器渲染
3. 不阻塞 DOM 解析
1. 由 CSS 解析器進行解析
2. 會阻塞瀏覽器頁面渲染(緣由:避免閃屏)
<link rel="stylesheet" href="css/my-sleep-3000-commen.css" />
3. 不阻塞 DOM 結構的解析
由於 DOM 解析 和 CSS 解析是兩個並行的進程
瀏覽器解析 DOM 生成 DOM Tree,解析 CSS 生成 CSS Tree
最終組成 render Tree,再渲染頁面,DOM 的解析,和 CSS的解析並行的。
4. 會阻塞 js 的執行(但不會阻塞 js 等資源的加載)
腳本在文檔解析階段會請求樣式信息,若是 css 尚未徹底加載解析完,腳本可能得到錯誤的回覆
優化方案: (儘量快的提升 css 加載速度)
會阻塞 DOM 解析
由於 js 可能會修改 DOM 樹
會阻塞 頁面的渲染
由於 js 代碼可能會修改 DOM 樹 / CSSOM 樹 的結構
js 會順序執行,阻塞後續 js 邏輯的執行 (不阻塞 js 等其餘資源的加載)
維護依賴關係
css 的解析 和 js 的執行 是互斥的 ( css 解析的時候 js 中止執行,js 執行的時候 css 中止解析)
預解析
WebKit 和 FireFox 都進行了這項優化。
在執行 js 腳本時,其餘線程會解析文檔的其他部分 (只是檢查,不影響原結構),找出並加載須要網絡加載的其餘資源
使得這些資源在並行鏈接上加載,從而提升整體速度
預解析器 不會修改 DOM 樹,而是將這件事交給 主解析器 處理
預解析器 只會解析外部資源的引用(例如外部腳本、樣式、圖片)
提早發送請求,提早解析外部資源內容