在NodeJs项目中使用ECMAScript module
随着 Nodejs v16 成为长期稳定支持的版本,ESM 也随之成为 NodeJs 正式支持的标准化模块系统,这允许我们通过 ESM 来开发我们的 NodeJs 项目,并在项目中通过ESM 来导入其他的ESM包。
创建项目
我们以新建一个 NodeJs 项目为例, 它有如下的结构:
./my-esm-package
├── lib
│ ├── resolve.js
│ └── index.js
└── package.json这个项目的功能是导出一个 resolve 方法,是 path.resolve 的封装实现。
export * from './resolve.js'import path from 'node:path'
export const resolve = (...arg) => path.resolve(...arg)package.json
在 package.json 中,我们需要进行以下声明:
声明
type字段值为module这个字段声明了你的包将作为一个
ECMAScript module被NodeJs加载并解析,并允许使用.mjs格式的文件。声明
exports字段该字段描述了 项目如何导出模块给到其他包使用。
默认导出
package.json{ "exports": "./lib/index.js" }即当使用
import { resolve } from 'my-esm-package'时,默认引入的文件是lib/index.js。导出多个模块
package.json{ "exports": { ".": "./lib/index.js", "resolve": "./lib/resolve.js" } }声明了导出了两种模块:一个是默认导出,使用
"."作为key;一个是具名导出。当使用
import { resolve } from 'my-esm-package'时,默认引入的文件是lib/index.js。当使用
import { resolve } from 'my-esm-package/resolve'时,引入的文件是lib/resolve.js。exports还支持其他形式的值,这里暂不赘述。
声明
engines字段由于
Nodejs并不是全版本支持esm的,而是从v14.16.0版本开始试验性的支持,并到了v16版本才作为正式支持, 且当前v16版本作为目前的长期稳定支持的版本。这个项目运行环境的NodeJs版本,最低应该推荐使用v16以上的版本。 即它的值应该为{ "node": ">=16" }
到这里,这个项目的package.json 文件,包含以下内容:
{
"name": "my-esm-package",
"description": "My first esm package.",
"type": "module",
"exports": {
".": "./lib/index.js",
"resolve": "./lib/resolve.js"
},
"engines": {
"node": ">=16"
}
}编写项目代码
由于是一个
esm项目,所以理所当然的不能项目中使用require()/module.exports来导入导出模块。 而是应该全部使用import/export的方式来导入导出模块。不需要在项目代码中 使用
use strict。由于
esm项目中,NodeJs不再支持__dirname/__filename,所以有相关场景需要使用时,需要使用其他的方式来实现相同功能:
import { basename, dirname } from 'node:path'
import { fileURLToPath } from 'node:url'
const _dirname = typeof __dirname !== 'undefined' ? __dirname : dirname(fileURLToPath(import.meta.url))
const _filename = typeof __filename !== 'undefined' ? __filename : basename(fileURLToPath(import.meta.url))TypeScript
如果在项目中使用了 TypeScript,那么除了需要遵循以上的内容,还需要在 tsconfig.json 配置文件中补充以下配置:
{
"module": "node16",
"moduleResolution": "node16"
}并且,应该将 .ts 文件,编译为 .js 文件,package.json 配置的 exports 导出的,是编译后的 .js 文件。
最后
当完成了以上步骤,就可以得到一个NodeJs ESM 项目。它也只能在另一个支持 esm 的项目中使用。
