本篇重點
<script>的載入與執行特性defer和async的功能與特性type="module"與 defer 的關係
<script> 的載入與執行機制
HTML 解析器在遇到 <script src="xxx.js"> 時,預設行為是:
- 暫停 HTML 解析
- 下載 script 檔案
- 立即執行 script
- 繼續解析 HTML
因此若未加上任何屬性(即同步載入),每個 script 標籤都可能造成主執行緒中斷,延後頁面渲染。
無屬性(同步載入)
功能與特性
- 預設為同步模式,遇到
<script>時會暫停 HTML 解析,等待下載並執行完成後才繼續解析。 - 若放在
<head>,可能導致白屏延遲(render-blocking)。
使用時機
適合需要立即執行或初始化頁面邏輯的腳本。
- 在 DOM 尚未完全建立前,就必須修改或偵測初始狀態的功能(例如 polyfill 引入)。
- 須確保執行順序固定的腳本。
範例:
polyfill.js 的執行會阻塞後續的 HTML 載入。
1 | <head> |
defer 屬性
功能與特性
- 表示 script 延遲執行,直到整份 HTML 解析完成。
- 在解析 HTML 的同時開始非同步下載腳本,等到 DOM 結構建立完畢後才執行。
- 如果有多個帶
defer的 script,會依照在文件中的出現順序執行。 - 執行時機在
DOMContentLoaded事件前。
使用時機
適合需要存取或操作 DOM 元素的程式
範例
DOM 已解析完成,main.js 可以安全地操作 DOM。
1 | <script defer src="main.js"></script> |
執行順序
1 | <p>Start parsing...</p> |
- HTML 解析不中斷
a.js、b.js同步下載- HTML 完成解析後,依序執行
a.js→b.js
async 屬性
功能與特性
- 表示該 script 非同步載入與執行,不會阻塞 HTML 解析。
- 載入完成立即執行,不會等待 DOM 完成。
- 如果有多個帶
async的 script,執行順序不保證和文件檔案順序一致,取決於哪個 script 先下載完。
使用時機
適合與頁面內容無依賴關係的外部腳本,例如:
- 網站統計工具(例如:Google Analytics)
- 廣告追蹤腳本
- 第三方 SDK
範例:
adsbygoogle.js 會在下載完成的那一刻立刻執行,不干擾主要頁面邏輯。
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 的行為:
1 | <script type="module" src="app.js"></script> |
因此模組不會阻塞 HTML 解析,會在 DOM 解析完成後執行。
結論
| 屬性 | 是否阻塞 HTML 解析 | 下載時機 | 執行時機 | 多腳本執行順序 | 適用情境 |
|---|---|---|---|---|---|
| 無屬性 | 是 | 立即下載 | 下載完成即執行 | 順序固定 | 需立即執行、初始化頁面邏輯 |
| defer | 否 | 與解析並行 | DOM 完成後執行 | 順序固定 | 需操作 DOM 的主程式 |
| async | 否 | 與解析並行 | 下載完成即執行 | 順序不定 | 無依賴、獨立腳本 |
defer 與 async 都是為了避免傳統 <script> 阻塞頁面載入所設計,根據腳本間的相依性與執行時機選擇:
- 若腳本需操作 DOM 或依賴其他腳本 → 使用
defer - 若腳本獨立且不影響頁面主流程 → 使用
async - 若需立即執行初始化邏輯 → 可保留同步載入



