富媒體網(wǎng)頁
布局(CSS)、圖片、音頻、視頻出現(xiàn)
交互式Web應(yīng)用
javascript、AJAX出現(xiàn),網(wǎng)頁轉(zhuǎn)換成交互式Web應(yīng)用的革命時代。揭開腳本、樣式和文檔之間復(fù)雜依賴關(guān)系的時代
網(wǎng)頁的三個時代
首先來看一下瀏覽器的高層基本結(jié)構(gòu)
瀏覽器的主要組件為:
1.用戶界面 - 包括地址欄、前進(jìn)/后退按鈕、書簽菜單等。除了瀏覽器主窗口顯示的您請求的頁面外,其他顯示的各個部分都屬于用戶面。
2.瀏覽器引擎 - 在用戶界面和呈現(xiàn)引擎之間傳送指令
3.呈現(xiàn)引擎 - 負(fù)責(zé)顯示請求的內(nèi)容。如果請求的內(nèi)容是 HTML,它就負(fù)責(zé)解析 HTML 和 CSS 內(nèi)容,并將解析后的內(nèi)容顯示在屏幕上
4.網(wǎng)絡(luò) - 用于網(wǎng)絡(luò)調(diào)用,比如 HTTP 請求。其接口與平臺無關(guān),并為所有平臺提供底層實現(xiàn)
5.用戶界面后端- 用于繪制基本的窗口小部件,比如組合框和窗口。其公開了與平臺無關(guān)的通用接口,而在底層使用操作系統(tǒng)的用戶界面方法。
6.JavaScript解釋器-用于解析和執(zhí)行 JavaScript 代碼。
7.數(shù)據(jù)存儲-這是持久層。瀏覽器需要在硬盤上保存各種數(shù)據(jù),例如 Cookie。新的 HTML 規(guī)范 (HTML5) 定義了“網(wǎng)絡(luò)數(shù)據(jù)庫”,這是一個完整(但是輕便)的瀏覽器內(nèi)數(shù)據(jù)庫。
下面有一張非常簡單的html頁面,內(nèi)容只有一行文本和一張圖片,有一些HTML基本元素和一個CSS文件,沒有引入javascript文件。那么思考一個比較直觀的問題,對于這么簡單的頁面,瀏覽器是怎么把它從一個文檔變成像素呈現(xiàn)在顯示器上?
先撇開原理這種比較學(xué)術(shù)的字眼,直觀一些地思考這個問題。HTML文檔原來肯定是在服務(wù)器上,那么瀏覽器要顯示它,肯定首先要獲取到這個頁面。瀏覽器拿到的是上圖左邊部分的內(nèi)容,這個和最終右邊的像素內(nèi)容還差十萬八千里,這中間它怎么處理?這時它就要認(rèn)真研究拿到的HTML文檔了。它有一套自己從左到右的流程。下面會說到。
總的來說,瀏覽器要做的事情就是:
1.取得資源(得先拿到HTML文檔吧)
2.分析計算頁面布局和渲染 (從左到右的流程)
3.javascript 執(zhí)行
Q: 誰最重要?
A: 都重要(廢話)。但如果一定要選取一個話,always remember that,獲取資源是第一要義!巧婦難為無米之炊,沒有HTML文檔,任何優(yōu)化技巧都是沒有用的。
指瀏覽器所經(jīng)歷的一系列步驟,將HTML CSS 和 JavaScript 轉(zhuǎn)換為在屏幕上呈現(xiàn)像素內(nèi)容的過程。 提高網(wǎng)頁呈現(xiàn)速度,即優(yōu)化關(guān)鍵呈現(xiàn)路徑。
獲取HTML,構(gòu)建文檔對象模型(DOM )
獲取CSS,構(gòu)建CSS對象模型(CSSOM)
二者結(jié)合,創(chuàng)建渲染樹
計算布局
像素呈現(xiàn)
練習(xí)1
很簡單,首先各自建立DOM和CSS的樹形結(jié)構(gòu),然后對應(yīng)DOM樹上的每個節(jié)點,將對應(yīng)的CSS樣式附著上去。注意渲染樹上只捕捉可見內(nèi)容,span元素是display:none,所以不顯示在渲染樹上,span下原來有一個文本節(jié)點,但由于CSS的繼承屬性,所以這個文本節(jié)點也是不可見,不顯示在最終的渲染樹里。
練習(xí)2
渲染樹如下。html、head、meta等元素雖然也在DOM結(jié)構(gòu)里,但這些都不是可以呈現(xiàn)的元素,所以不會出現(xiàn)在最終的渲染樹里。
我們在討論Web性能時有三個不同的測量指標(biāo)。
最早渲染時間
文檔完成時間
資源最后獲取時間
那么這 3個時間是什么概念呢?還記得文章剛開始提到的web的發(fā)展歷史嗎?最初的超文本文檔上根本沒有圖片、音視頻等資源,所以它就只有文檔加載時間,即瀏覽器拿到HTML的時間,這就是它的性能指標(biāo)。當(dāng)富媒體網(wǎng)頁出現(xiàn)時,性能的關(guān)鍵指標(biāo)就從文檔加載時間變成了頁面加載時間(Page Load Time),即PTL 。
PTL的簡單定義就是:“ 瀏覽器中的加載旋轉(zhuǎn)圖標(biāo)停止旋轉(zhuǎn)的時間。”即瀏覽器中的onload事件,這個事件由瀏覽器在文檔及其所有依賴資源(javascript、圖片等)下載完畢時觸發(fā)。
大家還記得曾經(jīng)比較熱門的一道面試題:window.onload 和$(document).ready()的區(qū)別?在這里就可以比較清楚地解釋這個問題了。
onload是瀏覽器的內(nèi)置事件,ready是jQuery封裝的事件。
onload事件如上面所說,要等到頁面上所有資源(注意不是文檔,資源包括javascript,圖片等等)都下載完成時才觸發(fā),而ready事件是當(dāng)DOM結(jié)構(gòu)準(zhǔn)備好后就觸發(fā),即我們上面提到的DOM樹形結(jié)構(gòu),一旦瀏覽器拿到HTML文檔就會構(gòu)建DOM結(jié)構(gòu)。我們前面提到的三個測量指標(biāo),我們大體可以對應(yīng)文檔完成時間到ready,資源最后獲取時間到onload.
那么什么是最早渲染時間?
用戶訪問一個站點時,瀏覽器會先發(fā)出一個請求獲取html文檔,拿到html后開始解析并渲染到窗口。這個過程中需要知道以下兩個時間點:
Time Of First Byte
首字節(jié)時間。衡量網(wǎng)絡(luò)性能和后端程序的一個關(guān)鍵指標(biāo)。
Start Render Time
指用戶屏幕剛開始顯示某些內(nèi)容的時刻。
瀏覽器屏幕剛開始是一大片空白,繪制時會發(fā)生一些變化,可能是顯示背景、logo或者文字等。上面提到渲染樹的時候說過,DOM樹上會有一些非可視化的元素(例如html、head等),這些元素不會出現(xiàn)在最后的渲染樹里,即不會呈現(xiàn)在窗口上。所以繪制肯定需要先解析完head元素中的內(nèi)容。
一般情況下,CSS準(zhǔn)備就緒后,即可以開始繪制。css文件通常放在head中,所以大體上可以認(rèn)為瀏覽器開始渲染body標(biāo)簽的時間就是Start Render Time 。這個時間減去首字節(jié)時間,就是head標(biāo)簽的解析時間。
首屏?xí)r間(above the fold)
指用戶在沒有滾動頁面的時候看到的內(nèi)容渲染完成并且可以交互的時間。首屏一般指根據(jù)用戶屏幕分辨率數(shù)確定一個首屏線,首屏線以上即為首屏。這個區(qū)域本身也需要時間來渲染。這個區(qū)域的資源越多(css,js,img等),其渲染時間越長,首屏?xí)r間也就越長。
哪個時間最重要?
答案不唯一,需要根據(jù)應(yīng)用而定。一般來說最好讓用戶能夠盡早與重要內(nèi)容進(jìn)行交互。
這里推薦一個非常好用的在線工具 http://www.webpagetest.org/
用于顯示網(wǎng)頁加載過程的資源瀑布圖。(注意看這里的很多豎線,非常詳細(xì)地標(biāo)注了加載過程中各個階段的時間點)
開發(fā)者工具中的Timeline Tool 也可以看到類似信息,但沒有這個來自直觀和全面。開發(fā)者工具相關(guān)p/e0fb716a834f
這里提一個很簡單的問題:
瀏覽器是什么時候開始繪制頁面的?
答案:B . 繪制網(wǎng)頁需要渲染樹,構(gòu)建渲染樹需要DOM tree 和 CSS tree . 因此瀏覽器需要等到獲取了CSS后再繪制網(wǎng)頁。
文章開頭提到,交互式Web應(yīng)用揭開了揭開腳本、樣式和文檔之間復(fù)雜依賴關(guān)系的時代。這個是什么意思?到目前為止,在提到Javascript之前,瀏覽器呈現(xiàn)網(wǎng)頁的流程看起來還是很清晰的,從HTML文檔里提取DOM,從CSS資源里得到CSSOM,然后得到渲染樹,布局繪制,done!
然而網(wǎng)頁要交互,必然需要JavaScript的能力。然而隨之而來的,便是這個第三者帶來的復(fù)雜依賴關(guān)系
Javascript 擁有操作DOM和CSS的能力。當(dāng)HTML遇到<script>標(biāo)簽時,無法得知這個腳本將會對頁面進(jìn)行什么操作(增刪改查),所以瀏覽器只好先停止處理頁面,先執(zhí)行js代碼,然后再繼續(xù)處理頁面 。 JS阻塞DOM(js腳本之后的DOM)的解析和構(gòu)建。
腳本會嘗試訪問CSS屬性,所以CSS應(yīng)該在腳本執(zhí)行之前先處理完成
依賴關(guān)系形成:
JS阻塞DOM解析
CSS阻止執(zhí)行JS執(zhí)行,CSS同時還阻塞渲染
于是,DOM及CSSOM的構(gòu)建頻繁地交織在一起:DOM構(gòu)建在JS執(zhí)行完畢前無法進(jìn)行,而JS在CSSOM構(gòu)建完成前也無法進(jìn)行。獲取渲染樹的過程變得曲折,困難重重。而沒有渲染樹,自然也就沒有呈現(xiàn)。
從這個依賴關(guān)系我們能知道什么?
CSS阻塞渲染:渲染需要渲染樹,在CSSOM完成之前,無法渲染
CSS阻止JS執(zhí)行
渲染和腳本執(zhí)行都受樣式表的阻塞,所以我們必須讓CSS以最快的速度下載完。所以有了流行的樣式在上,腳本在下的優(yōu)化原則,我們必須以最快的速度將CSS下載完成。
javascript 和 CSS 的依賴關(guān)系
如果我們外聯(lián)css文件,內(nèi)聯(lián)js文件(js引擎的速度很快),那么這個文件里段落的顏色會是black 還是 red?
答案:red.(JS必須等待CSSOM,即使它已經(jīng)先于css文件到達(dá)瀏覽器)
關(guān)鍵呈現(xiàn)路徑(critical rendering path)
指瀏覽器所經(jīng)歷的一系列步驟,將HTML CSS和JavaScript轉(zhuǎn)換為在屏幕上呈現(xiàn)像素的過程。我們平常所說的提高網(wǎng)頁呈現(xiàn)速度,也可以看做是優(yōu)化關(guān)鍵呈現(xiàn)路徑。
做個小練習(xí):根據(jù)腳本畫一條簡單的關(guān)鍵呈現(xiàn)路徑
腳本
路徑圖
首先瀏覽器發(fā)出請求,獲取HTML文檔,然后開始解析,解析一半發(fā)現(xiàn)css和js資源,于是發(fā)出資源請求,獲取到資源后,開始構(gòu)建CSSOM,這個時候即使JS資源也已經(jīng)獲取到,但需要等待CSSOM的構(gòu)建,CSSOM構(gòu)建完以后開始執(zhí)行JS,這個時候DOM構(gòu)建需要停止下來等待JS執(zhí)行完以后才能繼續(xù),最后渲染。即使是這么簡單的網(wǎng)頁,也會存在很多依賴條件降低關(guān)鍵路徑的速度
關(guān)鍵呈現(xiàn)路徑指標(biāo)
關(guān)鍵資源數(shù)量
關(guān)鍵資源大小
關(guān)鍵路徑長度(往返客戶端和服務(wù)器端的次數(shù))
從這個路徑圖中,我們看到整個渲染過程共有2次請求,一個是請求基本的HTML文檔,一個是請求CSS文件,所以關(guān)鍵資源數(shù)據(jù)量有2個。關(guān)鍵資源大小也就是這兩個文件大小之和,即9KB。來往服務(wù)器的次數(shù)也是2次。在前端開發(fā)人員能做到的范圍內(nèi),提高網(wǎng)頁呈現(xiàn)速度即優(yōu)化關(guān)鍵呈現(xiàn)路徑,既然關(guān)鍵呈現(xiàn)路徑有具體的指標(biāo),那么我們在考慮優(yōu)化策略的時候,就可以根據(jù)這三個具體的指標(biāo)來思考。
一般優(yōu)化策略
減小通過網(wǎng)絡(luò)發(fā)送的數(shù)據(jù)量
減少關(guān)鍵關(guān)鍵資源的數(shù)量
縮短關(guān)鍵呈現(xiàn)路徑的長度
未完待續(xù)...
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com