Jest配置忽略node_modules仍报import语句模块外使用错误
Jest 单元测试报 ESM 语法错误问题
问题现象
- 使用 Jest 进行单元测试时,抛出
SyntaxError: Cannot use import statement outside a module报错,溯源后发现错误来自jsdom-worker包依赖引入的node-fetch包,初步怀疑问题与node-fetch包相关,但无法完全确认。 - 已经在
jest.config.js中配置了忽略node_modules路径,仍出现该问题,不清楚具体原因。
当前 jest.config.js 配置文件内容如下:
const ignores = ['/node_modules/', '/__fixtures__/', '/fixtures/', '/__tests__/helpers/', '/__tests__/utils/', '__mocks__']; module.exports = { preset: 'ts-jest', roots: ['<rootDir>'], modulePaths: [ "<rootDir>/src" ], moduleDirectories: [ "node_modules" ], transformIgnorePatterns: [...ignores], transform: { '^.+\\.(ts|tsx|js|jsx)?$': 'ts-jest', '^.+\\.(gif|svg|ico)$': '<rootDir>/svgTransform.js', }, testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.js?$', moduleFileExtensions: ['tsx', 'js', 'json', 'node', 'ts'], moduleNameMapper: { "\\.(css|less|scss|sass)$": "identity-obj-proxy" }, clearMocks: true, // collectCoverage: true, // todo // coverageDirectory: "coverage", // todo testEnvironment: 'jsdom', setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect', 'jsdom-worker'], } // }
问题更新
将 node-fetch 版本降级至 2.4 后,上述报错消失,但其他包又出现了完全相同的语法错误,问题反复出现。
代码报错追踪截图:
已尝试的配置
当前使用的 babel.config.js
配置逻辑为测试环境下将模块转为 CommonJS 格式,方便 Jest 识别,具体内容如下:
// 测试环境下需要将模块转为CommonJS格式,Jest才可正常识别 const isTest = String(process.env.NODE_ENV) === 'test' const isProd = String(process.env.NODE_ENV) === 'production' module.exports = { // 用于转换TSX及其他React相关Babel插件 presets: [ // 根据目标环境智能完成转译 ['@babel/preset-env', { modules: isTest ? 'commonjs' : false }], // 让Babel支持TypeScript语法 '@babel/preset-typescript', ], }
尝试过的第三方Babel配置
曾尝试使用kcd-scripts内置的Babel配置,对应代码如下:
"use strict"; const browserslist = require('browserslist'); const semver = require('semver'); const { ifDep, ifAnyDep, ifTypescript, parseEnv, appDirectory, pkg } = require('../utils'); const { BABEL_ENV, NODE_ENV, BUILD_FORMAT } = process.env; const isTest = (BABEL_ENV || NODE_ENV) === 'test'; const isPreact = parseEnv('BUILD_PREACT', false); const isRollup = parseEnv('BUILD_ROLLUP', false); const isUMD = BUILD_FORMAT === 'umd'; const isCJS = BUILD_FORMAT === 'cjs'; const isWebpack = parseEnv('BUILD_WEBPACK', false); const isMinify = parseEnv('BUILD_MINIFY', false); const treeshake = parseEnv('BUILD_TREESHAKE', isRollup || isWebpack); const alias = parseEnv('BUILD_ALIAS', isPreact ? { react: 'preact' } : null); const hasBabelRuntimeDep = Boolean(pkg.dependencies && pkg.dependencies['@babel/runtime']); const RUNTIME_HELPERS_WARN = '你应当将@babel/runtime添加为项目依赖,这样可以直接复用node_modules中的babel helper代码,避免在每个文件中重复打包helper副本'; if (!treeshake && !hasBabelRuntimeDep && !isTest) { throw new Error(RUNTIME_HELPERS_WARN); } else if (treeshake && !isUMD && !hasBabelRuntimeDep) { console.warn(RUNTIME_HELPERS_WARN); } /** * 按照browserslist声明的策略加载浏览器配置,未找到自定义配置时回退到默认配置 */ const browsersConfig = browserslist.loadConfig({ path: appDirectory }) || ['defaults']; const envTargets = isTest ? { node: 'current' } : isWebpack || isRollup ? { browsers: browsersConfig } : { node: getNodeVersion(pkg) }; const envOptions = { modules: false, loose: true, targets: envTargets }; module.exports = () => ({ presets: [[require.resolve('@babel/preset-env'), envOptions], ifAnyDep(['react', 'preact'], [require.resolve('@babel/preset-react'), { pragma: isPreact ? ifDep('react', 'React.h', 'h') : undefined }]), ifTypescript([require.resolve('@babel/preset-typescript')])].filter(Boolean), plugins: [[require.resolve('@babel/plugin-transform-runtime'), { useESModules: treeshake && !isCJS }], require.resolve('babel-plugin-macros'), alias ? [require.resolve('babel-plugin-module-resolver'), { root: ['./src'], alias }] : null, ifAnyDep(['react', 'preact'], [require.resolve('babel-plugin-transform-react-remove-prop-types'), isPreact ? { removeImport: true } : { mode: 'unsafe-wrap' }]), isUMD ? require.resolve('babel-plugin-transform-inline-environment-variables') : null, [require.resolve('@babel/plugin-proposal-class-properties'), { loose: true }], isMinify ? require.resolve('babel-plugin-minify-dead-code-elimination') : null, treeshake ? null : require.resolve('@babel/plugin-transform-modules-commonjs')].filter(Boolean) }); function getNodeVersion({ engines: { node: nodeVersion = '10.13' } = {} }) { const oldestVersion = semver.validRange(nodeVersion).replace(/[>=<|]/g, ' ').split(' ').filter(Boolean).sort(semver.compare)[0]; if (!oldestVersion) { throw new Error(`无法从package.json的engines.node字段配置的"${nodeVersion}"范围中确定最低支持的Node版本,请调整版本范围配置避免歧义。`); } return oldestVersion; }
内容的提问来源于stack exchange,提问作者AAMCODE
相关产品推荐
相关产品推荐

