返回

Node.js 模块使用指南:CommonJS 与 ECMAScript 模块详解

前端

CommonJS 与 ECMAScript:Node.js 中的模块系统

Node.js 作为服务器端 JavaScript 运行环境,为开发者提供了强大的模块系统,使代码组织和复用变得轻而易举。其中,CommonJS 和 ECMAScript(ESM)是 Node.js 中最常用的两种模块系统,它们各有特色,了解其差异对 Node.js 开发至关重要。

CommonJS 模块

CommonJS 是 Node.js 最早采用的模块系统,其特点如下:

  • 模块通常以 .js 为后缀的 JavaScript 文件组成。
  • 模块导出变量、函数和类,使用 exports 对象。
  • 引入模块时,使用 require() 函数,返回模块导出的对象。

ECMAScript 模块

ECMAScript 是 JavaScript 的官方模块系统,其特点如下:

  • 模块通常以 .mjs 为后缀的 JavaScript 文件组成。
  • 模块导出变量、函数和类,使用 export 语句。
  • 引入模块时,使用 import 语句,返回模块导出的对象。

CommonJS 模块与 ECMAScript 模块的区别

虽然同为模块系统,但 CommonJS 模块与 ECMAScript 模块存在一些关键差异:

  • 模块后缀: CommonJS 模块使用 .js 后缀,而 ECMAScript 模块使用 .mjs 后缀。
  • 引入方式: CommonJS 模块使用 require() 函数引入,而 ECMAScript 模块使用 import 语句引入。
  • 导出方式: CommonJS 模块使用 exports 对象导出,而 ECMAScript 模块使用 export 语句导出。

互相引入和使用

尽管存在差异,但 CommonJS 模块和 ECMAScript 模块可以在 Node.js 中互相引入和使用:

  • CommonJS 模块引入 ECMAScript 模块: 使用 require() 函数,并在模块路径前添加 ., 如:require('./module.mjs')
  • ECMAScript 模块引入 CommonJS 模块: 使用 import 语句,并在模块路径前添加 cjs, 如:import * from 'cjs:./module.js'

代码示例

CommonJS 模块(module1.js)

exports.name = 'John Doe';
exports.age = 30;

ECMAScript 模块(module2.mjs)

export const name = 'Jane Doe';
export const age = 35;

互相引入

CommonJS 模块(main.js)

const module1 = require('./module1.js');
console.log(module1.name, module1.age); // 输出:John Doe 30

ECMAScript 模块(main.js)

import * as module2 from 'cjs:./module2.mjs';
console.log(module2.name, module2.age); // 输出:Jane Doe 35

总结

CommonJS 和 ECMAScript 模块是 Node.js 中功能强大的模块系统,了解其差异对选择最适合项目需求的模块至关重要。 CommonJS 模块历史悠久,广泛使用,而 ECMAScript 模块则更现代,符合 JavaScript 的原生标准。开发者可以根据需要灵活选择和使用这些模块系统,以构建健壮且可复用的 Node.js 应用程序。

常见问题解答

1. CommonJS 和 ECMAScript 模块哪个更好?

没有绝对的优劣之分,具体取决于项目的具体需求。 CommonJS 模块兼容性更广,而 ECMAScript 模块更符合 JavaScript 标准。

2. 如何在 Node.js 中启用 ECMAScript 模块?

在 Node.js 13 或更高版本中,使用 --experimental-modules 标志启用。

3. 为什么 CommonJS 模块需要使用 require() 函数?

require() 函数是 CommonJS 模块系统的一部分,用于动态加载模块。

4. 为什么 ECMAScript 模块使用 export 语句?

export 语句是 JavaScript 的原生语法,用于导出模块内容。

5. 如何避免 CommonJS 和 ECMAScript 模块之间的冲突?

使用文件扩展名(.js.mjs)或其他策略来区分它们,以避免冲突。