瀏覽器
瀏覽器基礎結構主要包括以下7部分:
1.用戶界面(User Interface):用戶所看到及與之交互的功能組件,如地址欄,返回,前進按鈕等;
2.瀏覽器引擎(Browser engine):負責控制和管理下一級的渲染引擎;
3.
渲染引擎(Rendering engine):負責解析用戶請求的內容(如HTML或XML,渲染引擎會解析HTML或XML,以及相關CSS,而後返回解析後的內容);
4.網絡(Networking):負責處理網絡相關的事務,如HTTP請求等;
5.UI後端(UI backend):負責繪製提示框等瀏覽器組件,其底層使用的是操做系統的用戶接口;
6.
JavaScript解釋器(JavaScript interpreter):負責解析和執行JavaScript代碼;
7.數據存儲(Data storage):負責持久存儲諸如cookie和緩存等應用數據。
瀏覽器內核
瀏覽器內核主要指的是瀏覽器的渲染引擎,各大主要瀏覽器使用內核也是有差異的,大體能夠分爲如下幾類:
- Trident內核: IE
- Webkit內核:Chrome,Safari
- Gecko內核:FireFox
關於移動端
移動端的瀏覽器內核主要說的是系統內置瀏覽器的內核。
目前移動設備瀏覽器上經常使用的內核有 Webkit,Blink,Trident,Gecko 等,其中 iPhone 和 iPad 等蘋果 iOS 平臺主要是 WebKit,Android 4.4 以前的 Android 系統瀏覽器內核是 WebKit,Android4.4 系統瀏覽器切換到了Chromium,內核是 Webkit 的分支 Blink,Windows Phone 8 系統瀏覽器內核是 Trident。
瀏覽器渲染過程

從圖可知:瀏覽器從上到下解析HTML文檔,碰到css樣式(若是爲外聯,則加載css樣式表),生成DOM節點樹
和解析樣式生成CSSOM樹是同時進行的。

