分析不同类型页面渲染过程
現(xiàn)在讓我們看看瀏覽器從網(wǎng)絡(luò)上加載資源所耗費的時間(我們忽略從緩存以及從CDN等中間商網(wǎng)絡(luò)上加載資源),我們首先要知道的是:
- 一個到無服務(wù)的網(wǎng)路往返?(傳播延遲) 大約100ms
- 服務(wù)器對于HTML文檔的響應(yīng)大約100ms,對于其他資源大約10ms
The Hello World experience
<html><head><meta name="viewport" content="width=device-width,initial-scale=1"><title>Critical Path: No Style</title></head><body><p>Hello <span>web performance</span> students!</p><div><img src="awesome-photo.jpg"></div></body> </html>我們只是加載了時間和網(wǎng)頁——沒有任何的js和css資源等——我們的頁面非常簡單,下面我們看看谷歌瀏覽器開發(fā)者工具里記錄下載用的時間:
HTML文檔大約花費200ms來加載。注意上面的藍(lán)色透明進(jìn)度條表明了網(wǎng)路上的一個往返,這里我們的HTML文檔非常的小(小于4k),我們只是進(jìn)行了簡單的文件抓取工作,一半的時間來等待網(wǎng)絡(luò)響應(yīng),一般的時間花費在服務(wù)器響應(yīng)上,總用時大于200ms。
一旦HTML文檔內(nèi)容可以使用,瀏覽器開始解析HTML內(nèi)容(全部是字節(jié)),將其轉(zhuǎn)化成tokens,然后建立DOM樹。注意在工具條最下面顯示了DOMContentLoaded事件花費的時間是216毫秒,也就是對應(yīng)的藍(lán)色垂直實線。在藍(lán)色透明進(jìn)度條和藍(lán)色垂直實線之間的時間就是瀏覽器建立DOM樹的時間——在上例中只是花費了幾毫秒。
注意我們的“awesome photo”沒有阻塞任何的DOMContentLoaded事件,所以我們可以直接構(gòu)造render tree甚至將內(nèi)容顯示在屏幕上,不用等待圖片資源:不是所有的資源都會阻塞渲染!所以,在談?wù)撲秩具^程的時候,我們只是談?wù)摿薺s,css和html標(biāo)記。圖片雖然不會阻塞渲染,但是我們?nèi)耘f應(yīng)該讓其迅速加載顯示。
但是,“l(fā)oad”事件(也被叫做"onload")事件卻被圖片加載阻塞:因為load事件是在所有資源加載完畢之后觸發(fā),上圖中也即是最后的紅色垂直實線,也就是工具條最下面顯示的load:335ms,這也是瀏覽器加載器停止加載的時間點。
Adding JavaScript and CSS into the mix
實際的編程中肯定需要css和js,所以讓我們在其中加入css和js:
<html><head><title>Critical Path: Measure Script</title><meta name="viewport" content="width=device-width,initial-scale=1"><link href="style.css" rel="stylesheet"></head><body onload="measureCRP()"><p>Hello <span>web performance</span> students!</p><div><img src="awesome-photo.jpg"></div><script src="timing.js"></script></body> </html>在加入js和css之前:
在加入js和css之后
css文件和js文件都在異步同時被加載,這是好事!注意load和DOMContentLoaded和之前的微妙的不同:
- 不像只是簡單的HTML文件(不包含任何的css和js),包含js和css的文件還需要將css編程CSSOM樹,以及CSSOM樹和HTML樹相互結(jié)合形成render tree的過程。
- 因為js文件可能要處理CSSOM,所以css文件必須在執(zhí)行js文件之前執(zhí)行!并且css的下載將會阻塞domContentLoaded事件。
如果我們將js直接寫在html內(nèi)部呢?
外部js導(dǎo)入:
直接書寫js:
雖然我們減少了一次加載請求,但是事件是差不多的,因為在解析script標(biāo)簽的時候?qū)枞钡紺SSOM被創(chuàng)建完成。同時,從上圖中我們可以看見,css和js文件的加載是平行進(jìn)行的。
所以,我們有什么策略來減少事件呢?
讓我們在js文件中加入async異步關(guān)鍵字:
<html><head><title>Critical Path: Measure Async</title><meta name="viewport" content="width=device-width,initial-scale=1"><link href="style.css" rel="stylesheet"></head><body onload="measureCRP()"><p>Hello <span>web performance</span> students!</p><div><img src="awesome-photo.jpg"></div><script async src="timing.js"></script></body> </html>?
?
同步內(nèi)部加載js:
異步外部加載js:
可以看見domContentLoade事件在HTML解析完成后馬上執(zhí)行:瀏覽器知道了不要在處理js中對其進(jìn)行阻塞,因為沒有了其他渲染的阻塞,CSSOM構(gòu)造可以同時進(jìn)行。
我們可以同時在文件內(nèi)部書寫js和css文件內(nèi)容,而不是外部引入:
<html><head><title>Critical Path: Measure Inlined</title><meta name="viewport" content="width=device-width,initial-scale=1"><style>p { font-weight: bold }span { color: red }p span { display: none }img { float: right }</style></head><body><p>Hello <span>web performance</span> students!</p><div><img src="awesome-photo.jpg"></div><script>var span = document.getElementsByTagName('span')[0];span.textContent = 'interactive'; // change DOM text content span.style.display = 'inline'; // change CSSOM property// create a new element, style it, and append it to the DOMvar loadTime = document.createElement('div');loadTime.textContent = 'You loaded this page on: ' + new Date();loadTime.style.color = 'blue';document.body.appendChild(loadTime);</script></body> </html>可以看見domContentLoaded事件的時間和異步加載外部js文件例子中個domContentLoadedNotice時間差不多。
將css和js文件內(nèi)容直接書寫在html文件內(nèi)部,雖然會讓html變得非常龐大,但是可以減少外部資源的加載。
優(yōu)化模式
最簡單的html就是沒有css和js亦或依他資源,只有html內(nèi)容。
渲染這種頁面,瀏覽器你需要初始化請求,等待html文檔加載完成,解析它,建立DOM樹,最后渲染到屏幕上:
<html><head><meta name="viewport" content="width=device-width,initial-scale=1"><title>Critical Path: No Style</title></head><body><p>Hello <span>web performance</span> students!</p><div><img src="awesome-photo.jpg"></div></body> </html>?
?T0?和T1?之間的時間捕捉了網(wǎng)絡(luò)和服務(wù)器操作的時間。
?在理想情況下(如果HTML文檔足夠小),所有我們需要做的就是使用一個網(wǎng)絡(luò)往返來獲取整個文件——根據(jù)TCP傳輸協(xié)議,文件越大需要越多的網(wǎng)絡(luò)往返。所以上圖是建立在最理想的狀況下,加載文件只要一個網(wǎng)絡(luò)往返。
讓我們增加css文件:
<html><head><meta name="viewport" content="width=device-width,initial-scale=1"><link href="style.css" rel="stylesheet"></head><body><p>Hello <span>web performance</span> students!</p><div><img src="awesome-photo.jpg"></div></body> </html>我們使用了一個網(wǎng)絡(luò)往返來獲取HTML資源,在將內(nèi)容最終渲染到屏幕上之前我們必須要加載css文件,所以我們使用了一個網(wǎng)絡(luò)往返來獲取css文件,最后渲染頁面。注意我們這里每次獲取資源使用一個網(wǎng)絡(luò)往返是建立在資源非常小的情況下,也就是說最理想的狀態(tài)下。
讓我們使用關(guān)鍵術(shù)語來描述渲染過程:
- 關(guān)鍵資源:?資源可能會阻塞頁面的渲染(這是使用可能是因為圖片等資源是不會阻塞頁面的渲染的,只有css和js資源會)
- 渲染路徑長度:?網(wǎng)絡(luò)往返的次數(shù),亦或獲取所有資源的總時間 number of roundtrips, or the total time required to fetch all of the critical resources.
- 關(guān)鍵字節(jié):?頁面第一次渲染時所需要的字節(jié)數(shù),也就是將關(guān)鍵資源文件大小的總和。
- 我們上面第一個最簡單的網(wǎng)頁形式的例子,就包含了一個關(guān)鍵資源(HTML文檔),關(guān)鍵路徑長度是1個網(wǎng)絡(luò)往返(假設(shè)文件非常小),總共的關(guān)鍵字節(jié)是HTML文檔的字節(jié)大小。
讓我們比較上面HTML+CSS文件的渲染過程:
- 2?關(guān)鍵文件:CSS文件和HTML文檔
- 2?或者更多的路徑長度:加載css和HTML時所分別需要一個網(wǎng)絡(luò)往返?
- 9?KB 的關(guān)鍵字節(jié):2個關(guān)鍵文件的總和
現(xiàn)在讓我們加入js:
<html><head><meta name="viewport" content="width=device-width,initial-scale=1"><link href="style.css" rel="stylesheet"></head><body><p>Hello <span>web performance</span> students!</p><div><img src="awesome-photo.jpg"></div><script src="app.js"></script></body> </html>過程是,加載完了HTML之后,同時加載css和js文件,因為js要查詢CSSOM,所以必須等到cssom建立完成知乎才可以運行js,之后建立DOM,最后渲染頁面。
- 3?個關(guān)鍵文件:CSS和JS和HTML文件分別一個
- 2?或者更多的路徑長度:因為加載css和js是同時進(jìn)行的,也就是說在同一個網(wǎng)絡(luò)往返中,加載HTML進(jìn)行了一次網(wǎng)絡(luò)往返
- 11?KB 的關(guān)鍵字節(jié):3個關(guān)鍵文件的大小綜合
異步加載js文件:
<html><head><meta name="viewport" content="width=device-width,initial-scale=1"><link href="style.css" rel="stylesheet"></head><body><p>Hello <span>web performance</span> students!</p><div><img src="awesome-photo.jpg"></div><script src="app.js" async></script></body> </html>?
?
異步加載js的好處:
- js腳本不會讓瀏覽器在解析其他文件時對其進(jìn)行阻塞,也不會影響關(guān)鍵渲染進(jìn)程
- 因為關(guān)鍵文件中不再包含js腳本文件,css同樣不需要阻塞domContentLoaded事件
- domContentLoaded事件越快被觸發(fā),其他的應(yīng)用邏輯也會越快被執(zhí)行
所以,最后的結(jié)果是我們只有兩個關(guān)鍵文件,且我們只有兩個路徑長度(因為我們只進(jìn)行了兩次網(wǎng)路往返),并且9kb的關(guān)鍵字節(jié)。
?
如果css只是針對打印機(jī)設(shè)備呢?
<html><head><meta name="viewport" content="width=device-width,initial-scale=1"><link href="style.css" rel="stylesheet" media="print"></head><body><p>Hello <span>web performance</span> students!</p><div><img src="awesome-photo.jpg"></div><script src="app.js" async></script></body> </html>因為css資源只是用于打印機(jī)設(shè)備,所以瀏覽器不需要下載css時進(jìn)行渲染阻塞,所以,一旦DOM構(gòu)造完成,瀏覽器就有足夠的信息來渲染頁面!
所以,文檔只有一個關(guān)鍵文件(HTML文檔),最小的渲染路徑(只有一個網(wǎng)絡(luò)往返)。
?
原文:https://developers.google.com/web/fundamentals/performance/critical-rendering-path/analyzing-crp?hl=en
轉(zhuǎn)載于:https://www.cnblogs.com/RachelChen/p/5456189.html
總結(jié)
以上是生活随笔為你收集整理的分析不同类型页面渲染过程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VS2015升级Update2之后Cor
- 下一篇: ImageLoader加载图片