NodeJS 中 CommonJS 和 ESModule 混用时的各种坑解决方案

NodeJS 中 CommonJS 和 ESModule 混用时的各种坑解决方案
最新回答
木卯之夏

2023-04-22 20:22:35

在NodeJS中,两种标准的模块引入模式分别是CommonJS(CJS)和ESModule(ESM)。混用这两种引入模式时,可能会遇到一些问题。以下是CJS和ESM在单用和混用时的坑点及解决方案。

### CJS与ESM单用

#### CJS文件定义方法

模块定义使用 `module.exports` 和 `exports` 来暴露功能。

#### CJS模块引入

使用 `require` 来引入CJS模块。

### 坑点:module.exports和exports混用问题

避免混用`module.exports`和`exports`,以防产生不预期的行为。如果必须同时使用,应重新赋值`module.exports`并更新`exports`引用。

#### ESM文件定义方法

ESM使用`export`和`import`来定义和引入模块。

#### ESM模块引入

使用`import`语句来引入ESM模块。

### 坑点:`__filename`和`__dirname`无法使用

在ESM中,`__filename`和`__dirname`仅在CJS中有效。使用等效的ESM方法。

### CJS与ESM混用

#### CJS引入ESM

使用`dynamic import`(`import()`)来引入ESM模块。

#### 坑点:ESM编译注意事项

在编译库时,确保`.tsconfig.json`中的`.compilerOptions.module`设置为"ES6",否则编译结果无法使用。

#### 配置文件报错

如果在`package.json`中设置`type="module"`,所有JS文件会被识别为ESM。解决方法是:

1. 不在`package.json`中配置`type`,将ESM文件改为`.mjs`扩展名(不推荐)。

2. 使用`.cjs`扩展名的配置文件(推荐)。

使用`.cjs`扩展名的配置文件会被强制识别为CJS模块,即使`package.json`中`type`的值不同。

#### ESM引入CJS

ESM引入CJS模块时,`module.exports`的值就是所期望的导入值,无需额外的处理。

### 结语

ESM正在逐步取代CJS,目前在过渡期,兼容问题在所难免。开发新的第三方库时,应尽量使用ESM。随着生态系统的发展和优化,未来的NodeJS将更加倾向于ESM的使用。