瀏覽器的工作機制
瀏覽器包含渲染引擎(也稱瀏覽器內核)和 JavaScript 引擎,它們都是單線程運行。單線程的優(yōu)勢是開發(fā)方便,避免多線程下的死鎖、競爭等問題,劣勢是失去了并發(fā)能力。
- 互斥性機制
瀏覽器為了避免兩個引擎同時修改頁面而造成渲染結果不一致的情況,增加了另外一個機制,這兩個引擎具有互斥性,也就是說在某個時刻只有一個引擎在運行,另一個引擎會被阻塞。操作系統(tǒng)在進行線程切換的時候需要保存上一個線程執(zhí)行時的狀態(tài)信息并讀取下一個線程的狀態(tài)信息,俗稱上下文切換。而這個操作相對而言是比較耗時的。
每次 DOM 操作就會引發(fā)線程的上下文切換——從 JavaScript 引擎切換到渲染引擎執(zhí)行對應操作,然后再切換回 JavaScript 引擎繼續(xù)執(zhí)行,這就帶來了性能損耗。 - 重新渲染
瀏覽器在渲染頁面時會將 HTML 和 CSS 分別解析成 DOM 樹和 CSSOM 樹,然后合并進行排布,再繪制成我們可見的頁面。如果在操作 DOM 時涉及到元素、樣式的修改,就會引起渲染引擎重新計算樣式生成 CSSOM 樹,同時還有可能觸發(fā)對元素的重新排布(簡稱“重排”)和重新繪制(簡稱“重繪”)。
除了這些方法之外,還有一些原則也可能幫助我們提升渲染性能,比如: - 性能優(yōu)化
針對DOM 操作耗時,有一些原則也可能幫助我們提升渲染性能如下:
- 盡量不要使用復雜的匹配規(guī)則和復雜的樣式,從而減少渲染引擎計算樣式規(guī)則生成 CSSOM 樹的時間;
- 盡量減少重排和重繪影響的區(qū)域;
- 使用 CSS3 特性來實現(xiàn)動畫效果。
瀏覽器如何渲染頁面
瀏覽器通過 HTTP 協(xié)議接收到的文檔內容是字節(jié)數(shù)據(jù),下圖是抓包工具截獲的報文截圖,報文內容為左側高亮顯示的區(qū)域(為了查看方便,該工具將字節(jié)數(shù)據(jù)以十六進制方式顯示)。當瀏覽器得到字節(jié)數(shù)據(jù)后,通過“編碼嗅探算法”來確定字符編碼,然后根據(jù)字符編碼將字節(jié)流數(shù)據(jù)進行。

image.png
-
從HTML到DOM到過程
如下圖:
image.png
如果在 HTML 解析過程中遇到 script 標簽,則會發(fā)生一些變化。
如果遇到的是內聯(lián)代碼,也就是在 script 標簽中直接寫代碼,那么解析過程會暫停,執(zhí)行權限會轉給 JavaScript 腳本引擎,待 JavaScript 腳本執(zhí)行完成之后再交由渲染引擎繼續(xù)解析。有一種情況例外,那就是腳本內容中調用了改變 DOM 結構的 document.write() 函數(shù),此時渲染引擎會回到第二步,將這些代碼加入字符流,重新進行解析。
如果遇到的是外鏈腳本,那么渲染引擎會按照我們在第 01 課時中所述的,根據(jù)標簽屬性來執(zhí)行對應的操作。
- 從 CSS 到 CSSOM
渲染引擎除了解析 HTML 之外,也需要解析 CSS,CSS 解析的過程與 HTML 解析過程步驟一致,最終也會生成樹狀結構。與 DOM 樹不同的是,CSSOM 樹的節(jié)點具有繼承特性,也就是會先繼承父節(jié)點樣式作為當前樣式,然后再進行補充或覆蓋。
(注:筆記來自 朱德龍 前端高手進階)
