Jest测试Discord.js触发ES模块导入错误,求配置调整方案
解决Jest+ts-jest测试Discord.js时的"Must use import to load ES Module"错误
问题背景
项目基于Node.js+Discord.js,用Jest+ts-jest做测试,tsconfig输出为CommonJS(因Knex等工具对ESM支持不佳)。所有导入Discord.js的测试均报错Must use import to load ES Module,指向undici的wasm文件,其他ESM模块测试正常。
错误原因
Discord.js现已改为纯ESM模块,当前Jest配置存在以下问题:
modulePathIgnorePatterns忽略了discord.js,导致ts-jest未对其进行转换处理.js后缀的moduleNameMapper规则影响了Discord.js依赖(如undici)的ESM加载逻辑- 未正确配置
transformIgnorePatterns来处理node_modules中的ESM模块
解决方案(无需大幅修改tsconfig)
修改Jest配置文件,调整关键项如下:
- 修正
moduleNameMapper:移除多余的discord.js映射,限定.js后缀规则仅作用于项目内部文件,避免干扰node_modules模块 - 移除
modulePathIgnorePatterns中的discord.js:让ts-jest能够处理Discord.js模块 - 添加
transformIgnorePatterns:指定需要ts-jest转换的node_modules中的ESM模块(discord.js及其核心依赖) - 调整ts-jest的ESM处理配置:启用
isolatedModules避免ESM模块的类型检查冲突
修改后的Jest配置:
import type { InitialOptionsTsJest } from 'ts-jest/dist/types'; const jestOptions: InitialOptionsTsJest = { preset: 'ts-jest', testEnvironment: 'node', setupFilesAfterEnv: ['./jest.setup.ts'], transform: { '\.[jt]sx?$': [ 'ts-jest', { useESM: true, isolatedModules: true, }, ], }, moduleNameMapper: { // 仅映射项目内部的.js后缀文件 '^(.+\\.js)$': '<rootDir>/src/$1', }, moduleDirectories: ['node_modules', 'src'], extensionsToTreatAsEsm: ['.ts', '.json'], // 仅转换discord.js及其核心依赖,忽略其他node_modules模块 transformIgnorePatterns: [ 'node_modules/(?!(discord.js|undici|@discordjs)/)', ], clearMocks: true, }; export default jestOptions;
可选的tsconfig微调(不影响CommonJS输出)
在tsconfig.json的compilerOptions中确保以下配置启用:
"allowSyntheticDefaultImports": true, "esModuleInterop": true
这能提升对ESM模块的兼容性,同时不改变输出为CommonJS的核心配置。
验证
重新运行测试命令,导入Discord.js的测试应能正常执行,不再出现ES模块加载错误。
内容的提问来源于stack exchange,提问作者Kobold
相关产品推荐
相关产品推荐

