支持情况
8 或 10版本的 Node.js 对 ES Modules 的支持还是处于实验阶段,要在 Node 环境下使用 ES Modules 需要做一些步骤。
- 将文件的扩展名由 .js 改为 .mjs。
- 启动时需要额外添加
--experimental-modules
参数。 ```javascript // module.mjs 文件 export const foo = ‘hello’ export const bar = ‘world’
// index.mjs 文件 import { foo, bar } from ‘./module.mjs’
console.log(foo, bar)
// 此时我们也可以通过 esm 加载内置模块了 import fs from ‘fs’ fs.writeFileSync(‘./foo.txt’, ‘es module working’)
// // 也可以直接提取模块内的成员,内置模块兼容了 ESM 的提取成员方式 import { writeFileSync } from ‘fs’ writeFileSync(‘./bar.txt’, ‘es module working’)
// 对于第三方的 NPM 模块也可以通过 esm 加载 import from ‘lodash’ console.info(.camelCase(‘ES Module’))
// 不支持,因为第三方模块都是导出默认成员 import { camelCase } from ‘lodash’ console.log(camelCase(‘ES Module’))
<a name="vF4gP"></a>
# 与 CommonJS 交互
- ES Modules 可以导入 CommonJS 模块。
- 原生 Node 环境下,CommonJS 不可以导入 ES Modules 模块。
- 在 ES Modules 引用时,CommonJS 始终只会导出一个默认成员。
- ES Modules 中 import 不是解构导出对象。
<a name="XMQxw"></a>
# 与 CommonJS 的差异
ESM 没有 CommonJS 的那些模块全局成员了。
```javascript
// CommonJS
// 加载模块函数
console.log(require)
// 模块对象
console.log(module)
// 导出对象别名
console.log(exports)
// 当前文件的绝对路径
console.log(__filename)
// 当前文件所在目录
console.log(__dirname)
// ESM 中,import 和 export 可以代替 require、module、exports
// __filename 和 __dirname 通过 import 对象的 meta 属性获取
// 通过 url 模块的 fileURLToPath 方法转换为路径
import { fileURLToPath } from 'url'
import { dirname } from 'path'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
console.log(__filename)
console.log(__dirname)
v12
node.js v12可以通过在 package.json 中将 “type” 字段 设置为 “module”,此时就不需要修改文件扩展名为 .mjs。但是这时如果需要继续使用 CommonJS,则需要把文件扩展名改为 .cjs。
Babel 兼容方案
在早期 Node 版本中, 可以在运行时通过 Babel 的插件将 ESM 转换成 CommonJS。
安装以下依赖:
{
"devDependencies": {
"@babel/core": "^7.6.0",
"@babel/node": "^7.6.1",
"@babel/plugin-transform-modules-commonjs": "^7.6.0"
}
}
在 .babelrc 中加载转换插件:
{
"plugins": [
"@babel/plugin-transform-modules-commonjs"
]
}
通过 "yarn babel-node 文件名.js" 即可使用 ESM 标准。