CodeceptJS升级nanoid4触发[ERR_REQUIRE_ESM]报错如何解决?
问题根因
nanoid 从v4大版本开始,不再提供CommonJS格式的构建产物,包根目录的package.json中声明了"type": "module",仅支持ESM规范的导入方式。
当前你的CodeceptJS运行测试时,默认使用CommonJS规范加载脚本;虽然代码里写的是ESM风格的import语法,但现有tsconfig配置下,ts-node转译TS代码时会将静态import转换为CommonJS的require()调用,用require()去加载仅支持ESM的nanoid v4,就会触发ERR_REQUIRE_ESM报错。
排查思路
- 确认nanoid实际安装版本:执行
npm ls nanoid,如果返回版本号为4.x及以上,即可确认是版本带来的模块规范兼容问题 - 确认测试运行时的模块模式:检查CodeceptJS启动参数、ts-node配置,确认当前是否以CommonJS模式加载测试脚本,默认配置下CodeceptJS+ts-node的组合是走CJS加载逻辑
- 验证TS转译结果:临时开启ts-node的转译日志,检查转译后的JS代码,确认
import { customAlphabet } from 'nanoid'是否被转换为const { customAlphabet } = require('nanoid'),如果是则和报错提示的非法require调用完全对应
修复方案
按改造成本从低到高排序,可任选一种方案解决:
方案1:降级nanoid到CJS兼容版本(最省事)
nanoid v3.x版本同时兼容CommonJS和ESM规范,核心API和v4完全一致,能覆盖绝大多数测试场景的使用需求,不需要修改任何现有业务/测试代码:
npm install nanoid@3.3.7 --save-dev
安装完成后直接重新运行测试即可。
方案2:将测试运行环境切换为ESM模式(保留nanoid v4版本)
如果必须使用nanoid v4的新特性,可以把整个测试运行环境调整为ESM模式:
- 在项目根目录的
package.json中添加顶层字段:"type": "module" - 修改
tsconfig.json的compilerOptions配置:- 将
module字段值从ES6改为NodeNext - 将
moduleResolution字段值从node改为NodeNext
- 将
- 修改CodeceptJS测试启动命令,指定ESM格式的ts-node加载器:
npx codeceptjs run --loader ts-node/esm
*注意:该方案需要确认项目中所有测试相关依赖都支持ESM规范,否则可能触发新的模块兼容报错。
方案3:使用动态导入加载nanoid(最小范围改动)
如果不想降级版本,也不想修改全局模块配置,可以直接在测试代码中用CJS环境支持的动态import()异步加载nanoid,不需要调整其他配置:
// 移除原有的顶部静态import,在使用nanoid的代码块中通过动态导入加载 test('signup test', async ({ I }) => { const { customAlphabet } = await import('nanoid'); const generateId = customAlphabet('abcdefghijklmnopqrstuvwxyz0123456789', 10); const testAccount = generateId(); // 后续测试逻辑 })
*注意:动态导入返回Promise,调用时需要配合async/await使用,CodeceptJS原生支持async格式的测试用例,不会影响测试执行逻辑。
内容的提问来源于stack exchange,提问作者meds
相关产品推荐
相关产品推荐

