HTML渲染過程詳解


轉載於  我的小樹林  原址:http://www.cnblogs.com/dojo-lzz/p/3983335.html



HTML渲染過程詳解

  無意中看到寒冬關於前端的九個問題,細細想來我也只是對第一、二、九問有所瞭解,正好也趁着這個機會梳理一下自己的知識體系。由於本人對http協議以及dns對url的解析問題並不瞭解,所以這裏之探討url請求加載到瀏覽器端時,瀏覽器對html的解析到呈現過程,後來經過幾位道友分享,整理了一下url解析的過程,如下:

  1. 用戶輸入url地址,瀏覽器根據域名尋找IP地址
  2. 瀏覽器向服務器發送http請求,如果服務器段返回以301之類的重定向,瀏覽器根據相應頭中的location再次發送請求
  3. 服務器端接受請求,處理請求生成html代碼,返回給瀏覽器,這時的html頁面代碼可能是經過壓縮的
  4. 瀏覽器接收服務器響應結果,如果有壓縮則首先進行解壓處理,緊接着就是頁面解析渲染

  解析渲染該過程主要分爲以下步驟:

  1. 解析HTML
  2. 構建DOM樹
  3. DOM樹與CSS樣式進行附着構造呈現樹
  4. 佈局
  5. 繪製

解析與構建DOM樹

  前兩步我們放在一起討論,瀏覽器的實際工作也是將他們放在一起進行的。對於HTML瀏覽器有專門的html解析器來解析HTML,並在解析的過程中構建DOM樹。在這裏我們討論兩種DOM元素的解析,即樣式(link、style)與腳本文件(script)。由於瀏覽器採用自上而下的方式解析,在遇到這兩種元素時都會阻塞瀏覽器的解析,直到外部資源加載並解析或執行完畢後纔會繼續向下解析html。對於樣式與腳本的先後順序同樣也會影響到瀏覽器的解析過程,究其原因主要在於:script腳本執行過程中可能會修改html界面(如document.write函數);DOM節點的CSS樣式會影響js的執行結果。在我的測試中得到以下四條結論:

  1)外部樣式會阻塞後續腳本執行,直到外部樣式加載並解析完畢。

 View Code

  2)外部樣式不會阻塞後續外部腳本的加載,但會阻塞外部腳本的執行。

 主頁代碼
 外部腳本

  從瀑布圖中我們可以看到,外部腳本與外部樣式是並行加載,但直到外部樣式加載完畢,外部腳本纔開始執行

  3)如果後續外部腳本含有async屬性(IE下爲defer),則外部樣式不會阻塞該腳本的加載與執行

 View Code

  從瀑布圖中可以看到外部腳本的加載與執行並不受link的阻塞

  4)對於動態創建的link標籤不會阻塞其後動態創建的script的加載與執行,不管script標籤是否具有async屬性,但對於其他非動態創建的script,以上三條結論仍適用

 View Code

  這是最終頁面結構

  通過瀑布圖與頁面結果可以看到動態創建的外部腳本並未受link的阻塞。

  link或style標籤都會被解析成DOM節點。瀏覽器對於樣式表還會生成CSSStyleSheet對象(C++代碼),他集成子CSSStyle,指標是樣式表對象而不管該對象來自於Style還是link。該對象主要包含以下幾個重要屬性和方法

  • CSSRules 即css樣式代碼
  • type 表示樣式表類型的字符串。對CSS樣式表而言,這個字符串是“type/css”。
  • href 通過link生成的爲樣式鏈接,否則爲undefined
  • insertRule(rule,index):向cssRules集合中指定的位置插入rule字符串。IE不支持這個方法,但支持一個類似的addRule()方法。
  • deleteRule(index):刪除cssRules集合中指定的位置的規則。IE不支持這個方法,但支持一個類似的removeRule()方法。

  文檔中對於所有的樣式表集合可以通過document.styleSheets來訪問。同時對於style或link DOM元素可以通過element.sheet來訪問CSSStyleSheet對象,IE中則通過element.styleSheet來訪問。

  html解析完畢,DOM樹創建完成後DOMContentLoaded事件即觸發,這時候可以用過script來操作DOM節點。

 

構建呈現樹  

  HTML解析完畢後,開始構建呈現樹RenderTree,這一步的主要工作在於將css樣式應用到DOM節點上,WebKit內核將這一過程稱爲附着,其他瀏覽器有不同的概念。對前端工程師而言這個過程會涉及到CSS層疊問題。

  首先將根據樣式重要性排序,由低到高依次爲:

    1. 瀏覽器聲明
    2. 用戶普通聲明
    3. 作者普通聲明
    4. 作者重要聲明
    5. 用戶重要聲明

  對於同一重要級別,則是根據CSS選擇符的特指度來判定優先級;一條樣式聲明的特指度由以下四個部分決定:S-I-C-E

    1. 聲明來自內聯的style屬性則 S+1;
    2. 聲明中含有id屬性則 I+1;
    3. 聲明中含有類、僞類、屬性選擇器則 C+1;
    4. 生命中含有元素、僞元素選擇器則 E+1;

  特指度的比較類似於兩個字符串之間比較大小。

  呈現樹的每一個節點即爲與其相對應的DOM節點的CSS框,框的類型與DOM節點的display屬性有關,block元素生成block框,inline元素生成inline框。每一個呈現樹節點都有與之相對應的DOM節點,但DOM節點不一定有與之相對應的呈現樹節點,比如display屬性爲none的DOM節點,而且呈現樹節點在呈現樹中的位置與他們在DOM樹中的位置不一定相同,比如float與絕對定位元素。

  下圖爲呈現樹與其相對應的DOM樹節點

佈局

  呈現樹構造完成後瀏覽器便進行佈局處理,及計算每個呈現樹節點的大小和位置信息。有道友可能要問,前面已將樣式附着到DOM節點上,不是已經有了樣式信息爲何還要計算大小。這裏可以這樣理解,以上包含大小的樣式信息只是存在內存裏,並沒有實際使用,瀏覽器要根據窗口的實際大小來處理呈現樹節點的實際顯示大小和位置,比如對於margin爲auto的處理。

  佈局是一個遞歸過程,從跟呈現節點開始,遞歸遍歷子節點,計算集合幾何信息。具體過程還是比較複雜偶也不甚瞭解,道友們還是查閱其他資料吧。

 

繪製

   佈局完成後,便是將呈現樹繪製出來顯示在屏幕上。對於每一個呈現樹節點來說,主要繪製順序如下:

  1. 背景顏色
  2. 背景圖片
  3. 邊框
  4. 子呈現樹節點
  5. 輪廓

readyState共有五種狀態,分別是:

  • uninitialized:初始狀態
  • loading:document加載中
  • loaded: document加載完成
  • interactive:已加載並可與用戶交互,但還需要加載圖片等其他資源
  • complete:全部資源加載完成

  1. 解析HTML結構
  2. 加載外部腳本和樣式表文件(loading)
  3. 解析並執行腳本
  4. DOM樹構建完成(readyState:interactive)
  5. 加載外部資源文件(圖片等)
  6. 頁面加載完成(readyState:complete)

IE瀏覽器的最終狀態有時候只到loaded而不會到complete,有時候也可能直接跳過loaded直接到達complete狀態。


另附篇同樣寫得不錯的文章:


1、瀏覽器加載、解析、渲染的過程  http://blog.csdn.net/xiaozhuxmen/article/details/52014901

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章