支持情况
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 标准。
