如何配置Jest兼容node_modules中不同编译格式的TypeScript依赖
time-span v5及以上版本为纯ESM包,未提供CommonJS导出,Jest默认运行在CommonJS模式下,仅配置ts-jest的ESM预设、单独修改transform规则无法覆盖所有ESM运行所需的配置项,会直接将node_modules下的ESM文件按CommonJS规则解析,触发SyntaxError: Cannot use import statement outside a module异常。
常见漏配点包括:未在package.json中声明ESM模式、未给Jest传入ESM运行参数、transformIgnorePatterns未覆盖time-span的关联ESM依赖、tsconfig模块配置未对齐ESM规范、Jest本地缓存未清理。
按以下步骤逐一核对配置即可修复:
1. 修正package.json基础配置
- 在根层级添加
"type": "module",声明项目内.js文件默认按ESM规范解析 - 修改test脚本,传入ESM运行所需参数:
{ "type": "module", "scripts": { "test": "NODE_OPTIONS=--experimental-vm-modules jest" } }
Windows环境执行上述命令报错的话,先安装cross-env依赖,将脚本替换为cross-env NODE_OPTIONS=--experimental-vm-modules jest即可兼容。
2. 修正jest.config.js配置
重点注意transformIgnorePatterns需要放开time-span及其关联ESM依赖的转译限制,不要漏配ESM识别规则,参考配置如下:
export default { preset: 'ts-jest/presets/default-esm', testEnvironment: 'node', transform: { '^.+\\.tsx?$': ['ts-jest', { useESM: true }] }, // 关键:放行time-span及其依赖的ESM包,交由ts-jest转译 transformIgnorePatterns: [ 'node_modules/(?!(time-span|convert-hrtime|is-number)/)' ], // 处理ESM模式下相对路径导入的后缀解析问题 moduleNameMapper: { '^(\\.{1,2}/.*)\\.js$': '$1' }, // 声明ts文件按ESM模块处理 extensionsToTreatAsEsm: ['.ts'] }
3. 对齐tsconfig.json模块配置
确保compilerOptions下的模块相关配置适配ESM规范,避免ts-jest转译输出CommonJS格式和运行环境冲突,参考配置如下:
{ "compilerOptions": { "target": "ES2020", "module": "NodeNext", "moduleResolution": "NodeNext", "esModuleInterop": true, "strict": true } }
4. 清理缓存重跑测试
Jest默认开启持久化缓存,改完配置先执行清缓存命令再跑测试,避免旧转译结果干扰:
yarn test --clearCache yarn test
兜底方案(不想调整ESM配置时使用)
直接将time-span降级到支持CommonJS的v4版本,无需修改任何ESM相关配置即可正常运行:
yarn add time-span@4.0.0
安装完成后直接执行yarn test即可。
内容的提问来源于stack exchange,提问作者Daniel

