6張圖讓你搞懂瀏覽器渲染網頁過程

做者:James Starkie
譯者:前端小智
來源:dev

最近開源了一個 Vue 組件,還不夠完善,歡迎你們來一塊兒完善它,也但願你們能給個 star 支持一下,謝謝各位了。javascript

github 地址:https://github.com/qq44924588...css

個人想法:若是我要構建快速可靠的網站,須要真正瞭解瀏覽器渲染網頁的每一個步驟機制,這樣就能夠在開發過程當中對每一個步驟進行優化。 這篇文章是我在較高水平上對端到端過程的學習總結。前端

好了,廢話很少說,咱們開始吧。這個過程能夠分爲如下幾個主要階段:vue

  1. 開始解析HTML
  2. 獲取外部資源
  3. 解析 CSS 並構建CSSOM
  4. 執行 JavaScript
  5. 合併 DOM 和 CSSOM 以構造渲染樹
  6. 計算佈局和繪製

1.開始解析HTML

當瀏覽器經過網絡接收頁面的HTML數據時,它會當即設置解析器將HTML轉換爲文檔對象模型(DOM)java

文檔對象模型 (DOM) 是HTML和XML文檔的編程接口。它提供了對文檔的結構化的表述,並定義了一種方式可使從程序中對該結構進行訪問,從而改變文檔的結構,樣式和內容。DOM 將文檔解析爲一個由節點和對象(包含屬性和方法的對象)組成的結構集合。簡言之,它會將web頁面和腳本或程序語言鏈接起來。

解析過程的第一步是將HTML分解並表示爲開始標記結束標記及內容標記,而後它能夠構造DOM。git

clipboard.png

2. 獲取外部資源

當解析器遇到外部資源(如CSS或JavaScript文件)時,解析器將提取這些文件。 解析器在加載CSS文件時繼續運行,此時會阻止頁面渲染,直到資源加載解析完(稍後會詳細介紹)。github

JavaScript 文件略有不一樣-默認狀況下,解析器會在加載 JS 文件而後進行解析同時會阻止對HTML的解析。 能夠將兩個屬性添加到腳本標籤中以減輕這種狀況:deferasync。 二者都容許解析器在後臺加載JavaScript 文件的同時繼續運行,可是它們的執行方式不一樣。 關於這一點後面還會再講一點,但總的來講:web

defer表示文件的執行將被延遲,直到文檔的解析完成爲止。 若是多個文件具備defer屬性,則將按照頁面放置的順序依次執行。面試

<script type="text/javascript" src="script.js" defer>

async 意味着文件將在加載後當即執行,這多是在解析過程當中或在解析過程以後執行的,所以不能保證異步腳本的執行順序。編程

<script type="text/javascript" src="script.js" async>

預加載資源

<link> 元素的 rel 屬性的屬性值preload可以讓你在你的HTML頁面中 <head>元素內部書寫一些聲明式的資源獲取請求,能夠指明哪些資源是在頁面加載完成後即刻須要的。

對於這種即刻須要的資源,你可能但願在頁面加載的生命週期的早期階段就開始獲取,在瀏覽器的主渲染機制介入前就進行預加載。這一機制使得資源能夠更早的獲得加載並可用,且更不易阻塞頁面的初步渲染,進而提高性能。

<link href="style.css" rel="preload" as="style" />

clipboard.png

3.解析CSS並構建CSSOM

你可能很早就知道DOM,但對CSSOM(CSS對象模型)可能聽得少,反正我也沒聽過幾回。

CSS 對象模型 (CSSOM) 是樹形形式的全部CSS選擇器和每一個選擇器的相關屬性的映射,具備樹的根節點,同級,後代,子級和其餘關係。CSSOM 與 文檔對象模型(DOM) 很是類似。二者都是關鍵渲染路徑的一部分,也是正確渲染一個網站必須採起的一系列步驟。

CSSOM 與 DOM一塊兒構建渲染樹,瀏覽器依次使用渲染樹來佈局和繪製網頁。

與HTML文件和DOM類似,加載CSS文件時,必須將它們解析並轉換爲樹-此次是CSSOM。 它描述了頁面上的全部CSS選擇器,它們的層次結構和屬性。

CSSOMDOM的不一樣之處在於它不能以增量方式構建,由於CSS規則因爲特定性而能夠在各個不一樣的點相互覆蓋。 這就是CSS 阻塞渲染的緣由,由於在解析全部CSS並構建CSSOM以前,瀏覽器沒法知道每一個元素在屏幕上的位置。

clipboard.png

4.執行JavaScript

不一樣的瀏覽器有不一樣的 JS 引擎來執行此任務。從計算機資源的角度來看,解析 JS 多是一個昂貴的過程,比其餘類型的資源更昂貴,所以優化它對於得到良好的性能是如此重要。

載入事件

加載的JS和DOM被徹底解析並準備就緒後就會 emit document.DOMContentLoaded事件。 對於須要訪問DOM的任何腳本,例如以某種方式進行操做或偵聽用戶交互事件,優良做法是在執行腳本以前先等待此事件。

document.addEventListener('DOMContentLoaded', (event) => {
    // 這裏面能夠安全地訪問DOM了
});

在全部其餘內容(例如異步JavaScript,圖像等)完成加載後,將觸發window.load事件。

window.addEventListener('load', (event) => {
    // 頁面現已徹底加載
});

clipboard.png

5.合併DOM和CSSOM 構建渲染樹

渲染樹DOMCSSOM的組合,表示將要渲染到頁面上的全部內容。 這並不必定意味着渲染樹中的全部節點都將在視覺上呈現,例如,將包含opacity: 0visibility: hidden的樣式的節點,並仍然能夠被屏幕閱讀器等讀取,而display: none不包括任何內容。 此外,諸如<head>之類的不包含任何視覺信息的標籤將始終被忽略。

與 JS 引擎同樣,不一樣的瀏覽器具備不一樣的渲染引擎。

clipboard.png

6. 計算佈局和繪製

如今咱們有了完整的渲染樹,瀏覽器知道了要渲染什麼,可是不知道在哪裏渲染。 所以,必須計算頁面的佈局(即每一個節點的位置和大小)。 渲染引擎從頂部開始一直向下遍歷渲染樹,計算應顯示每一個節點的座標。

完成以後,最後一步是獲取佈局信息並將像素繪製到屏幕上。

clipboard.png


原文:https://dev.to/jstarmx/how-th...

代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug

交流

文章每週持續更新,能夠微信搜索「 大遷世界 」第一時間閱讀和催更(比博客早一到兩篇喲),本文 GitHub https://github.com/qq449245884/xiaozhi 已經收錄,整理了不少個人文檔,歡迎Star和完善,你們面試能夠參照考點複習,另外關注公衆號,後臺回覆福利,便可看到福利,你懂的。

相關文章
相關標籤/搜索