跳到主要内容

esm-cjs

模块系统:ESM 与 CommonJS

Node 同时支持 CJS(require/module.exports)与 ESM(import/export),两者有差异与互操作边界。

要点

  • 识别:type: module.mjs/.cjspackage.json#exports
  • 互操作:import() 动态加载 CJS、createRequire 在 ESM 中使用 CJS;
  • 路径与解析:URL vs 相对路径、裸模块解析策略;
  • 顶层 await:仅 ESM 支持;
  • Tree Shaking 与打包器:ESM 友好,注意运行时差异。

示例:双包导出(CJS/ESM)

package.json

{
"name": "awesome-pkg",
"type": "module",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs",
"types": "./dist/index.d.ts"
}
}
}

在 ESM 中使用 CJS:

// index.mjs
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
const cjsOnly = require('some-cjs-lib');

在 CJS 中动态导入 ESM:

// index.cjs
async function load() {
const esm = await import('some-esm-lib');
}

Monorepo 建议:使用 workspace + exports 限制私有路径;统一 TS 路径别名与打包/测试工具的解析策略。