解析-HTML 解析器

4-解析-HTML 解析器

由於 HTML 語言在語法層面並有那麼嚴格的語法規則,致使常規的解析器並不能解析HTML文檔,對應的解決方案讓瀏覽器廠商自定義 HTML 解析器。那麼,讓咱們一塊兒梳理一下 HTML 解析器究竟是什麼吧~html

輸入(語法)

由於 HTML 語法是由 W3C 組織建立的規範中進行定義的,並且語法格式是由 DTD (Document Type Definition)定義的,該格式中定義了語言中容許的元素、屬性和層次結構,適用一切的 SGML (Standard Gerneralized Markup Languge)族的語言。爲了在發展的進程中向後兼容老版本的內容,DTD 存在兩種模式,嚴格模式徹底遵照 HTML 規範,其餘模式支持老的瀏覽器使用的編輯。web

解析算法

由於 HTML 文檔語法特性(包容性),以及在解析過程當中存在腳本會改變 HTML 文檔(如: document.write),致使沒法使用自上而下或是自下而上的解析器進行解析。算法

解析過程前半段是詞法分析,也就是標記化(tokenization),總體算法的核心就是狀態機的改變(就是解析過程當中有一個標識當前狀態應是解析到哪個階段了)。瀏覽器

同時構建 DOM 樹,也就是樹構建(tree construction)過程,該過程就是咱們在「解析-理論剖析」講述的同樣,將對應的標記去擊中語法,而後添加到 DOM 樹上。此過程當中也有一個狀態機去維護對應的階段。異步

最後 DOM 樹是 HTML 文檔的映射關係和存留 HTML 元素對外的接口(如: 對JS),每個節點是由 DOM 元素和節點屬性組成。看一個例子:post

<html>
  <body>
    <p>
      Hello World
    </p>
    <div> <img src="example.png"/></div>
  </body>
</html>
複製代碼

解析完,進入交互階段開始解析處於 'deferred mode' (that should be executed after the document is parsed)的腳本,執行完這些腳本後,文檔狀態爲 complete,觸發 load 事件。spa

由於解析器是瀏覽器廠商的自定義,而 HTML語法特性比較特殊,因此解析器要有相關的容錯機制,而這機制並非 HTML 規範中強制規定,而是瀏覽器發展過程當中的產品(友商之間互抄好的地方唄),可是後期的 HTML 5 規範中有部分容錯機制的要求(webkit 的 HTML 解析器就有這樣的註釋)。firefox

上述只是描述到 HTML 文檔的解析,那腳本和樣式的解析順序呢?線程

由於 web 的模型式同步的緣由,若是碰見內部 <script> 標籤,就會中斷 HTML 解析,開始執行腳本,直到腳本執行完畢,而遇到外部的腳本,解析一樣中斷直到請求腳本回來。這些解析模式在 HTML 4 5規範中有所描述。3d

畢竟忽然中斷 HTML 解析仍是會影響頁面展現的時間,那樣咱們須要規避沒必要要的因腳本而中斷解析,那就是給 <script>添加 defer 屬性,這是 HTML 5中給腳本標記爲異步的標識,這樣腳本經過不一樣的線程解析和執行。

當有腳本在執行的過程當中,會觸發「預解析」,此時是其餘線程繼續解析文檔,找到須要請求加載的資源,加載這部分資源(並行加載,提升總體速度)。預解析只解析外部文件(外部腳本、樣式或圖片),此過程不修改 DOM 樹。

樣式方面,由於解析樣式並不會影響 DOM 樹,因此不須要中斷文檔解析。但同時存在一個問題,當腳本獲取樣式信息時,但此時樣式並無加載就會報錯。對應的解決手段就是阻塞腳本,但不用瀏覽器阻塞的階段不一樣,firefox是當樣式加載或解析的時候,會阻塞全部的腳本;而 webkit 是當腳本去訪問那些肯定會被爲加載樣式影響到的屬性時,阻塞腳本。

以上是剛剛完成了 DOM 樹的構建,那咱們立刻進入後續階段咯~

下一篇文章

渲染樹-理論剖析

相關文章
相關標籤/搜索