在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引入CJSESM引入CJS模块时,`module.exports`的值就是所期望的导入值,无需额外的处理。### 结语ESM正在逐步取代CJS,目前在过渡期,兼容问题在所难免。开发新的第三方库时,应尽量使用ESM。随着生态系统的发展和优化,未来的NodeJS将更加倾向于ESM的使用。