javaScript模块化旨在解决代码组织、复用与依赖管理问题;es6模块静态编译时解析、绑定实时响应、路径字面量限定,Commonjs动态运行时加载、导出值拷贝、支持路径拼接,二者不兼容需工具桥接。

javascript模块化是为了解决代码组织、复用和依赖管理问题。ES6模块(import/export)和CommonJS(require/module.exports)是两种主流方案,它们在设计思想、语法、加载时机和运行环境上都有本质区别。
ES6模块是静态的、编译时确定的
ES6模块的导入导出语句必须出现在顶层作用域,不能放在条件语句或函数中。这是因为模块关系在代码执行前就由解析器静态分析完成,支持tree-shaking、循环引用更安全、也便于构建工具优化。
- 必须用字面量字符串指定模块路径:不能动态拼接路径,比如
import('./' + name + '.js')是非法的(但可以用import()动态导入替代) - 绑定是实时的、响应式的:导出值改变,所有导入该值的地方会同步看到更新(尤其是
export let或export const obj = {}这类对象引用) - 默认导出是命名导出的语法糖:本质上是
export { xxx as default },所以import foo from 'mod'等价于import { default as foo } from 'mod'
CommonJS是动态的、运行时加载的
CommonJS最初为node.js设计,require() 是一个函数调用,可在任意位置执行,模块加载和导出发生在代码运行阶段。
- 可以动态 require:比如
if (env === 'dev') require('./debug')或require('./' + config.file) - 导出的是值的拷贝(浅拷贝):
module.exports = 42后再改它,已require的模块不会感知变化;但如果是对象,修改其属性仍可见(因为导出的是引用) - 模块缓存基于文件路径:同一文件多次
require返回同一个缓存对象,保证单例行为
两者不兼容,需工具桥接
浏览器原生只支持ES6模块(<script type="module"></script>),node.js从v12起默认支持ES6模块(需文件后缀为.mjs或"type": "module"),但CommonJS仍是Node生态主流。二者不能直接混用:
立即学习“Java免费学习笔记(深入)”;
- ES6模块中不能直接
importCommonJS模块的module.exports对象——但现代打包器(如webpack、vite)和Node都会自动将require导出的对象挂到default属性上,即import cjs from 'cjs-pkg'实际拿到的是cjs.default - CommonJS中不能用
require()加载原生ES6模块(无exports对象),但可通过import()动态导入,返回 promise - Node.js中可通过
createRequire创建require函数,在ESM中加载CJS模块
选择建议
新项目优先使用ES6模块:语法统一、利于工具链优化、未来标准。在Node中若需兼容老包或动态逻辑,可保留部分CommonJS,或用import()替代require()实现动态加载。前端开发基本无需考虑CommonJS,现代构建工具已能平滑处理混合模块。
基本上就这些。