Skip to content

.mjs文件总是以 ES6 模块加载,.cjs文件总是以 CommonJS 模块加载,.js文件的加载取决于package.json里面type字段的设置。

CommonJS 模块加载 ES6 模块

js
(async () => {
  await import('./ejs-package.mjs');
})();

ES6 模块加载 CommonJS 模块

js
// 只能整体加载
import packageMain from 'cjs-package';

同时支持ESM和CJS的模块

json
{
  "exports": {
    "require": "./index.js",
    "import": "./esm/index.js"
  }
}

CommonJS vs ES6 Module (ESM)

对比项CommonJSES6 Module (ESM)
语法require() / module.exportsimport / export
加载时机运行时加载(执行时动态引入模块)编译时加载(编译阶段静态分析依赖)
导出方式赋值给 module.exportsexports 对象使用 export / export default 声明导出
导入方式const a = require('./a')import a from './a.js'
导出值的拷贝类型值拷贝(拷贝一份导出的结果)引用绑定(实时绑定)
执行顺序模块在第一次 require() 时同步执行一次模块在编译阶段确定依赖关系后异步加载执行
是否异步加载否(同步加载,适合 Node.js 后端)是(异步加载,适合浏览器环境)
作用域模块有自己的独立作用域模块也有自己的作用域(同样不会污染全局)
this 指向顶层 this 指向 module.exports顶层 thisundefined
Node.js 原生支持情况Node.js 默认支持(无需额外配置)Node.js 需在 "type": "module" 下使用或文件扩展名为 .mjs
浏览器支持情况不支持原生浏览器导入现代浏览器原生支持 <script type="module">
循环依赖处理返回已执行部分的结果(可能是空对象)返回绑定引用(引用可能未初始化)
用途Node.js 服务端模块系统前端标准模块系统(Node.js 也逐步支持)

Reference

Powered by VitePress