瞭解瀏覽器渲染網頁的每個步驟機制!

2020-11-23 21:01:42

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

好了,廢話不多說,我們開始吧。這個過程可以分為以下幾個主要階段:

1、開始解析HTML

2、獲取外部資源

3、解析 CSS 並構建CSSOM

4、執行 JavaScript

5、合併 DOM 和 CSSOM 以構造渲染樹

6、計算佈局和繪製

1.開始解析HTML

當瀏覽器通過網路接收頁面的HTML資料時,它會立即設定解析器將HTML轉換為檔案物件模型(DOM)

檔案物件模型 (DOM) 是HTML和XML檔案的程式設計介面。它提供了對檔案的結構化的表述,並定義了一種方式可以使從程式中對該結構進行存取,從而改變檔案的結構,樣式和內容。DOM 將檔案解析為一個由節點和物件(包含屬性和方法的物件)組成的結構集合。簡言之,它會將web頁面和指令碼或程式語言連線起來。

解析過程的第一步是將HTML分解並表示為開始標記結束標記及內容標記,然後它可以構造DOM。

1.png

2. 獲取外部資源

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

JavaScript 檔案略有不同-預設情況下,解析器會在載入 JS 檔案然後進行解析同時會阻止對HTML的解析。 可以將兩個屬性新增到指令碼標籤中以減輕這種情況:deferasync。 兩者都允許解析器在後臺載入JavaScript 檔案的同時繼續執行,但是它們的執行方式不同。 關於這一點後面還會再講一點,但總的來說:

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" />

2.png

3.解析CSS並構建CSSOM

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

CSS 物件模型 (CSSOM) 是樹形形式的所有CSS選擇器和每個選擇器的相關屬性的對映,具有樹的根節點,同級,後代,子級和其他關係。CSSOM 與 檔案物件模型(DOM) 非常相似。兩者都是關鍵渲染路徑的一部分,也是正確渲染一個網站必須採取的一系列步驟。

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

與HTML檔案和DOM相似,載入CSS檔案時,必須將它們解析並轉換為樹-這次是CSSOM。 它描述了頁面上的所有CSS選擇器,它們的層次結構和屬性。

CSSOMDOM的不同之處在於它不能以增量方式構建,因為CSS規則由於特定性而可以在各個不同的點相互覆蓋。 這就是CSS 阻塞渲染的原因,因為在解析所有CSS並構建CSSOM之前,瀏覽器無法知道每個元素在螢幕上的位置。

3.png

4.執行JavaScript

不同的瀏覽器有不同的 JS 引擎來執行此任務。從計算機資源的角度來看,解析 JS 可能是一個昂貴的過程,比其他型別的資源更昂貴,因此優化它對於獲得良好的效能是如此重要。

載入事件

載入的JS和DOM被完全解析並準備就緒後就會 emit document.DOMContentLoaded事件。 對於需要存取DOM的任何指令碼,例如以某種方式進行操作或偵聽使用者互動事件,優良作法是在執行指令碼之前先等待此事件。

document.addEventListener('DOMContentLoaded', (event) => {
    // 這裡面可以安全地存取DOM了
});

在所有其他內容(例如非同步JavaScript,影象等)完成載入後,將觸發window.load事件。

window.addEventListener('load', (event) => {
    // 頁面現已完全載入
});

4.png

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

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

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

5.png

6. 計算佈局和繪製

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

完成之後,最後一步是獲取佈局資訊並將畫素繪製到螢幕上。

6.png

原文地址:https://dev.to/jstarmx/how-the-browser-renders-a-web-page-1ahc

作者:James Starkie

譯文地址:https://segmentfault.com/a/1190000037650883

更多程式設計相關知識,請存取:!!

以上就是了解瀏覽器渲染網頁的每個步驟機制!的詳細內容,更多請關注TW511.COM其它相關文章!