CommonJS项目在依赖切换为纯ESM时如何升级适配?
CommonJS项目适配纯ESM第三方依赖解决方案
该问题根因是node-fetch v3及以上版本为纯ESM包,仅支持ESM规范导入。生产构建正常是因为webpack、rollup等构建工具默认支持ESM与CommonJS混合导入,而Jest默认运行在Node的CommonJS运行时,无法直接加载ESM包。
方案1:降级使用兼容CommonJS的版本
该方案改动最小,适合短期不想调整项目架构的场景,node-fetch v2.x分支仍会接收安全补丁更新:
- 安装v2版本的node-fetch:
npm install node-fetch@2 # 若使用TypeScript,同步安装对应版本类型定义 npm install -D @types/node-fetch@2
- 原有业务代码和单测代码都不需要修改,直接正常运行即可。
方案2:CommonJS中使用动态import()加载纯ESM包
不需要整体迁移项目为ESM,仅修改用到node-fetch的代码即可:
// 移除原有同步导入语句,改为异步动态导入 async function yourFetchLogic() { const { default: fetch } = await import('node-fetch') // 后续正常使用fetch即可 const res = await fetch('your-request-url') }
- 若为TypeScript项目,仅需将
tsconfig.json中的module配置调整为ESNext,moduleResolution保持Node即可,不影响其他CommonJS代码编译。
方案3:调整Jest配置适配纯ESM包
若不想修改业务代码,仅调整Jest相关配置即可解决单测报错:
- 安装babel转译相关依赖:
npm install -D babel-jest @babel/preset-env
- 根目录新增
.babelrc配置文件:
{ "presets": [["@babel/preset-env", { "targets": { "node": "current" } }]] }
- 修改
jest.config.js,将纯ESM包加入转译白名单:
module.exports = { transformIgnorePatterns: [ "node_modules/(?!node-fetch)/" // 有其他纯ESM依赖也可依次加入,用|分隔 ] }
- 保留原有Jest启动命令即可正常运行单测。
方案4:使用esm加载器兼容
若不想使用babel转译,可安装esm加载器直接兼容CommonJS加载ESM包的需求:
- 安装esm依赖:
npm install -D esm
- 修改Jest启动命令为:
node -r esm node_modules/.bin/jest
内容的提问来源于stack exchange,提问作者Alireza
相关产品推荐
相关产品推荐

