先簡要概述瀏覽器渲染的步驟:
- 處理HTML標記并構(gòu)建DOM樹
- 處理CSS標記并構(gòu)建CSSOM樹
- 將DOM與CSSOM合并成一個渲染樹
- 根據(jù)渲染樹來布局苫费,計算每個節(jié)點的布局信息
- 將各個節(jié)點繪制到屏幕上
如果DOM或CSSOM被修改汤锨,就會重新執(zhí)行上面所有步驟
構(gòu)建對象模型(DOM,CSSOM)
瀏覽器解析HTML文檔時百框,會完成以下步驟:
- 讀取HTML的原始字節(jié)闲礼,根據(jù)文件制定編碼(例:utf-8)解析為各個字符
- 將字符串轉(zhuǎn)化為各種標簽
- 將標簽轉(zhuǎn)化為node節(jié)點
- DOM構(gòu)建
瀏覽器解析HTML時,遇到link標簽铐维,會發(fā)出請求并返回資源柬泽,開始解析CSS:
CSS字節(jié)轉(zhuǎn)換為字符,接著轉(zhuǎn)換成令牌和節(jié)點嫁蛇,最后構(gòu)建生成CSSOM
CSSOM和DOM是獨立的數(shù)據(jù)結(jié)構(gòu)
渲染樹構(gòu)建锨并、布局及繪制
CSSOM樹和DOM樹合并成渲染樹,然后用于計算每個可見元素的布局睬棚,并輸出給繪制流程琳疏,將像素渲染到屏幕上有决。
構(gòu)建渲染樹的步驟:
- 從DOM樹的根節(jié)點開始遍歷每個可見節(jié)點(display:none與visibility:hidden的區(qū)別)
- 對于每個可見節(jié)點,為其找到適配的CSSOM規(guī)則并應(yīng)用它
- 生成渲染樹
布局階段:輸出盒模型
繪制:輸出到屏幕上的像素
CSS阻塞渲染
CSS 是阻塞渲染的資源空盼。需要將它盡早书幕、盡快地下載到客戶端,以便縮短首次渲染的時間揽趾。
這就是為什么我們將外部樣式的引入放在head標簽中的原因台汇,在body渲染前先把相對完整CSSOM Tree構(gòu)建好。
對于某些CSS樣式只在特定條件下叉用篱瞎,添加媒體查詢解決苟呐。
請注意“阻塞渲染”僅是指瀏覽器是否需要暫停網(wǎng)頁的首次渲染,直至該資源準備就緒俐筋。無論哪一種情況牵素,瀏覽器仍會下載 CSS 資產(chǎn),只不過不阻塞渲染的資源優(yōu)先級較低罷了澄者。
JavaScript阻塞渲染
JavaScript 會阻止 DOM 構(gòu)建和延緩網(wǎng)頁渲染笆呆。 為了實現(xiàn)最佳性能,可以讓您的 JavaScript 異步執(zhí)行粱挡,并去除關(guān)鍵渲染路徑中任何不必要的 JavaScript赠幕。
- JavaScript 可以查詢和修改 DOM 與 CSSOM。
- JavaScript 執(zhí)行會阻止 CSSOM询筏。
- 除非將 JavaScript 顯式聲明為異步榕堰,否則它會阻止構(gòu)建 DOM。
- 如果瀏覽器尚未完成 CSSOM 的下載和構(gòu)建嫌套,而我們卻想在此時運行腳本逆屡,瀏覽器將延遲腳本執(zhí)行和 DOM 構(gòu)建,直至其完成 CSSOM 的下載和構(gòu)建踱讨。
簡言之魏蔗,JavaScript 在 DOM、CSSOM 和 JavaScript 執(zhí)行之間引入了大量新的依賴關(guān)系勇蝙,從而可能導致瀏覽器在處理以及在屏幕上渲染網(wǎng)頁時出現(xiàn)大幅延遲:
- 腳本在文檔中的位置很重要
- 當瀏覽器遇到一個 script 標記時沫勿,DOM 構(gòu)建將暫停挨约,直至腳本完成執(zhí)行味混。
- JavaScript 可以查詢和修改 DOM 與 CSSOM。
- JavaScript 執(zhí)行將暫停诫惭,直至 CSSOM 就緒翁锡。
async屬性:加載和渲染后續(xù)文檔元素的過程將和 script.js 的加載與執(zhí)行并行進行(異步)。無順序
defer屬性: 加載后續(xù)文檔元素的過程將和 script.js 的加載并行進行(異步)夕土,但 script.js 的執(zhí)行要在所有元素解析完成之后馆衔,DOMContentLoaded 事件觸發(fā)之前完成瘟判。按順序
參考文章
谷歌開發(fā)者文檔
kraaas博客