前端必讀-瀏覽器加載頁面時(shí)都做了什么

當(dāng)一個瀏覽器接收到從服務(wù)器發(fā)來的html頁面,在渲染并呈現(xiàn)到屏幕上之前,有很多步驟要做。瀏覽器渲染頁面需要做的一系列行為被稱作“關(guān)鍵渲染路徑(Critical Rendering Path 簡稱CRP)”。

CRP 的知識對于如何提升網(wǎng)站性能是相當(dāng)有用的。CRP有6個步驟:

  1. 構(gòu)建DOM樹
  2. 構(gòu)建CSSOM樹
  3. 運(yùn)行JavaScript
  4. 創(chuàng)建渲染樹
  5. 生成布局
  6. 繪制頁面


    CRP的6個步驟

構(gòu)建DOM樹

DOM(Document Object Model)樹是一個表示整個解析過的HTML頁面的對象,從根節(jié)點(diǎn)<html>開始,會創(chuàng)建頁面中的每個 元素/文本 節(jié)點(diǎn)。嵌套在其他元素中的元素作為字節(jié)點(diǎn),每個節(jié)點(diǎn)都包含了其所有的元素屬性,例如: 一個<a>節(jié)點(diǎn)將有 href 屬性與其關(guān)聯(lián)。

舉個例子

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

上面的 HTML 將會被解析成下面的DOM樹


DOM樹

HTML的優(yōu)點(diǎn)在于它不必等待整個頁面加載完成才呈現(xiàn)頁面,可以解析一部分,顯示一部分。但是像CSS、JavaScript等其他資源會阻止頁面渲染。

構(gòu)建CSSOM樹

CSSOM(CSS Object Model) 是一個跟DOM相關(guān)的樣式對象。它跟DOM的表示方法是相似的,但是不論顯式聲明還是隱式繼承,每個節(jié)點(diǎn)都存在關(guān)聯(lián)樣式。

In the style.css file from the document mentioned above, we have the folowing styles
在上面提到的html頁面的style.css中的樣式如下

body { font-size: 18px; }

header { color: plum; }  
h1 { font-size: 28px; }

main { color: firebrick; }  
h2 { font-size: 20px; }

footer { display: none; }  

它會被構(gòu)建成下面的CSSOM樹


CSSOM樹

CSS 被認(rèn)為是 “渲染阻塞資源”,它意味著如果不首先完全解析資源,渲染樹是無法構(gòu)建的。CSS由于它的層疊繼承的性質(zhì),不能像HTML一樣解析一部分,顯示一部分。定義在文檔后面的樣式會覆蓋或改寫之前定義的樣式,因?yàn)樵谡麄€樣式表都被解析之前,如果我們使用了在樣式表中較早定義的樣式,那錯誤的樣式將被應(yīng)用。這意味著CSS必須被全部解析之后,才能開始下一步。

如果CSS文件適用于當(dāng)前設(shè)備的話,僅僅只是會阻塞渲染。<link rel="stylesheet">標(biāo)簽可以使用media屬性,用來指定特定樣式寬度的特定媒體查詢。

舉個例子,如果我們有一個包含媒體屬性orientation:landscape的樣式,我們使用縱向模式(portrait mode)查看頁面,這個資源將不會阻塞渲染。

CSS 也會導(dǎo)致腳本阻塞。這是因?yàn)镴avaScript文件必須等待CSSOM被構(gòu)建后才能運(yùn)行。

運(yùn)行JavaScript

JavaScript被認(rèn)為是解析阻塞資源,這意味著HTML的解析會被JavaScript阻塞。

當(dāng)解析器解析到 <script> 標(biāo)簽時(shí),無論該資源是內(nèi)部還是外鏈的都會停止解析,先去下載資源。這也是為什么,當(dāng)頁面內(nèi)有引用JavaScript文件時(shí),引用標(biāo)簽要放到可視元素之后了。

為避免JavaScript解析阻塞,它可以通過設(shè)定 async 屬性來要求其異步加載。

<script async src="script.js">

創(chuàng)建渲染樹

渲染樹是DOM和CSSOM的結(jié)合體,它代表最終會渲染在頁面上的元素的結(jié)構(gòu)對象。這意味著它只關(guān)注可見內(nèi)容,對于被隱藏或者CSS屬性 display:none 的屬性,不會被包含在結(jié)構(gòu)內(nèi)。

使用上面例子的DOM和CSSOM,渲染樹被創(chuàng)建如下:


渲染樹

生成布局

布局決定了瀏覽器視窗的大小,它提供了上下文依賴的CSS樣式,如百分比或窗口的單位。視窗尺寸通常通過 <head> 標(biāo)簽中的 <meta> 中的 viewport 設(shè)定來決定。如果不存在該標(biāo)簽,則通常默認(rèn)為 980px

例如,最常用的 meta veiwport 的值將會被設(shè)置為和設(shè)備寬度相符:

<meta name="viewport" content="width=device-width,initial-scale=1">  

如果用戶訪問網(wǎng)頁的設(shè)備寬度為1000px。然后整體視窗尺寸就會基于這個寬度值了,比如 50% 就是500px, 10vw 就是100px 等等。

繪制頁面

最后,在繪制頁面步驟。頁面上的所有可見內(nèi)容都會被轉(zhuǎn)換為像素并呈現(xiàn)在屏幕上。

具體的繪制時(shí)間跟DOM數(shù)以及應(yīng)用的樣式有關(guān)。有些樣式會花費(fèi)更多的執(zhí)行時(shí)間,比如復(fù)雜的漸變背景圖片所需要的計(jì)算時(shí)間遠(yuǎn)超過簡單固定背景色。

整合所有

想要看到關(guān)鍵渲染路徑的執(zhí)行流程,可以使用DevTools,在Chrome中,它是根據(jù)時(shí)間軸展示的。

舉個例子, 上面的頁面加入<script>標(biāo)簽

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

可以看關(guān)于頁面加載時(shí)的事件日志,以下是我們獲得的:


時(shí)間軸
  1. Send Request - 發(fā)送到index.html的GET請求
  2. Parse HTML and Send Request - 開始解析HTML并構(gòu)建DOM,然后發(fā)送 GET 請求style.css和main.js
  3. Parse Stylesheet - 根據(jù) style.css 創(chuàng)建的CSSOM
  4. Evaluate Script - 執(zhí)行 main.js
  5. Layout - 基于HTML的元視窗標(biāo)簽,生成布局
  6. Paint - 繪制網(wǎng)頁
    基于這些信息,我們可以知道如何優(yōu)化關(guān)鍵渲染路徑。

原文: Understanding the Critical Rendering Path

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,546評論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,570評論 3 418
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,505評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,017評論 1 313
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,786評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,219評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,287評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,438評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,971評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,796評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,995評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,540評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,230評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,918評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,697評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內(nèi)容