CommonJS (module.exports)

基本概念

  • CommonJS 是 Node.js 早期的模块系统标准。
  • 每个文件是一个模块,模块内部通过 module.exports 导出内容。
  • 使用 require() 导入模块。

// util.js (CommonJS)
module.exports = {
foo() { console.log(‘foo’); },
bar() { console.log(‘bar’); }
};

// main.js
const util = require(‘./util.js’);
util.foo(); // 输出 ‘foo’

特点

1/ 每个模块导出的是 一个对象,可以直接赋值给 module.exports。

2/ 导入的时候得到的就是这个对象。

3/ 没有概念上的 “default”,整个 module.exports 就是模块本身。

ES Module (export default / export)

基本概念

ES Module(简称 ESM)是 JavaScript 官方标准模块系统。

支持 静态分析(在编译时就能确定依赖),语法是 import / export。

有两种导出方式:

默认导出:export default …

命名导出:export const foo = …

// util.js (ES Module)
export default {
foo() { console.log(‘foo’); },
bar() { console.log(‘bar’); }
};

// main.js
import util from ‘./util.js’;
util.foo(); // 输出 ‘foo’

特点

1/ 可以同时有 一个默认导出 和 多个命名导出:

export const x = 1;
export default function() {}

2/ ESM 是静态的,编译器可以提前知道依赖关系,方便 tree-shaking。

3/ 默认导出 (export default) 在语法上和 CommonJS 的 module.exports 类似,但概念上是 ESM 模块的 default 成员。

为什么它们不一样?

属性 CommonJS ES Module
导出语法 module.exports = {...} export default {...} / export const ...
导入语法 const x = require('./module') import x from './module'
默认导出 没有默认导出概念,整个模块对象就是导出值 default 和命名导出概念
加载方式 动态加载(运行时 require) 静态加载(编译时 import)
兼容性 Node.js 内置,适合老项目 浏览器原生、现代 JS 打包工具

所以它们本质上 是不同模块系统:

  • CommonJS:模块是一个对象,运行时加载
  • ESM:模块是静态结构,支持默认和命名导出

为什么有兼容问题?

当你用 import 导入一个 CommonJS 模块时,ESM 会把整个 module.exports 当作 一个默认成员,因此有时你要用:

import util from ‘./util.js’;
util.default.foo(); // 因为 util = { default: { foo(), bar() } }

同理,ESM 的 export default 如果用 require() 导入,有时也会得到一个对象包裹在 .default 下:

const util = require(‘./util.js’);
util.default.foo(); // 可能需要这样访问

这就是“兼容问题”的来源。

总结

CommonJS

早期 Node.js 模块系统

module.exports = 整个模块

require() 导入

ES Module

官方标准模块系统

export default 是模块的默认导出

import 导入,可同时有命名导出

区别

CommonJS 是对象导出,动态加载

ESM 有默认/命名导出,静态加载

兼容问题

CommonJS 导出的模块用 import 可能需要 .default

ESM 导出的模块用 require 可能需要 .default

作者 admin

百度广告效果展示