html載入過程

Sue1024發表於2019-02-16

HTML載入流程圖

在位址列輸入url,返回html後,瀏覽器開始順序載入並渲染DOM

Body標籤

當瀏覽器遇到body標籤才算真正開始載入並渲染DOM,此時會有以下幾種情況:

DOM元素

瀏覽器遇到dom元素時,正常順序載入,邊載入邊渲染

內聯CSS

當遇到內聯CSS時,瀏覽器繼續載入,但渲染被阻塞,此時會生成新的CSS Rule Tree,生成後重新渲染介面

外聯CSS

當遇到外聯CSS(link標籤),瀏覽器啟一個執行緒載入css檔案,DOM繼續載入但渲染被阻塞

內聯Javascript

當遇到內聯Javascript,瀏覽器開始執行這段指令碼,DOM的載入和渲染同時被阻塞(由於JavaScript有可能會更改DOM Tree和Render Tree,因此同時被阻塞)

外聯Javascript

當遇到外聯Javascript,瀏覽器開始下載這段指令碼,下載成功後執行它,這整個過程DOM的載入和渲染同時被阻塞

Example

用一個例子解釋一下

<html>
<body>
  <h2>Hello</h2>
  <script>
    function print(){
        console.log(`first script`, document.querySelectorAll(`h2`));
    }
    print();
    setTimeout(print);
  </script>
  <script src="http://cdn.bootcss.com/bootstrap/4.0.0-alpha.4/js/bootstrap.js"></script>
  <h2>World</h2>
  <script> console.log(`second script`, document.querySelectorAll(`h2`)); </script>
</body>
</html>

在js檔案下載的過程中,js後面的元素沒有被載入,也沒有呈現在介面上,說明js檔案的下載阻塞了DOM的解析並渲染

<html>
<body>
  <h2>Hello</h2>
  <script>
    function print(){
        console.log(`first script`, document.querySelectorAll(`h2`));
    }
    print();
    setTimeout(print);
  </script>
  <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/4.0.0-alpha.4/css/bootstrap.css">
  <h2>World</h2>
  <script> console.log(`second script`, document.querySelectorAll(`h2`)); </script>
</body>
</html>

在css檔案仍在下載的過程中,已經可以列印出兩個<h>,可以看出css檔案的載入阻塞了DOM渲染但沒有阻塞DOM載入

defer 與 async

如果我們執行以下程式碼,首先載入外部Javascript檔案,然後載入DOM其他內容:

<html>
<body>
  <script src="https://cdn.bootcss.com/docsearch.js/2.5.2/docsearch.min.js"></script>
  <h2>Hello World</h2>
</body>
</html>

如我們所料,檔案沒有下載並執行完畢,Hello World是不會列印出來的。

如果我們為外部Javascript新增defer或async屬性,那麼它的下載就不會阻塞DOM其他內容的載入:

<html>
<body>
  <script async src="https://cdn.bootcss.com/docsearch.js/2.5.2/docsearch.min.js"></script>
  <h2>Hello World</h2>
</body>
</html>


關於defer與async屬性的區別,請參考我的另一篇文章:
Javascript高階程式設計讀書筆記——在HTML中使用Javascript

相關文章