一、ES Modules in Node.js
ES Modules 是 JavaScript 的语言层面的模块化标准,会逐渐统一所有 JS 领域的模块化需求。
Node.js 作为 JavaScript的一个重要应用领域,它逐步支持这一个特性。从 V8.5版本之后,内部就已经以实验的方式去支持ESM 了。启动 node 的时候, 需要加 experimental-modules,这个参数 表示启用 ESM 的实验特性。Nodejs v12.17.0 LTS 版发布,去掉 --experimental-modules 标志。
ES Modules 在 node.js中的基本使用
1. 在 V8.5 - V12.17 版本内使用
- 将 .js 文件 改为 .mjs 文件
- 启动 node 的 时候, 需要 加 --experimental-modules。这个参数 表示启用 ESM 的实验特性。
2. 在 V12.17 版本之后使用
- 通过声明 .mjs 后缀的文件或在 package.json 里指定
"type" : "module"
,这两种方式使用 ES Modules, - 启动 node , 可以加 --experimental-modules,也可以不加。
二、Node.js 中 ES Modules 与 CommonJS 的互动
- ES Modules 中可以导入 CommonJS 模块。但不能直接提取 CommonJS 模块内的成员。(注意 import 不是解构导出对象)
- CommonJS 中不能导入 ES Modules 模块
- CommonJS 始终只会导出一个默认成员,因此 ES Modules 只能以载入默认成员的方式去导入。
// b.js --- CommonJS
exports.foo = 'commonjs exports value'
// a.mjs --- ES Modules
import foo from './b.js'
console.log(foo) // => {foo: 'commonjs exports value'}
注意:如果需要在 type= module 的情况下继续使用 CommonJS,
需要将文件扩展名修改为 .cjs
三、ES Modules 与 CommonJS 的全局成员
CommonJS 中模块全局成员:require(加载模块函数)、module(模块对象)、exports(导出对象别名)、__filename(当前文件的绝对路径)、__dirname(当前文件所在目录)。
ES Modules 中没有模块全局成员
require, module, exports 是通过 import 和 export 代替
__filename 和 __dirname 通过 import 对象的 meta 属性获取。
const currentUrl = import.meta.url
// 通过 url 模块的 fileURLToPath 方法转换为路径
import { fileURLToPath } from 'url'
import { dirname } from 'path'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
四、ES Modules 早期在 Node.js 版本中兼容方案
采用 Babel 去实现兼容,Babel 目前是最主流的JavaScript编译器,它可以帮我们将一些使用了新特性的代码编译成当前环境支持的代码。
babel 是基于插件机制实现。核心模块并不会去转换我们的代码,具体去转换代码当中的每一个特性,是通过插件去实现。
preset-env 是插件的集合,在这个插件集合当中去包含了最新的 js标准当中的所有新特性。
使用方法一:
- 先安装 npm i @babel/node @babel/core @babel/preset-env -D
- 运行命令 npm babel-node index.js --presets=@babel/preset-env 或者 在项目中创建 .babelrc 的配置文件,内部设置
"presets": ["@babel/preset-env"]
,然后就可以直接运行 npm babel-node index.js
使用方法二:
不安装 preset-env ,可以单独安装转换新特性的插件plugin-transform-modules-commonjs
,在 .babelrc 配置文件中设置以下内容
{
"plugins": [
"@babel/plugin-transform-modules-commonjs"
]
}
运行命令: pm babel-node index.js