你有想過,我們在 JavaScript 要引入其他文件,有的時候使用 require
,有的時候使用 import
,這兩個方式有什麼差別?效能上又有什麼差別呢?本篇就來說明一下!
遵循的模塊化規範不同
require/exports
遵循 CommonJS 規範,主要用於 Node.js 伺服器端開發,以同步方式載入模組,也就是要載入完成後才能執行後面的程式碼。
而 import/export
則是 ES6 模組(ESM)標準,由 TC39 制定,屬於靜態編譯,編譯期就能解析依賴,瀏覽器與 Node.js 都原生支持(Node.js 14+)。若舊環境不支援,則可以透過 Babel + Webpack 轉譯。
出現的時間不同
require/exports
:2010 年左右在 CommonJS 規範中出現,Node.js 廣泛採用。import/export
:ES6 (ES2015) 引入,2015 年之後才廣泛使用,Babel 是早期轉譯支援的重要工具。
現在 Node.js 14+ / 16+ 已原生支援 ES Module,不需要 Babel 也能直接使用 import/export
。
寫法與使用方式不同
CommonJS (require/exports
)
|
|
ES6 Module (import/export
)
|
|
動態載入(Dynamic Import)
靜態 import
必須是字面量字串,編譯期就要能確定模組路徑:
|
|
若需要 動態載入,可以使用 CommonJS 的 require()
或 ESM 的動態 import()
:
|
|
說明
方法 | 同步/非同步 | 支援變數 | 適用環境 |
---|---|---|---|
import (靜態) | 靜態編譯 | ❌ | ESM(編譯期) |
require() | 同步 | ✅ | CommonJS (Node.js) |
await import() | 非同步 | ✅ | ESM (Node.js / 瀏覽器) |
Node.js 支援情況
- Node.js 14.8+:動態
import()
正式可用(無需 flag)。 - Node.js 16+ LTS:動態
import()
穩定,CommonJS 與 ESM 都可使用。 - 靜態
import
與動態import()
都可以取代 Babel 轉譯的需求,但 Babel/Webpack 仍用於瀏覽器或舊版兼容。
本質上的不同
- CommonJS 與 ES Module 輸出都是物件,但 ESM 支援
export default
與強綁定屬性。 require()
載入的是值或引用,靜態與動態都可以。- 動態
import()
與require()
的動態行為對等,但非同步,不阻塞事件循環。
範例比較
|
|
執行結果:
|
|
效能差異
- 靜態
import
:編譯期執行。 require()
:同步載入,阻塞事件循環。- 動態
import()
:非同步載入,不阻塞事件循環。
在現代 Node.js 專案,如果能用靜態 import 就用,需動態載入才使用
require()
或await import()
。效能差異微乎其微,但動態載入的同步/非同步行為會影響事件循環。