【Html】解析 <script> 載入機制與 defer、async 屬性

【Html】解析 <script> 載入機制與 defer、async 屬性

本篇重點

  • <script> 的載入與執行特性
  • deferasync 的功能與特性
  • type="module" 與 defer 的關係

<script> 的載入與執行機制

HTML 解析器在遇到 <script src="xxx.js"> 時,預設行為是:

  1. 暫停 HTML 解析
  2. 下載 script 檔案
  3. 立即執行 script
  4. 繼續解析 HTML

因此若未加上任何屬性(即同步載入),每個 script 標籤都可能造成主執行緒中斷,延後頁面渲染

無屬性(同步載入)

功能與特性

  • 預設為同步模式,遇到 <script> 時會暫停 HTML 解析,等待下載並執行完成後才繼續解析。
  • 若放在 <head>,可能導致白屏延遲(render-blocking)。

使用時機

適合需要立即執行或初始化頁面邏輯的腳本。

  • 在 DOM 尚未完全建立前,就必須修改或偵測初始狀態的功能(例如 polyfill 引入)。
  • 須確保執行順序固定的腳本。

範例:

polyfill.js 的執行會阻塞後續的 HTML 載入。

html
1
2
3
<head>
<script src="polyfill.js"></script>
</head>

健忘筆記

polyfill 能夠產生舊瀏覽器所支援的程式版本,讓舊瀏覽器可以使用新的功能。

defer 屬性

功能與特性

  • 表示 script 延遲執行,直到整份 HTML 解析完成
  • 在解析 HTML 的同時開始非同步下載腳本,等到 DOM 結構建立完畢後才執行。
  • 如果有多個帶 defer 的 script,會依照在文件中的出現順序執行。
  • 執行時機在 DOMContentLoaded 事件前。

健忘筆記

DOMContentLoaded 事件和 Load 事件

  • DOMContentLoaded 執行時機在整個 DOM 樹建構完成後(不含圖片、CSS、iframe 等外部資源)
  • load 執行時機在所有資源都載入完成(包含圖片、CSS、iframe、JS等)

使用時機

適合需要存取或操作 DOM 元素的程式

範例

DOM 已解析完成,main.js 可以安全地操作 DOM。

html
1
<script defer src="main.js"></script>

執行順序

html
1
2
3
4
<p>Start parsing...</p>
<script defer src="a.js"></script>
<script defer src="b.js"></script>
<p>Parsing continues...</p>
  1. HTML 解析不中斷
  2. a.jsb.js 同步下載
  3. HTML 完成解析後,依序執行 a.jsb.js

async 屬性

功能與特性

  • 表示該 script 非同步載入與執行,不會阻塞 HTML 解析。
  • 載入完成立即執行,不會等待 DOM 完成。
  • 如果有多個帶 async 的 script,執行順序不保證和文件檔案順序一致,取決於哪個 script 先下載完。

使用時機

適合與頁面內容無依賴關係的外部腳本,例如:

  • 網站統計工具(例如:Google Analytics)
  • 廣告追蹤腳本
  • 第三方 SDK

範例:

adsbygoogle.js 會在下載完成的那一刻立刻執行,不干擾主要頁面邏輯。

html
1
<script data-ad-client="ca-pub-11111" src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js" async></script>

type="module" 與 defer 的關係

當使用 <script type="module"> 時,模組腳本預設具有 defer 的行為:

html
1
<script type="module" src="app.js"></script>

因此模組不會阻塞 HTML 解析,會在 DOM 解析完成後執行。

結論

屬性是否阻塞 HTML 解析下載時機執行時機多腳本執行順序適用情境
無屬性立即下載下載完成即執行順序固定需立即執行、初始化頁面邏輯
defer與解析並行DOM 完成後執行順序固定需操作 DOM 的主程式
async與解析並行下載完成即執行順序不定無依賴、獨立腳本

deferasync 都是為了避免傳統 <script> 阻塞頁面載入所設計,根據腳本間的相依性與執行時機選擇:

  • 若腳本需操作 DOM 或依賴其他腳本 → 使用 defer
  • 若腳本獨立且不影響頁面主流程 → 使用 async
  • 若需立即執行初始化邏輯 → 可保留同步載入

延伸閱讀

【Html】解析 <script> 載入機制與 defer、async 屬性

https://forgetfulengineer.github.io/Frontend/Html/script-loading-defer-async/

作者

健忘工程師

發表於

2025-10-29

更新於

2025-10-29

許可協議


你可能也想看

【HTML】button 在 form 裡和在 form 以外的差別
【HTML】解析 <a> 的 rel 屬性
【Html】自定義屬性:data-* 的命名規則和取值方法

評論

複製完成