You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NPM包导入失败求助:CommonJS与ESM模块兼容问题

ESM与CommonJS模块兼容问题解决方案

方案1:让NPM包同时支持双模块格式

最稳妥的方式是让你的包同时适配ESM和CommonJS,不管项目用哪种模块系统都能直接用,步骤如下:

  • 给包新增一个CommonJS专用的ts配置文件tsconfig.cjs.json:
{
  "files": ["src/globaltype.ts"],
  "compilerOptions": {
    "target": "es2016",
    "module": "CommonJS",
    "declaration": true,
    "outDir": "./build/cjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}
  • 把原来的tsconfig改名为tsconfig.esm.json,调整输出目录为ESM专用:
{
  "files": ["src/globaltype.ts"],
  "compilerOptions": {
    "target": "es2016",
    "module": "es2015",
    "declaration": true,
    "outDir": "./build/esm",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}
  • 更新包的package.json,配置多入口并完善脚本:
{
  "name": "nodecustomerrorhandler",
  "version": "1.0.14",
  "description": "basic error handling module for node basic projects",
  "type": "module",
  "exports": {
    ".": {
      "import": "./build/esm/globaltype.js",
      "require": "./build/cjs/globaltype.js"
    }
  },
  "main": "./build/cjs/globaltype.js",
  "module": "./build/esm/globaltype.js",
  "types": "./build/esm/globaltype.d.ts",
  "repository": {
    "type": "git"
  },
  "scripts": {
    "build": "tsc -p tsconfig.esm.json && tsc -p tsconfig.cjs.json"
  },
  "license": "ISC",
  "devDependencies": {
    "typescript": "^5.0.4"
  }
}
  • 重新执行npm run build并发布包,之后CommonJS项目用require、ESM项目用import都能正常运行。

方案2:把项目改成纯ESM格式

如果想把项目切换到ESM,需要调整几个关键点:

  1. 项目package.json添加"type": "module":
{
  "name": "affiliatesystem",
  "version": "1.0.0",
  "type": "module",
  "main": "test.file.js",
  "scripts": {
    "dev": "ts-node-dev --esm --respawn src/server.ts"
  }
}
  1. 修改项目的tsconfig,适配ESM模块解析:
{
  "files": ["src/server.ts"],
  "compilerOptions": {
    "target": "es2016",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "rootDir": "./",
    "typeRoots": ["./src/globals.d.ts"],
    "outDir": "src/build",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}
  1. 启动脚本要加--esm参数,让ts-node-dev支持ESM
  2. 项目里的导入语句统一用ESM格式:import { GlobalErrorClass } from 'nodecustomerrorhandler',不能再用require

方案3:在CommonJS项目中动态导入ESM包

如果不想改包也不想动项目的模块系统,直接用动态import就行:

async function bootstrap() {
  const { GlobalErrorClass } = await import('nodecustomerrorhandler');
  // 在这里使用GlobalErrorClass
}
bootstrap();

注意这种方式需要把模块相关逻辑放在异步函数里,适合不需要同步加载的场景。

内容的提问来源于stack exchange,提问作者kingNodejs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 08:57:53