Jest 28搭配React时不带文件扩展名的模块导入失效问题
问题原因
Jest 28 版本对模块解析逻辑做了破坏性更新,核心变动是默认对齐 Node.js 原生 ESM 解析规范:当文件被识别为 ESM 格式时,所有相对路径导入必须显式写全文件扩展名,不再自动读取moduleFileExtensions配置做后缀补全,这就是升级后无扩展名导入报错、手动补全扩展名后测试恢复正常的核心原因。
报错截图如下:
触发该问题的常见场景:
- 项目根目录
package.json中声明了"type": "module",Jest 会默认将所有.js/.ts文件按 ESM 规则解析 - 自定义的
babelTransform转译配置中设置了modules: false,转译输出保留 ESM 格式的import/export语句,Jest 会将这类文件识别为 ESM 模块,触发严格解析规则
你当前配置中moduleFileExtensions字段本身没有配置错误,只是ESM解析模式下该配置不会用于隐式补全相对导入的扩展名。另外你贴出的FileTransform.js存在明显代码问题:使用了path模块但未显式引入,虽然不是本次导入报错的直接诱因,但运行到静态资源转译时会抛出path is not defined错误,需要一并修复。
修复方案
根据项目的模块规范选择对应方案即可:
- 方案1:恢复 CommonJS 解析逻辑(改造成本最低,完全适配原有代码)
调整测试环境下的 Babel 转译配置,将模块输出改为 CommonJS 格式,不要保留 ESM 语句。如果使用@babel/preset-env,测试环境的配置参考如下:
如果根目录// 测试环境专用babel配置 module.exports = { presets: [ ['@babel/preset-env', { targets: {node: 'current'}, modules: 'commonjs' // 核心配置,禁止设为false }], '@babel/preset-typescript', '@babel/preset-react' ] }package.json设置了"type": "module",可删除该配置,或通过jest的transform配置强制转译输出为CJS格式。 - 方案2:保留 ESM 模式,通过自定义解析器兼容无扩展名导入
如果项目需要保留 ESM 输出格式,可安装兼容旧版解析逻辑的resolver,恢复隐式扩展名补全能力:- 安装开发依赖:执行
npm i -D jest-ts-webcompat-resolver - 在jest配置中新增resolver字段:
module.exports = { // 原有配置保持不变 resolver: require.resolve('jest-ts-webcompat-resolver') } - 安装开发依赖:执行
- 方案3:全局适配 ESM 规范(长期维护推荐)
按照 Node.js ESM 规范修改所有导入语句,补全对应文件扩展名,同时调整jest配置适配ESM模式:module.exports = { // 原有配置保持不变 extensionsToTreatAsEsm: ['.ts', '.tsx', '.jsx'], transform: { // 调整原有transform配置,开启ESM转译支持 '^.+\\.(js|jsx|ts|tsx)$': ['babel-jest', {useESM: true}], // 其余transform配置不变 } } - 额外bug修复与配置优化
- 补全
FileTransform.js缺失的依赖引入,修正后代码如下:
const path = require('path'); // 补上缺失的path模块引入 module.exports = { process(src, filename) { const assetFilename = JSON.stringify(path.basename(filename)); return `module.exports = ${assetFilename};`; } };- 你当前配置中的
testURL: 'http://localhost'在Jest28中已废弃,可移到testEnvironmentOptions中消除警告,调整后配置如下:
testEnvironmentOptions: { pretendToBeVisual: true, url: 'http://localhost' // 替代原testURL配置 }, - 补全
内容的提问来源于stack exchange,提问作者Daniel Stoian
相关产品推荐
相关产品推荐


