原文: https://bitsofco.de/understan...做者:Ire Aderinokuncss
瀏覽器從接收到服務器返回的 HTML 到渲染像素到屏幕上,中間經歷了不少的步驟。瀏覽器初次繪製網頁的必通過程稱之爲「關鍵渲染路徑(Critical Rendering Path,如下稱CRP)」。html
CRP的知識對理解怎樣提高網站性能很是有用。CRP有如下6個階段:chrome
DOM 樹是一個表示完整解析過的 HTML 網頁的對象。它從根元素 <html> 開始,每個節點表明頁面上的一個元素或者文本。包含在其餘元素中間的元素被表示成子節點。每個節點記錄着對應元素的全部屬性,舉例來講,一個 <a>
元素對應的節點包含了元素的 href
屬性。瀏覽器
<html> <head> <title>Understanding the Critical Rendering Path</title> <link rel="stylesheet" href="style.css"> </head> <body> <header> <h1>Understanding the Critical Rendering Path</h1> </header> <main> <h2>Introduction</h2> <p>Lorem ipsum dolor sit amet</p> </main> <footer> <small>Copyright 2017</small> </footer> </body> </html>
以這個網頁爲例,它將被解析成下圖的 DOM樹:服務器
A good thing about HTML is that it can be executed in parts. The full document doesn't have to be loaded for content to start appearing on the page. However, other resources, CSS and JavaScript, can block the render of the page.
HTML 的一點好處是它能夠分塊執行,無需加載整個文檔,內容就能夠開始出如今頁面上。可是很差的地方是,諸如CSS 和 JavaScript 文件這樣的資源,卻可以阻塞頁面的渲染。併發
CSSOM (CSS 對象模型) 是一個表示DOM相關聯樣式的對象。它與DOM的表現方式相似,但記錄了每一個節點的關聯樣式,包含明確聲明的樣式和默認繼承的樣式。app
在上面文檔中提到的style.css裏, 咱們聲明瞭以下樣式:異步
body { font-size: 18px; } header { color: plum; } h1 { font-size: 28px; } main { color: firebrick; } h2 { font-size: 20px; } footer { display: none; }
上面的樣式會生成以下的CSSOM 樹:async
CSS 被稱爲 「渲染阻塞資源(render blocking resource)」 。渲染阻塞資源 沒有通過初次完整解析,渲染樹(後面會解釋) 不會被構建。因爲CSS 具備繼承和層疊的特性,它不能像 HTML同樣被分塊解析。在CSS 文檔後面定義的樣式會覆蓋或更改前面定義的樣式。因此若是咱們只解析前面部分的 CSS 樣式,而非整個 CSS 文檔,那麼有可能解析出來錯誤的結果。這意味着 CSS 必須被完整解析,咱們才能進入頁面渲染的下一個階段。佈局
CSS 文件只有適用於當前設備的時候纔會被認爲是 」渲染阻塞資源「 。<link rel="stylesheet">
標籤能夠接受一個媒體屬性,經過改屬性咱們能夠聲明樣式表適用的設備。例如:咱們有個樣式表聲明瞭一個媒體屬性 orientation:landscape
, 只有咱們在縱向模式訪問的時候,該資源纔是阻塞渲染的。
因爲 Javascript 文件必須等待 CSSOM 構建完成纔可以運行。所以也能夠說CSS 是 「阻塞腳本」的。
JavaScript 被認爲是一種 解析阻塞資源,HTML 自己的解析會被 JavaScript 阻塞。
當解析器遇到 <script>
標籤時,不論是內部腳本仍是外部腳本,解析器會停下來加載腳本(是外部腳本的狀況下)並運行它。這就是爲何咱們必須將哪些須要引用 Element 和文檔的腳本放在文檔外觀的後面。
爲了不 Javascript 阻塞解析,經過聲明async
屬性,可讓它被異步加載。
<script async src="script.js">
渲染樹 是 DOM 和 CSSOM的結合。它是一個表示頁面被最終渲染效果的樹。這意味着它只會表示哪些可見的內容,哪些不可見內容,好比聲明瞭display:none;
的元素。
使用前面例子中提到的 DOM 和 CSSDOM ,下面的 渲染樹 會被建立出來。
佈局決定了視窗(viewport)的大小,它提供了 CSS 樣式依賴的上下文,例如視窗的百分比或者單位。
視窗的大小由在文檔頭部提供的 meta 標籤 viewport
決定,若是沒有提供,視窗默認寬度是980px。
舉例,經常使用於響應設備寬度的視窗設置以下:
<meta name="viewport" content="width=device-width,initial-scale=1">
若是用戶使用寬度爲1000px的設備訪問網頁,網頁的大小會基於這個單位。一半視窗的大小是500px,10vw會是100px。
最終的步驟是繪製,頁面的可見內容會被轉化成屏幕上的像素。
繪製過程的耗時取決於 DOM 的大小和應用的樣式。某些樣式比其餘樣式須要更多的處理過程。例如:複雜的漸變背景圖比簡單的填充背景須要消耗更多的處理時間。
爲了查看 CRP 過程,咱們能夠打開 chrome 的 devTools,它在Timeline 菜單下面(對於新版Chrome ,位於Performance菜單下)。
以咱們上面的 HTML 爲例。
<html> <head> <title>Understanding the Critical Rendering Path</title> <link rel="stylesheet" href="style.css"> </head> <body> <header> <h1>Understanding the Critical Rendering Path</h1> </header> <main> <h2>Introduction</h2> <p>Lorem ipsum dolor sit amet</p> </main> <footer> <small>Copyright 2017</small> </footer> <script src="main.js"></script> </body> </html>
打開頁面加載過程的Event Log選項 ,咱們能夠看到
基於這些信息,咱們能夠作出如何優化CRP的決策。