聊聊瀏覽器的那些事兒

鄒R-ainna發表於2019-02-15

主流瀏覽器

目前我們使用的主流瀏覽器包括:chrome, firefox, ie, safari, opera, uc等等。其中chrome瀏覽器所佔的全球市場份額最高,其次是IE。下面截圖資料來源於統計網站 www.netmarketshare.com/

394b0beff48072dc26adfcc01d2a8bc7

瀏覽器的主要目的就是向伺服器傳送請求,獲取並展示伺服器上的資源,資原始檔可以是html文件,也可以是pdf,jpg等其他型別的檔案。

瀏覽器元件

使用者操作介面:包括位址列、前進/後退按鈕、書籤選單等。

瀏覽器引擎:在使用者介面和呈現引擎之間傳輸指令。

呈現引擎:展示所請求的內容,比如解析HTML文件和CSS內容,將頁面展示給使用者瀏覽。

網路:用於網路呼叫,比如發起HTTP請求。其底層實現跟平臺無關。

使用者介面後端:用於繪製基本的視窗小部件,比如彈窗等。其底層使用作業系統的使用者介面方法。

JavaScript直譯器:用於解釋和執行JS程式碼。

資料儲存:用於瀏覽器在硬碟上儲存資料,比如cookie,local storage等。HTML5的網路資料庫就是瀏覽器內的完整的輕量的資料庫。

bf353b96e1f5dcc3695c5151a5551391

chrome瀏覽器的每個標籤頁分別對應一個呈現引擎例項,每個標籤頁都是一個獨立的程式。

呈現引擎主流程

firefox使用的呈現引擎是 Mozilla 公司自制的 “Gecko” 引擎。Safari 和 chrome 使用的是 “Webkit” 引擎。 IE 使用的是 “trident” 引擎。webkit 是原始碼開放的呈現引擎。

呈現引擎通過網路層獲取到請求文件的內容後,進行如下流程的解析:

993bd8519803ef6134d172f9d87bf9e9

  1. 解析HTML文件生成DOM構造樹。在遍歷DOM樹的同時,會請求外鏈的樣式檔案和指令碼檔案等其他資原始檔。CSS檔案獲取後同時解析該CSS檔案,生成CSSOM樹。
  2. DOM樹和CSSOM樹結合後生成Render樹。Render樹是包含多個視覺屬性(比如樣式和尺寸)的矩形。矩形的排列順序為節點在螢幕上顯示的順序。
  3. Render樹構建完成後,進入layout佈局階段。也就是對每個節點在螢幕上展示的位置分配具體的座標。此時節點的位置是有層級覆蓋的。
  4. Render樹的繪製。呈現引擎遍歷Render樹,由使用者介面後端層將每個節點繪製出來。呈現引擎在繪製時不會等到整個HTML檔案解析完畢,而是一邊接收內容,一邊繪製。

b5ad674ddb15e9cff14a4f436b52b314

瀏覽器如何解析HTML文件

瀏覽器使用HTML解析器將HTML標記解析成解析樹。解析器輸出的“解析樹”是由DOM元素和屬性節點構成的樹形結構,DOM是HTML文件的物件表示,同時也是JS呼叫的基礎。

因為HTML語言的包容性,HTML解析器無法使用常規的自上而下或自下而上的解析器進行解析,所以使用自定義的解析器來解析。解析過程包括兩個階段:標記化和樹構建。

標記化:是詞法分析過程,將輸入內容分析成多個標記。HTML標記包括起始標記,結束標記,屬性名稱和屬性值。

樹構建:標記生成器識別標記後,傳遞給樹構建器,由樹構造器進行處理,然後再接受下一個字元繼續識別,繼續傳遞給樹構建器,如此迴圈直到輸入的結束。

26a18229d404c9e18e760e456c89d800

例如:下面HTML標記化過程

<html>
  <body>
    Hello world
  </body>
</html>
複製程式碼

初始狀態是資料狀態。遇到< 字元時,狀態更改為“標記開啟狀態”。接收一個 a-z 字元會建立“起始標記”,狀態更改為“標記名稱狀態”。這個狀態會一直保持到接收 > 字元。在此期間接收的每個字元都會附加到新的標記名稱上。在本例中,我們建立的標記是 html 標記。

遇到 > 標記時,會傳送當前的標記,狀態改回“資料狀態”。 標記也會進行同樣的處理。目前 html 和 body 標記均已發出。現在我們回到“資料狀態”。接收到 Hello world 中的 H 字元時,將建立併傳送字元標記,直到接收 中的 <。我們將為 Hello world 中的每個字元都傳送一個字元標記。

現在我們回到“標記開啟狀態”。接收下一個輸入字元 / 時,會建立 end tag token 並改為“標記名稱狀態”。我們會再次保持這個狀態,直到接收 >。然後將傳送新的標記,並回到“資料狀態”。 輸入也會進行同樣的處理。

例如:下面HTML的樹構建過程

<html>
  <body>
    Hello world
  </body>
</html>
複製程式碼

樹構建階段的輸入是一個來自標記化階段的標記序列。第一個模式是“initial mode”。接收 HTML 標記後轉為“before html”模式,並在這個模式下重新處理此標記。這樣會建立一個 HTMLHtmlElement 元素,並將其附加到 Document 根物件上。

然後狀態將改為“before head”。此時我們接收“body”標記。即使我們的示例中沒有“head”標記,系統也會隱式建立一個 HTMLHeadElement,並將其新增到樹中。

現在我們進入了“in head”模式,然後轉入“after head”模式。系統對 body 標記進行重新處理,建立並插入 HTMLBodyElement,同時模式轉變為“in body”。

現在,接收由“Hello world”字串生成的一系列字元標記。接收第一個字元時會建立並插入“Text”節點,而其他字元也將附加到該節點。

接收 body 結束標記會觸發“after body”模式。現在我們將接收 HTML 結束標記,然後進入“after after body”模式。接收到檔案結束標記後,解析過程就此結束。

瀏覽器解析完成的操作

瀏覽器解析完成後,將文件標註為互動狀態,並處理那些在文件解析完成後才執行的指令碼。然後將文件狀態設定為“完成”,並觸發load載入事件。

參考文章: www.html5rocks.com/zh/tutorial…

相關文章