ES Module 与 CommonJS 模块方案

文章类型:ES6

发布者:hp

发布时间:2025-03-02

一:引言

ES Module 与 CommonJS 都是JS模块化规范,都可以用来导入导出模块,那么他们有什么异同呢?

二:区别

(1)相同点

   1:都是JS模块化规范,都可以用来导入导出模块

   2:都实现了模块作用域隔离,不会污染全局作用域,需显式导出才可以被外部访问

   3:都支持模块缓存

(2)不同点

   1:语法上

       ESM=>采用export 或 export default,使用import引入,并且导出的的值只读引用

       CJS=>采用module.exports 或 exports,使用require引入,并且导出的值是拷贝

   2:加载上

       ESM=>静态解析依赖,编译阶段确定模块关系,支持异步加载,并且inport语句需要写在顶层,

const dynamicPath = './module' + variable;
import(dynamicPath).then(mod => { /* 异步加载 */ });

       CJS=>同步加载模块,执行时阻塞后续代码

const dynamicPath = './module' + variable;
const mod = require(dynamicPath); // 支持动态路径

   3:作用域上

       ESM=>模块顶层作用域为共享的模块环境,声明的变量对其他导入模块可见,(export显示暴露)

       CJS=>每个模块拥有独立的顶层作用域,通过闭包隔离变量

   4:运行环境上

       ESM=>浏览器支持,node需要通过.mjs扩展名或者配置启用

       CJS=>node原生支持,浏览器需要转换

   5:动态导入与灵活性上

       ESM=>使用import函数实现异步动态加载,返回Promise,适用于按需加载优化性能

       CJS=>使用require支持同步动态加载,路径可动态拼接

三:使用场景

    1: ESM=>浏览器现代应用、跨平台模块化开发

    2: CJS=>Node服务器开发,需同步加载的脚本

四:代码

1:ESM

// module.js
export const esFun = () => {
  console.log("ES Module");
};

// app.js
import { esFun } from "./module.js";
esFun(); // 输出 "ES Module"

2:CJS

// module.js
const cjsFun = () => {
  console.log("CommonJS");
};
exports.cjsFun = cjsFun;

// app.js
const myModule = require("./module.js");
myModule.cjsFun(); // 输出 "CommonJS"

四:总结

1:ESM 通过静态解析、引用导出和异步加载支持现代开发需求

2:: CJS 凭借同步执行和动态加载在服务端场景仍有优势