在位址列輸入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