升级ES6导出类库后Jest测试报Cannot use import statement outside a module错误
I’ve hit this exact snag before when migrating dependencies to ES modules—Jest’s default CommonJS environment doesn’t play nice with untranspiled ES imports out of the box. Let’s walk through targeted fixes tailored to your provided config files:
1. Update Jest Config to Transpile ES Modules
Jest ignores node_modules by default, so if your upgraded library lives there or is a local ES module, you need to explicitly tell Jest to transform it. Modify your jest.config.js:
module.exports = { roots: ['<rootDir>/src/'], transform: { '^.+\\.tsx?$': 'ts-jest', // Add transform for JS files if your library uses .js ES exports '^.+\\.jsx?$': 'babel-jest', }, testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.ts?$', moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], // Allow Jest to process your ES module library (replace `your-library-name` with the actual package name) transformIgnorePatterns: ['/node_modules/(?!your-library-name)/'], // Flag .ts/.js files as ES modules for Jest extensionsToTreatAsEsm: ['.ts', '.js'], globals: { 'ts-jest': { // Use a test-specific TS config (we'll create this next) tsconfig: 'tsconfig.test.json', // Enable ESM support for ts-jest useESM: true, }, }, };
2. Create a Test-Specific TypeScript Config
Your main tsconfig.json uses module: commonjs, which clashes with ES module imports. Make a tsconfig.test.json in your project root to align with Jest’s needs:
{ "extends": "./tsconfig.json", "compilerOptions": { "module": "ESNext", "moduleResolution": "node", "allowImportingTsExtensions": true, "noEmit": true } }
This extends your base config but switches to ES module syntax for testing, which plays better with ts-jest’s ESM support.
3. Adjust Babel Config for Test Environment
Ensure your Babel preset-env explicitly uses CommonJS modules in test mode—this guarantees Jest can parse transformed code correctly. Update your babel.config.js:
module.exports = { presets: [ [ '@babel/preset-env', { targets: { ie: '11' }, // Don't lock modules globally—let the test env override it modules: false, }, ], '@babel/typescript', ], plugins: [ ['@babel/plugin-proposal-class-properties', { loose: true }], '@babel/plugin-proposal-object-rest-spread', '@babel/plugin-transform-object-assign', '@babel/plugin-transform-runtime', ], env: { development: {}, production: { plugins: ['transform-dev-warning'], ignore: ['**/test/'], }, test: { presets: [ ['@babel/preset-env', { modules: 'commonjs' }], '@babel/typescript', ], sourceMaps: 'both', }, }, };
Setting modules: false globally lets Babel preserve ES modules for bundlers, while forcing commonjs in test mode keeps Jest happy.
4. Check package.json for Module Type
If your project root package.json includes "type": "module", confirm Jest knows to handle ESM:
- Keep the
extensionsToTreatAsEsmsetting in your jest.config.js (as added earlier) - Or add
"jest": {"extensionsToTreatAsEsm": [".ts", ".js"]}directly to your package.json
Quick Troubleshooting Tips
- If your library is local (not in node_modules), double-check its file extensions—use
.mjsor add"type": "module"to its package.json - Clear Jest cache with
jest --clearCacheafter making config changes—old cached transforms can cause odd, hard-to-debug issues - Verify your test files aren’t mixing CommonJS/ES imports (e.g.,
require()alongsideimport)
内容的提问来源于stack exchange,提问作者codehero

