ES Module(模組)
介紹
ES 模組(ES Module,ECMAScript Module,簡稱 ESM)是 JavaScript 在 ES6(ECMAScript
2015)中引入的一種標準模組系統,主要用來解決:
瀏覽器環境的 ESM 特性
- 模組內變數具有區域作用域(不會污染全域)
- 模組以異步方式加載(等同於加上
defer)
- 必須透過 HTTP(S) 協定執行,無法直接從
file:// 路徑載入
- 可搭配原生瀏覽器 cache 機制,有效利用瀏覽器快取
ES 模組的基本概念
- 每個
.js 或 .mjs 檔案皆為一個模組
- 可使用
export 導出變數、函式或類別
- 可使用
import 導入其他模組的導出內容
- 一個模組可同時包含命名導出與預設導出(但僅能有一個預設導出)
export 與
import 的語法
命名導出(Named Export)
命名導出可導出多個項目,導入時必須使用相同名稱,並包在 {} 中。
預設導出(Default Export)
每個模組僅能有一個預設導出。導入時可自行命名,不需要使用 {}。
在瀏覽器中使用 ES 模組
type="module" 表示這段 <script> 是 ES 模組,模組會自動延後執行(類似加上
defer),且支援 import 語法。
⚠️ 注意:需透過 HTTP 伺服器執行(如 Live Server、Vite dev server、localhost),否則將因 CORS 或
file:// 限制導致 import 失敗。
在 Node.js 中使用 ES 模組
自 Node.js 12 起支援 ESM(Node 14+ 更完整),需符合以下條件之一:
方法一:在
package.json 設定為模組模式
方法二:使用 .mjs 副檔名
動態匯入(Dynamic Import)
ESM 支援 import() 語法,可在程式執行階段動態載入模組,回傳 Promise:
用途:
- 延遲載入(Lazy loading)
- 根據條件動態選擇模組
- 在非頂層使用匯入邏輯
注意事項:ESM 與 CommonJS
(require) 的相容性限制
Node.js 原本使用 CommonJS 模組系統(require /
module.exports),而 ESM 使用 import /
export,兩者在某些情境下無法直接混用:
CommonJS 中無法使用
import:
ESM 中無法使用 require:
導入 CommonJS 模組時,需注意 default
包裝
相容性表格
| 情境 |
是否支援 |
備註 |
CommonJS 使用 require 載入 ESM |
❌ |
不支援,會噴錯 |
CommonJS 使用 import |
❌ |
除非設定 type: module |
ESM 使用 import 載入 CommonJS |
✅ |
可行,但須透過 default 包裝 |
ESM 使用 require |
❌ |
須使用 createRequire() |
總結
| 類型 |
說明 |
| 命名導出 |
可導出多個,導入時需使用相同名稱 |
| 預設導出 |
每個模組只能一個,導入時可自訂名稱 |
type="module" |
瀏覽器或 Node.js 指定為 ES 模組 |
.mjs |
明確標示為模組檔,常用於 Node.js 中 |
require 限制 |
不能在 ESM 中直接使用 |
import() |
動態匯入模組,返回 Promise |
參考資源
ES Module(模組)
介紹
瀏覽器環境的 ESM 特性
ES 模組的基本概念
export與import的語法命名導出(Named Export)
// utils.js export const name = "Vue"; export function greet() { return `Hello, ${name}!`; } // main.js import { name, greet } from './utils.js'; console.log(name); // "Vue" console.log(greet()); // "Hello, Vue!"預設導出(Default Export)
// math.js export default function add(x, y) { return x + y; } // main.js import sum from './math.js'; console.log(sum(2, 3)); // 5在瀏覽器中使用 ES 模組
<!DOCTYPE html> <html lang="zh-TW"> <head> <meta charset="UTF-8"> <title>ES Modules</title> </head> <body> <script type="module"> import { name, greet } from './utils.js'; console.log(greet()); </script> </body> </html>在 Node.js 中使用 ES 模組
自 Node.js 12 起支援 ESM(Node 14+ 更完整),需符合以下條件之一:
方法一:在
package.json設定為模組模式// utils.js export function sayHello() { return "Hello, Node.js ESM!"; } // main.js import { sayHello } from './utils.js'; console.log(sayHello());方法二:使用
.mjs副檔名// utils.mjs export function sayHello() { return "Hello, Node.js ESM!"; } // main.mjs import { sayHello } from './utils.mjs'; console.log(sayHello());動態匯入(Dynamic Import)
ESM 支援
import()語法,可在程式執行階段動態載入模組,回傳Promise:const { default: add } = await import('./math.js'); console.log(add(1, 2));用途:
注意事項:ESM 與 CommonJS (
require) 的相容性限制Node.js 原本使用 CommonJS 模組系統(
require/module.exports),而 ESM 使用import/export,兩者在某些情境下無法直接混用:CommonJS 中無法使用
import:// ❌ 不可行 import { something } from './mod.js'; // ✅ 應使用: const { something } = require('./mod.js');ESM 中無法使用
require:// ❌ 不可行 const fs = require('fs'); // ReferenceError // ✅ 可用 createRequire: import { createRequire } from 'node:module'; const require = createRequire(import.meta.url); const fs = require('fs');導入 CommonJS 模組時,需注意 default 包裝
// math.cjs module.exports = { add: (a, b) => a + b }; // main.mjs import math from './math.cjs'; console.log(math.add(1, 2)); // ✅ OK,透過 default 封裝相容性表格
require載入 ESMimporttype: moduleimport載入 CommonJSrequirecreateRequire()總結
type="module".mjsrequire限制import()參考資源