
Jest 默认不支持 import/export 语法,需通过 Babel 将 ES 模块转译为 CommonJS,并配置 transformIgnorePatterns 以正确处理 node_modules 中的 ESM 依赖。
jest 默认不支持 `import`/`export` 语法,需通过 babel 将 es 模块转译为 commonjs,并配置 `transformignorepatterns` 以正确处理 node_modules 中的 esm 依赖。
Jest 在 v29 及更早版本中默认运行于 CommonJS(CJS)环境,因此遇到 import axios from 'axios' 这类语句时会抛出 SyntaxError: Cannot use import statement outside a module 错误。根本原因在于:Jest 的测试运行时未启用原生 ESM 支持,且未对源码或第三方模块执行必要的语法降级。
✅ 正确配置方案(推荐稳定实践)
1. 配置 Babel 将 ES 模块转为 CommonJS
在项目根目录创建或更新 babel.config.js(不要用 .babelrc,因 Jest v29+ 推荐使用 babel.config.js 以支持环境条件判断):
// babel.config.js
module.exports = {
presets: [
['@babel/preset-env', {
targets: {
node: 'current' // 关键:强制输出 CJS,禁用 ES 模块语法
},
modules: 'commonjs' // 显式指定模块转换方式(可选但强烈建议)
}]
],
env: {
test: {
// 测试环境下额外确保兼容性
plugins: ['@babel/plugin-transform-modules-commonjs']
}
}
};
⚠️ 注意:
targets.node = 'current'会令 Babel 忽略type: "module"和.mjs文件的 ESM 语义,统一输出require()形式;若省略此配置,Babel 可能保留import,导致 Jest 仍报错。
2. 更新 Jest 配置以处理 node_modules 中的 ESM
许多现代库(如 axios@1.6+、@tanstack/react-query 等)已默认发布 ESM 格式。Jest 默认跳过 node_modules 转译,因此需显式放行相关包:
// package.json 或 jest.config.js
{
"jest": {
"transform": {
"^.+\.jsx?$": "babel-jest"
},
"transformIgnorePatterns": [
"/node_modules/(?!axios|@tanstack|lodash-es)" // 按需添加实际使用的 ESM 库名
]
}
}
✅ 示例说明:上述正则表示“忽略所有 node_modules,但允许 axios、@tanstack/* 和 lodash-es 被 Babel 处理”。
3. 验证配置生效
运行测试前,可通过以下命令检查 Babel 是否正确转译:
npx babel src/hooks/useTreeDataFetching.js --config-file ./babel.config.js
预期输出应包含 var axios = require('./lib/axios.js'); 而非 import axios from ...。
❌ 不推荐的替代方案
- 启用 Jest 实验性 ESM 支持(
"type": "module"+"extensionsToTreatAsEsm": [".js"]):文档明确标注为 experimental,存在动态导入、路径解析、HMR 兼容性等不稳定问题,不适用于生产级测试套件。 - 手动改写
import为require():破坏开发一致性,不可维护。
总结
解决 Jest ESM 识别问题的核心是 双管齐下:
① 用 Babel(配合 targets.node 和 modules: 'commonjs')将源码与白名单依赖转为 CJS;
② 用 transformIgnorePatterns 精准控制哪些 node_modules 需参与转译。
该方案稳定、可复现、与 CRA/webpack/Vite 开发环境解耦,是当前社区主流实践。











