ES Module 是 ECMAScript 2015 最重要發明,而從 Node 12 開始也正式支援 ES Module,甚至還可將 Import 語法用在原本 CommonJS Module。
Version
Node 14.18.1
Using .js
Node 12 允許我們一樣使用 .js
,但必須搭配 package.json
。
helloWorld.js
export let helloWorld = _ => 'Hello World'
在 hello-world.js
使用 ES6 的 export
將 helloWorld
匯出。
index.js
import { helloWorld } from "./helloWorld.js"
console.log (helloWorld())
在 index.js
使用 ES6 的 import
將 helloWorld
匯入。
package.json
{
"type": "module",
"name": "esm-import",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
}
若要 file extension 仍使用 .js
,則要在 pckage.json
加入 "type": "module"
,如此 Node 將視 .js
為 ES module。
Using .mjs
若不想使用 package.json
與 "type": "module"
,也可將 file extension 改成 .mjs
。
helloWorld.mjs
export let helloWorld = _ => 'Hello World'
從 helloWorld.js
改成 helloWorld.mjs
。
index.mjs
import { helloWorld } from "./helloWorld.mjs"
console.log (helloWorld ())
import
要改成 helloWorld.mjs
,index.js
也要改成 index.mjs
。
也就是若不使用
package.json
,則所有檔案都要改成.mjs
Importing CommonJS Module
Node 12 之後也可使用 import
載入 CommonJS module。
helloWorld.txt
Hello World
希望使用 Node 的 fs.readFile
讀取 helloWorld.txt
。
require
index.js
let { readFile } = require("fs")
readFile ("hello-world.txt", (err, data) => {
if (err) throw err
console.log (data.toString ())
})
Node 12 之前會使用 require
載入 CommonJS module,可直接搭配 destructuring。
import
index.js
import { readFile } from 'fs'
readFile ("hello-world.txt", (err, data) => {
if (err) throw err
console.log (data.toString ())
})
從 Node 12 開始也可使用 import
載入 CommonJS module,也可直接在 import
使用 Object Destructuring。
package.json
{
"type": "module",
"name": "esm-import",
"version": "1.0.0",
"main": "index.js",
"license": "MIT"
}
因為 file extension 為 .js
,所以依然要使用 package.json
與 "type": "module"
。
Conclusion
- 隨著 Node 支援 ES6+ 越來越完整,可漸漸不必使用 Babel 轉譯,直接使用原生 Node 即可
- 由於
import
可支援 ES module 與 CommonJS module,因此 Node 可全面使用import
語法;但若是開發 package,為了最大相容性仍建議使用 CommonJS module,若想使用export
語法,可使用 Node + Babel 開發環境,由 Babel 轉成 CommonJS module
Reference
Valeri Karpov, What’s New in Node.js 12: ESM Imports
Node.js, ECMAScript Modules