三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

CommonJS 与 ESM 的模块规范

CommonJS 与 ESM 的模块规范

CommonJS 与 ESM 全面对比:原理、区别及项目坑点

一、定义

CommonJS(简称 CJS)

  • Node.js 早期自己发明的模块规范

  • 专为服务端设计

  • 浏览器原生不支持

  • 后缀 .js 默认就是 CJS(package.json 没有 type:module

ESM(ES Module)

  • JavaScript 官方语言标准

  • ES6 推出

  • 浏览器、Node.js 统一标准

  • 项目 package.json 写了:

    "type": "module"
    

    整个项目所有 .js 文件 强制变成 ESM


二、核心语法对比

1. 导入导出

CommonJS

// 导出
module.exports = { name: "张三" };// 导入
const cfg = require("./config.js");

ESM

// 导出
export default { name: "张三" };// 导入
import cfg from "./config.js";

三、最关键 7 大区别(必须记住)

1. 语法不同

  • CJS:require / module.exports

  • ESM:import / export

2. 有没有缓存

CommonJS

  • require 加载模块会缓存

  • 可以手动清缓存:

    delete require.cache[路径]
    

ESM

  • import 也会缓存,而且不让你清缓存

  • **没有 require.cache 给你用

  • 想热更新配置,只能:
    读文件文本 → vm 执行

3. 有没有 dirname /filename

CommonJS

自带:

console.log(__dirname); 
//D:\myCode\pqc-reader 「文件夹路径」console.log(__filename);
//D:\myCode\pqc-reader\config.js 「完整绝对路径 + 文件名」

ESM

没有!必须自己手动算:

import { fileURLToPath } from 'url';
import path from 'path';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
//import.meta.url => 当前 JS 文件的地址(文件网址file:///D:/myCode/...)
// fileURLToPath => 把上面的 “文件网址” 转成 “电脑正常路径”
//path.dirname = > 拿到这个文件所在的 “文件夹路径”

4. 能不能用顶层 await

CommonJS

不支持,只能在函数里用 async

ESM

支持顶层 await

const cfg = await loadConfig();

5. 加载方式

CommonJS

同步加载
适合服务端本地文件

ESM

异步加载
设计给浏览器用,Node 也兼容

6. 文件后缀规则

CommonJS

导入可以省略后缀:

require("./config");

ESM

必须写全后缀

import cfg from "./config.js"; // 必须 .js

7. 浏览器支持

CommonJS

浏览器完全不认识,必须打包(webpack/vite)

ESM

浏览器原生直接支持

<script type="module" src="index.js"></script>

总结:

最简单记忆口诀
  • CommonJS:Node 老规矩,用 require,有 __dirname,能清缓存,同步加载

  • ESM:官方新标准,用 import,无 __dirname,不能清缓存,支持顶层 await,前后端通用


← 返回列表