把Script標籤放在頁面最底部的`</body>`之前和之後有什麼區別?瀏覽器會如何解析它們?

王铁柱6發表於2024-11-24

<script> 標籤放在 <body> 的底部,即 </body> 結束標籤之前,和放在 </body> 之後,主要區別在於瀏覽器解析和渲染頁面的方式,以及這會如何影響使用者體驗。

1. <script></body> 之前(推薦):

  • 瀏覽器解析: 瀏覽器解析 HTML 文件是自上而下的。當遇到 <script> 標籤時,會暫停 HTML 解析,下載並執行 JavaScript 程式碼。 將指令碼放在 </body> 之前意味著在解析完頁面主要內容(HTML 結構)之後才會執行指令碼。
  • 渲染: 這允許瀏覽器先渲染頁面內容,使用者可以更快地看到頁面,即使指令碼仍在下載或執行。這改善了使用者體驗,特別是對於包含大量 JavaScript 或網路連線較慢的使用者。
  • DOMContentLoaded 事件: 所有HTML解析完畢後會觸發 DOMContentLoaded 事件。放在 </body> 結束標籤之前的指令碼會在 DOMContentLoaded 事件觸發之前執行,這意味著指令碼可以訪問所有 DOM 元素。

2. <script></body> 之後:

  • 瀏覽器解析: 與之前類似,瀏覽器會暫停 HTML 解析來下載和執行指令碼。 不同的是,此時整個 HTML 文件(包括 </body>)都已經解析完畢。
  • 渲染: 由於指令碼在 HTML 解析完成後才執行,因此頁面渲染可能會被阻塞,直到指令碼下載和執行完畢。如果指令碼很大或網路連線慢,使用者可能會看到空白頁面或未完全載入的頁面,導致糟糕的使用者體驗。
  • load 事件: 放在 </body> 結束標籤之後的指令碼會在 load 事件觸發之前執行。 load 事件在頁面完全載入所有資源(包括圖片、樣式表等)後觸發。

總結:

幾乎所有情況下,都應該將 <script> 標籤放在 </body> 結束標籤之前。 這確保了瀏覽器可以儘快渲染頁面內容,提供更好的使用者體驗。 只有在某些特殊情況下,例如指令碼需要在所有頁面資源載入完成後才執行,才需要將指令碼放在 </body> 之後。 即使在這種情況下,也建議使用 deferasync 屬性來最佳化指令碼載入和執行,避免阻塞頁面渲染。

deferasync 屬性:

  • defer 使用 defer 屬性的指令碼會在 HTML 解析完成後,DOMContentLoaded 事件觸發之前執行。指令碼會按它們在 HTML 中出現的順序執行。
  • async 使用 async 屬性的指令碼會非同步下載和執行,不會阻塞 HTML 解析。指令碼執行的順序不確定,哪個先下載完哪個先執行。

示例:

<!DOCTYPE html>
<html>
<head>
  <title>Script Tag Placement</title>
</head>
<body>
  <h1>My Website</h1>
  <p>Some content here.</p>

  <script src="script1.js" defer></script>  <!-- 推薦做法 -->
  <script src="script2.js" async></script> <!-- 非同步載入 -->

</body>
</html>

在這個例子中,script1.js 會在 HTML 解析完成後,DOMContentLoaded 事件觸發之前執行,而 script2.js 會非同步載入和執行。

總之,為了最佳效能和使用者體驗,請將指令碼放在 </body> 結束標籤之前,並根據需要使用 deferasync 屬性。

相關文章