圖解釋:css
1.構建DOM樹(DOM tree):從上到下解析HTML文檔生成DOM節點樹(DOM tree),也叫內容樹(content tree);
2.構建CSSOM(CSS Object Model)樹:加載解析樣式生成CSSOM樹;
3.執行JavaScript:加載並執行JavaScript代碼(包括內聯代碼或外聯JavaScript文件);
4.構建渲染樹(render tree):根據DOM樹和CSSOM樹,生成渲染樹(render tree);渲染樹:按順序展現在屏幕上的一系列矩形,這些矩形帶有字體,顏色和尺寸等視覺屬性。
5.佈局(layout):根據渲染樹將節點樹的每個節點佈局在屏幕上的正確位置;
6.繪製(painting):遍歷渲染樹繪製全部節點,爲每個節點適用對應的樣式,這一過程是經過UI後端模塊完成;
七、合成(composite):在layout和painting以後,瀏覽器會將多個複合層傳入GPU,進行合成工做
爲了更友好的用戶體驗,瀏覽器會盡量快的展示內容,而不會等到文檔全部內容到達纔開始解析和構建/佈局渲染樹,而是每次處理一部分,並展示在屏幕上,這也是爲何咱們常常能夠看到頁面加載的時候內容是從上到下一點一點展示的。
5,6兩點過程當中,若是 DOM 或 CSSOM 被修改,以上過程須要重複執行,這樣才能計算出哪些像素須要在屏幕上進行從新渲染(致使重繪和迴流)。
阻塞渲染:CSS 與 JavaScript
css如何阻塞渲染的?html
碰到 CSS 資源,瀏覽器會優先CSSOM 構建,JavaScript 執行將暫停,直至 CSSOM 就緒。因此引入順序上,CSS 資源先於 JavaScript 資源。
渲染樹的構建要求同時具備 DOM 和 CSSOM。即HTML 和 CSS 都是阻塞渲染的資源。HTML 顯然是必需的,由於包括咱們但願顯示的文本在內的內容,都在 DOM 中存放,那麼能夠從 CSS 上想辦法。
最容易想到的固然是精簡 CSS 並儘快提供它。
js如何阻塞渲染的?
當瀏覽器遇到一個 script 標記時,DOM 構建將暫停,直至腳本完成執行。前端
主流瀏覽器如Chrome和FireFox等都有一些優化,老是並行加載資源。好比在執行腳本時,開啓另外一個進程解析剩餘的文檔以找出並加載其餘的待下載外部資源(不改變主進程的DOM樹,僅優化加載外部資源)segmentfault
若是腳本體積很大,下載和執行的時間就會很長,所以形成瀏覽器堵塞,用戶會感受到瀏覽器「卡死」了,沒有任何響應。這顯然是很很差的體驗,因此瀏覽器容許腳本異步加載,下面就是兩種異步加載的語法。後端
<script src="path/to/myModule.js" defer></script>
<script src="path/to/myModule.js" async></script>
defer(下載完成延遲執行)與async(下載完成異步執行)
的區別是:瀏覽器
defer
要等到整個頁面在內存中正常渲染結束(DOM 結構徹底生成,以及其餘腳本執行完成),纔會執行;緩存
async
一旦下載完,渲染引擎就會中斷渲染,執行這個腳本之後,再繼續渲染。cookie
另外,若是有多個defer
腳本,會按照它們在頁面出現的順序加載,而多個async
腳本是不能保證加載順序的。網絡
重繪和迴流
重繪Repaint
當頁面元素樣式的改變不影響元素在文檔流中的位置時(例如background-color, border-color,visibility),瀏覽器只會將新樣式賦予元素並進行重繪操做在,注意改變字體大小也會觸發重繪。
迴流Reflow
當改變影響文檔內容或者結構,或者元素位置時,迴流操做就會被觸發,本質仍是一個佈局的過程,通常有如下幾種狀況:
- DOM操做(對元素的增刪改,順序變化等);
- 內容變化,包括表單區域內的文本改變;
- CSS屬性的更改或從新計算;
- 增刪樣式表內容;
- 修改class屬性;
- 瀏覽器窗口變化(滾動或縮放);
- 僞類樣式激活(:hover等)。
對於重回和迴流,瀏覽器自身的渲染優化策略dom
瀏覽器自己會盡量地減小其重繪或迴流的次數,只更改必要的元素。例如一個position設置爲absolute/fixed的元素的更改只會影響其自己和其子元素,而static的元素變化則會影響其以後的全部頁面元素。
另一項優化的技術則是在JavaScript代碼運行時,瀏覽器會緩存全部的變化,而後只經過一次pass繪製操做來應用這些更改。例以下面這段代碼只會觸發一次重繪和迴流:
然而,根據咱們以前提到過的,獲取某個元素的屬性將會觸發強制迴流。好比咱們在剛纔的代碼中加上一句讀取元素屬性的操做:
結果就會有兩次迴流發生。所以,咱們應該儘可能合併讀取元素屬性的操做來優化性能。
強制迴流
當獲取一些屬性時,瀏覽器爲取得正確的值也會觸發重排。這樣就使得瀏覽器的優化失效了。
這些屬性包括:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight、getComputedStyle() (currentStyle in IE)。
因此,在屢次使用這些值時應進行緩存。
固然也有咱們不得不觸發強制迴流的狀況。好比說對同一個元素的margin-left屬性進行兩次操做——開始的時候賦值100px的距離,以後爲了實現動畫效果,再加上transition屬性將距離改變到50px.
咱們先定義一個CSS類:
以後再對頁面元素進行操做:
但事實上這段代碼並不會像註釋描述的那樣運做,每條語句的操做將被緩存,只有結果會在頁面上顯示,因此咱們就須要手動進行一次強制迴流:
瀏覽器渲染優化
合法地書寫HTML和CSS,不要忘了文檔編碼類型。樣式文件應當在 <head> 標籤中,腳本文件在 <body> 結束前。
簡化並優化你的CSS選擇器(有些人可能CSS預處理器用習慣了歷來不關注這一點)。
將嵌套層減小到最小。CSS選擇器根據其優先級具備不一樣的運行效率(從快到慢):
- ID選擇器: #id
- 類選擇器: .class
- 標籤選擇器: div
- 相鄰選擇器: a + i
- 子元素選擇器: ul > li
- 通用選擇器: *
- 屬性選擇器: input[type="text"]
- 僞類選擇器: a:hover
瀏覽器中CSS選擇器是從右到左進行匹配的(爲何瀏覽器要從右到左匹配樣式選擇器),這也是爲何越短的選擇器運行越快的緣由(別提通用選擇器,它會遍歷全部元素):
- 在你的腳本代碼中,屢次訪問的dom緩存下來,再去查詢他們的屬性。查找器儘可能簡潔,減小DOM的訪問
- 將元素緩存到本地以後再進行操做,最後再添加到DOM當中,減小DOM的操做
- 若是你使用jQuery進行DOM操做的話,最好遵循jQuery最佳實踐。
- 修改元素樣式時,更改其class屬性是性能最高的方法。你的選擇器越有針對性越好(這一樣也有助於分離頁面樣式和邏輯)。
- 儘可能只對 position 爲 absolute/fixed 的元素設置動畫。
-
HTML文檔結構層次儘可能少,最好不深於六層;
-
少許首屏樣式內聯放在標籤內
-
隱藏在屏幕外,或在頁面滾動時,儘可能中止動畫
- 在頁面滾動時禁用 :hover 樣式效果:

參考文章:
前端開發者應知必會:瀏覽器是如何渲染網頁的
淺析前端頁面渲染機制
JS 必定要放在 Body 的最底部麼?聊聊瀏覽器的渲染機制
探究 CSS 解析原理
認識 V8 引擎