一、瀏覽器概述
??目前的主流瀏覽器有5個:Internet Explorer、Firefox、Safari、Chrome和Opera瀏覽器。根據 StatCounter 瀏覽器統計數據,目前(截止2019 年 5 月)Firefox、Safari 和 Chrome 瀏覽器的總市場占有率將近 83.66%。由此可見,如今開放源代碼瀏覽器在瀏覽器市場中占據了非常堅實的部分。
??以上5種瀏覽器由于有著不同的瀏覽器內核,造成同樣的html頁面有著不同呈現。Internet Explorer的內核是Trident;Firefox的內核是Gecko;Chrome、Safari內核是Webkit;Opera的內核則是Presto。
二、瀏覽器渲染過程
??我們先大致看下瀏覽器渲染關鍵路徑圖:
1、HTML解析,構建DOM樹
??瀏覽器從網絡或硬盤中獲得HTML字節數據后會經過以下流程將字節解析為DOM樹:
- 字符編碼:先將HTML的原始字節數據轉換為文件指定編碼的字符。
- 令牌化:然后瀏覽器會根據HTML規范來將字符串轉換成各種令牌(如
<html>
、<body>
、<p>
這樣的標簽以及標簽中的字符串和屬性等都會被轉化為令牌,每個令牌具有特殊含義和規則)。 - 生成節點對象:接著每個令牌都會被轉換成定義其屬性和規則的對象,即節點對象。
- 構建DOM樹:最后將節點對象構建成樹形結構,即DOM樹。HTML標簽之間有復雜的父子關系,樹形結構剛好可以詮釋這樣的關系。
??下面通過一段HTML代碼與配圖更好的理解“字節 -> 字符 -> 令牌-> 節點對象 -> 對象模型”這個過程:
<html><head><meta name="viewport" content="width=device-width,initial-scale=1"><link href="style.css" rel="stylesheet"><title>Critical Path</title></head><body><p>Hello <span>web performance</span> students!</p><div><img src="test.png"></div></body>
</html>
復制代碼
2、CSS解析,構建CSSOM樹
??瀏覽器解析遇到<link>
標簽時,瀏覽器就開始解析CSS,像構建DOM樹一樣構建CSSOM樹。style.css的代碼如下:
body { font-size: 16px }
p { font-weight: bold }
span { color: red }
p span { display: none }
img { float: right }
復制代碼
3、Render Tree
??在構建了DOM樹和CSSOM樹之后,瀏覽器只是擁有2個相互獨立的對象集合,DOM樹描述的文檔結構和內容,CSSOM樹描述了對應文檔的樣式規則,想要渲染出頁面,就需要將DOM樹、CSSOM樹結合在一起,構建渲染樹。
4、Layout
??渲染樹構建好后,瀏覽器得到了每個節點的內容與樣式,下一步就是需要計算每個節點在瀏覽器窗口的確切位置與大小,即layout布局。
??布局階段,從渲染樹的根節點開始遍歷,采用盒子模型的模式來表示每個節點與其他元素之間的距離,從而確定每個元素在屏幕內的位置與大小。
盒子模型:包括外邊距(margin),內邊距(padding),邊框(border),內容(content)。標準盒子模型width/height = content;IE盒子模型width/height = content + padding + border。
5、Paint繪制頁面
??當Layout布局完成后,瀏覽器會立即發出Paint事件,開始講渲染樹繪制成像素,繪制所需要的時間跟CSS樣式的復雜度成正比,繪制完成后,用戶才能看到頁面在屏幕中的最終呈現效果。
??如果想更詳細地體驗瀏覽器渲染流程,可以使用Chrome開發者工具中的Performance面板,錄制瀏覽器從請求直到渲染完成的過程,如下圖所示:
三、渲染優化方案
1、優化渲染關鍵路徑方案
??通過優化渲染關鍵路徑,可以優化頁面渲染性能,減少頁面白屏時間。
- 優化JS:JavaScript文件加載會阻塞DOM樹的構建,可以給
<script>
標簽添加異步屬性async,這樣瀏覽器的HTML解析就不會被js文件阻塞。 - 優化CSS:瀏覽器每次遇到
<link>
標簽時,瀏覽器就需要向服務器發出請求獲得CSS文件,然后才繼續構建DOM樹和CSSOM樹,可以合并所有CSS成一個文件,減少HTTP請求,減少關鍵資源往返加載的時間,優化渲染速度。
2、其他優化方案
- 加載部分HTML
瀏覽器先加載主要HTML初始化靜態部分,動態變化的HTML內容通過Ajax請求加載。這樣可以減少瀏覽器構建DOM樹的工作量,讓用戶感覺頁面加載速度很快。 - 壓縮
對HTML、CSS、JavaScript這些文件去除冗余字符(例如不必要的注釋、空格符和換行符等),再進行壓縮,減小文件數據大小,加快瀏覽器解析文件編碼。 - 圖片加載優化
1)小圖標合并成雪碧圖,進而減少img的HTTP請求次數;
2)圖片加載較多時,采用懶加載的方案,用戶滾動頁面可視區時再加載渲染圖片。 - HTTP緩存
瀏覽器自帶了HTTP緩存的功能,只需要確保每個服務器響應的頭部都包含了以下的屬性:
1)ETag: ETag是一個傳遞驗證令牌,它對資源的更新進行檢查,如果資源未發生變化時不會傳送任何數據。當瀏覽器發送一個請求時,會把ETag一起發送到服務器,服務器會根據當前資源核對令牌(ETag通常是對內容進行Hash后得出的一個指紋),如果資源未發生變化,服務器將返回304 Not Modified響應,這時瀏覽器不必再次下載資源,而是繼續復用緩存。
2)Cache-Control: Cache-Control定義了緩存的策略,它規定在什么條件下可以緩存響應以及可以緩存多久。
a、no-cache: no-cache表示必須先與服務器確認返回的響應是否發生了變化,然后才能使用該響應來滿足后續對同一網址的請求(每次都會根據ETag對服務器發送請求來確認變化,如果未發生變化,瀏覽器不會下載資源)。no-store直接禁止瀏覽器以及所有中間緩存存儲任何版本的返回響應。簡單的說,該策略會禁止任何緩存,每次發送請求時,都會完整地下載服務器的響應。
b、public&private: 如果響應被標記為public,則即使它有關聯的HTTP身份驗證,甚至響應狀態代碼通常無法緩存,瀏覽器也可以緩存響應。如果響應被標記為private,那么這個響應通常只為單個用戶緩存,因此不允許任何中間緩存(CDN)對其進行緩存,private一般用在緩存用戶私人信息頁面。
c、max-age: max-age定義了從請求時間開始,緩存的最長時間,單位為秒。
小結
??今天瀏覽器渲染過程和優化方案就介紹到這里,大家如果有更多更好的頁面性能優化方案可以多多交流,評論區歡迎留言~~