CommonJS 和 ES Modules (ESM) 是两种不同的 JavaScript 模块系统。它们在 Node.js 环境中被广泛使用,尽管 ES Modules 也适用于浏览器环境。
CommonJS (CJS)
CommonJS 是为服务器端 JavaScript 开发设计的一种模块化标准,它最早被 Node.js 采用,并成为其默认的模块系统。CommonJS 规定了如何编写模块化的 JavaScript 代码以及如何加载这些模块。
- 特点:
- 使用
require
函数来导入其他模块中的变量、函数或对象。 - 使用
module.exports
或exports
对象导出模块中的内容。 - 在运行时解析依赖,这意味着你可以动态地决定要加载哪个模块。
- 每个模块都被封装在一个函数作用域内,避免全局变量污染。
- 使用
代码示例——exports导出
function add (a, b) {
return a + b
}
exports.hello = 'world';
exports.add = add;
const Add = require('./lib.js')
console.log(Add.add(1, 2), Add.hello); // 输出:3 world
代码示例——module.exports导出
function add (a, b) {
return a + b
}
module.exports = {
add: add,
hello: 'world'
}
const Add = require('./lib.js')
console.log(Add.add(1, 2), Add.hello); // 输出:3 world
ES Modules (ESM)
ES Modules 是 ECMAScript 标准的一部分,定义了 JavaScript 中模块的标准语法。从 ES6 (ES2015) 开始,JavaScript 引入了原生的模块支持。
- 特点:
- 使用
import
和export
关键字来导入和导出模块内容。 - 静态解析依赖,在编译时就已经确定了所有依赖关系。
- 支持树摇(Tree shaking),可以更高效地打包和加载只使用到的部分模块内容。
- 可以在浏览器和 Node.js 中使用。
- 使用
代码示例
export function add (a, b) {
return a + b
}
export const world = 'world';
export default 'world'
import {add, world} from './lib.js'
console.log(add(1, 2), world); // 输出:3 world
对比
- 互操作性: 在早期版本的 Node.js 中,只能使用 CommonJS。随着 Node.js 版本的发展,现在可以同时支持 CJS 和 ESM。但两者之间存在一些差异,例如处理循环引用的方式不同。
- 语法差异: CJS 使用
require
和module.exports
,而 ESM 使用import
和export
。 - 加载时机: CJS 是运行时加载,而 ESM 是静态解析,这使得 ESM 更适合现代构建工具和优化。
在 Node.js 中使用
Node.js 从 v12.0.0 开始支持 ES Modules。为了使用 ESM,你需要确保文件扩展名为 .mjs
或在 package.json
文件中设置 "type": "module"
。对于 CommonJS,则使用 .js
扩展名并保持 "type": "commonjs"
或不指定类型。
总结
总而言之,CommonJS 和 ES Modules (ESM) 是 JavaScript 中两种不同的模块系统,各自拥有独特的特性和应用场景。CommonJS 主要针对服务器端开发,提供了动态加载的能力,并且是 Node.js 中默认的模块系统。另一方面,ES Modules 提供了静态解析依赖的能力,支持树摇等现代构建工具优化技术,并且既适用于浏览器环境也适用于 Node.js 环境。无论是在 Node.js 环境还是浏览器环境中,合理选择和使用模块系统都能帮助我们构建更加健壮、可维护的 JavaScript 应用程序。