瀏覽器的運作原理
瀏覽器是一個用來瀏覽網頁的應用程式,它主要由以下幾個部分組成:
使用者介面
瀏覽器的使用者介面主要由以下幾個部分組成:
- 網址列:用來輸入網址,並且前往網頁。
- 前進、後退、重新整理、停止:用來控制瀏覽器的前進、後退、重新整理、停止。
- 分頁:用來顯示網頁的分頁。
- 瀏覽器視窗:用來顯示網頁的內容。
瀏覽器引擎
瀏覽器引擎主要負責解析 HTML、CSS 等資源,並且將這些資源顯示在瀏覽器視窗上。 常見的瀏覽器引擎有:
Blink:Google Chrome和Opera使用的瀏覽器引擎。WebKit:Safari使用的瀏覽器引擎。Gecko:Firefox使用的瀏覽器引擎。Trident:Internet Explorer使用的瀏覽器引擎。EdgeHTML:Microsoft Edge使用的瀏覽器引擎。
JavaScript 解析器
上一章我們提到,JavaScript 是直譯讓瀏覽器解析處理的,所以瀏覽器都內建了 JavaScript 解析器。 JavaScript 解析器主要負責解析 JavaScript 語言,並且將這些語言轉換成機器語言,讓電腦可以執行。 常見的 JavaScript 解析器有:
V8:Google Chrome使用的JavaScript解析器。SpiderMonkey:Firefox使用的JavaScript解析器。JavaScriptCore:Safari使用的JavaScript解析器。Chakra:Internet Explorer使用的JavaScript解析器。ChakraCore:Microsoft Edge使用的JavaScript解析器。
瀏覽器的渲染流程
解析 HTML:建立 DOM 樹
瀏覽器會先將 HTML 解析成 DOM 樹,DOM 樹是一個由節點組成的樹狀結構,每個節點代表了一個 HTML 元素。 比如說:
<!DOCTYPE html>
<html>
<head>
<title>Document</title>
</head>
<body>
<h1>Hello, World!</h1>
</body>
</html>解析後的 DOM 樹會長得像這樣:
html
├── head
│ └── title
│ └── Document
└── body
└── h1
└── Hello, World!解析 CSS,建立 CSSOM 樹
瀏覽器會將 CSS 解析成 CSSOM 樹,CSSOM 樹是一個由節點組成的樹狀結構,每個節點代表了一個 CSS 規則。 比如說:
h1 {
color: red;
}解析後的 CSSOM 樹會長得像這樣:
h1
└── color: red接著符合 CSSOM 節點上規則的元素會被標記為 style 屬性,這樣瀏覽器引擎就可以知道該元素的樣式。
合併 DOM 和 CSSOM:瀏覽器引擎會將 DOM 和 CSSOM 合併成一個 Render Tree
瀏覽器引擎會將 DOM 和 CSSOM 合併成一個 Render Tree,是一個由節點組成的樹狀結構,每個節點代表了一個可見的元素。 比如說:
html
└── body
└── h1 (color: red)
└── Hello, World!布局 (Layout/Reflow)
瀏覽器引擎會計算 Render Tree 的大小和位置,並且決定每個元素在畫面上的位置。 比如說:
// 預設情況下
html (width: 100%, height: 100%)
└── body (width: 100%, height: 100%)
└── h1 (color: red) (width: 100%, height: 100%, font-size: 16px, line-height: 1.2, color: black, background: transparent)
└── Hello, World! (width: 100%, height: 100%, font-size: 16px, line-height: 1.2, color: black, background: transparent)繪製 (Paint)
瀏覽器引擎會將 Render Tree 繪製到畫面上,但這還不是最終的畫面,因為接下來要開始執行 JavaScript。
執行 JavaScript
瀏覽器引擎會解析 JavaScript,並且執行 JavaScript,這可能會導致 Render Tree 的變化。
比如說,我們將 h1 的顏色改成藍色:
document.querySelector('h1').style.color = 'blue';這樣 Render Tree 就會變成:
html
└── body
└── h1 (color: blue)
└── Hello, World!然後由於 Render Tree 的變化,瀏覽器引擎會重新繪製和回流。
重繪和回流(Repaint and Reflow)
瀏覽器會監聽 Render Tree 的變化,當 Render Tree 發生變化時,瀏覽器引擎會重新繪製和回流,把畫面上的元素重新計算一次,然後重新繪製到畫面上。
瀏覽器的事件循環:瀏覽器會不斷的執行事件循環,並且處理事件
瀏覽器有一個事件循環機制,瀏覽器會不斷的執行事件循環。 假設有一個按鈕而且我們用滑鼠點了它一下,會產生一個 onClick 事件,這個事件就會被放到事件循環中,等待瀏覽器引擎執行。 假設這個按鈕綁定的事件是改變 h1 的顏色,那麼當事件循環執行到這個事件時,就會改變 h1 的元素,觸發重繪和回流。
結語
重繪跟回流是很重要的
根據以上的流程會發現,一開始瀏覽器會先解析 HTML、CSS,然後建立 DOM、CSSOM,接著合併成 Render Tree。
再經過布局、繪製完成最初的畫面,接著執行 JavaScript。
當 JavaScript 執行第一次時,可能會改變 DOM 導致 Render Tree 的變化,這時瀏覽器會重新繪製和回流。
而且 JavaScript 在綁定事件後,也可能會因為事件的觸發而去變更 DOM 導致 Render Tree 的變化,這時瀏覽器也會重新繪製和回流。
只要改變了 Render Tree,瀏覽器就會重新繪製和回流,這樣的過程會一直持續下去,直到網頁被關閉為止。
但是瀏覽器的繪製是需要時間、需要運算成本的,所以繪製與回流得越多,網頁的效能就會越差。
所以在使用 JavaScript 操作 DOM 時,如何減少繪製與回流就變得非常重要。
為了降低繪製與回流,Virtual DOM 誕生
後來就發展出了 Virtual DOM(即VDOM) 這個概念,透過用 JavaScript 去仿造一個 DOM,有點像是用 VDOM 預演一場戲,然後再去比對 VDOM 跟 DOM 的差異,最後再直接更新這些差異,減少 DOM 迭代的更新次數,進而提升效能。
使用 VDOM 技術來開發的框架有 React, Vue 等等,之後若有機會,會再詳細說明。
