在 HTML 中,當 <script> 標籤放在 <head> 時,建議加上 defer 屬性的原因與網頁的載入和執行順序有關。讓我詳細解釋一下:
問題背景
通常,當瀏覽器解析 HTML 文件時,它是從上到下逐步處理的。如果在 <head> 中放入 <script> 標籤,且該腳本是外部檔案(例如 <script src=”example.js”></script>),瀏覽器會在遇到這個標籤時立即停止解析 HTML,去下載並執行該腳本。這會導致一個問題:如果腳本需要操作頁面中的 DOM 元素(例如 <div> 或 <button>),而這些元素位於 <body> 中尚未被解析,腳本執行時就會找不到這些元素,進而引發錯誤或無法正常運作。
此外,這種行為還會延遲頁面的渲染,因為瀏覽器必須等待腳本下載和執行完畢後,才能繼續處理後續的 HTML 內容。這對用戶體驗來說是不利的,尤其是在腳本檔案較大或網路速度較慢的情況下。
defer 的作用
defer 屬性告訴瀏覽器,在遇到 <script> 標籤時,可以繼續解析 HTML,不必等待腳本的下載和執行。具體來說:
- 非阻塞載入:瀏覽器會在背景中下載腳本檔案,同時繼續解析 HTML 和構建 DOM。
- 延遲執行:腳本只會在整個 HTML 文件解析完成(即 DOM 構建完成)後才執行。
- 順序保證:如果有多個帶有 defer 的 <script>,它們會按照在 HTML 中出現的順序依次執行。
因此,當 <script> 放在 <head> 並加上 defer 時,你可以確保:
腳本執行時,DOM 已完全可用,避免找不到元素的情況。
頁面不會因為腳本載入而延遲渲染。
範例
沒有 defer 的情況
<head>
<script src="example.js"></script>
</head>
<body>
<div id="myDiv">Hello</div>
</body>
假設 example.js 包含:
console.log(document.getElementById("myDiv"));
結果會是 null,因為腳本在 <body> 中的 <div> 被解析前就執行了。
加上 defer 的情況
<head>
<script src="example.js" defer></script>
</head>
<body>
<div id="myDiv">Hello</div>
</body>
這次,腳本會等到 HTML 解析完成後才執行,document.getElementById(“myDiv”) 會正確返回 <div> 元素。
什麼時候需要 defer?
- 當 <script> 放在 <head> 中,且腳本需要操作 DOM 時。
- 當你希望腳本按順序執行,但不想阻塞頁面載入時。
替代方案
如果你不使用 defer,另一個常見做法是將 <script> 放在 </body> 結束標籤之前。這樣,腳本會在 DOM 解析完成後自然執行,不需要額外屬性。但若腳本必須出現在 <head>(例如某些第三方腳本或初始化需求),defer 是更好的選擇。
總結
在 <head> 中的 <script> 加上 defer,是為了避免阻塞 HTML 解析,確保腳本在 DOM 準備好後執行,並提升頁面載入效能。這是一個現代網頁開發的最佳實踐,特別是在處理外部腳本時。
探索更多來自 雖然沒準備什麼資料 的內容
訂閱即可透過電子郵件收到最新文章。