ts-jest项目中的ESM模块支持指南
前言
在现代JavaScript生态系统中,ES模块(ESM)已经成为标准模块系统。本文将详细介绍如何在ts-jest项目中配置和使用ESM支持,帮助开发者顺利过渡到ESM模块系统。
ESM支持的核心概念
基本要求
在使用ts-jest时,Jest会考虑以下ESM相关因素:
- ESM运行时环境
- tsconfig文件中
module
选项的值必须满足以下条件之一:- 设置为
Node16
/Node18
/NodeNext
,同时package.json中必须有"type": "module"
- 或者设置为ES标准值,如
ES2015
、ES2020
等
- 设置为
配置Jest运行时
注意事项
目前Jest运行时在ESM支持方面存在一些限制:
- 尚未完全支持根据package.json中的
"type": "module"
自动切换到ESM模式 - 对ES模块的模拟(mocking)功能尚未完全支持
启用ESM模式
要启用ESM支持,需要使用--experimental-vm-modules
标志运行Jest:
node --experimental-vm-modules node_modules/jest/bin/jest.js
对于Yarn用户,可以使用以下替代命令:
yarn node --experimental-vm-modules $(yarn bin jest)
TypeScript配置提示
如果使用TypeScript编写Jest配置,需要安装ts-node作为开发依赖:
npm install -D ts-node
配置TypeScript
方案一:使用ES模块值
推荐使用ES2022
或ESNext
以获得完整的ESM特性支持:
{
"compilerOptions": {
"module": "ES2022",
"target": "ESNext",
"esModuleInterop": true
}
}
方案二:使用混合模块值
目前代码转换器仅支持在isolatedModules: true
时使用混合值:
{
"compilerOptions": {
"module": "Node16",
"target": "ESNext",
"esModuleInterop": true,
"isolatedModules": true
}
}
配置Jest
使用ESM预设
ts-jest提供了专门的ESM预设创建函数:
import type { Config } from 'jest'
import { createDefaultEsmPreset } from 'ts-jest'
const presetConfig = createDefaultEsmPreset({
// 可选配置项
})
export default {
...presetConfig,
} satisfies Config
不使用预设的手动配置
import type { Config } from 'jest'
import { TS_EXT_TO_TREAT_AS_ESM, ESM_TS_TRANSFORM_PATTERN } from 'ts-jest'
export default {
extensionsToTreatAsEsm: [...TS_EXT_TO_TREAT_AS_ESM],
transform: {
[ESM_TS_TRANSFORM_PATTERN]: [
'ts-jest',
{
useESM: true,
// 其他ts-jest选项
},
],
},
} satisfies Config
处理.mjs/.mts扩展名
要支持.mts扩展名,除了启用ESM模式外,还需要:
- package.json中包含
"type": "module"
- 自定义Jest解析器处理.mjs扩展名
示例解析器实现:
import type { SyncResolver } from 'jest-resolve'
const mjsResolver: SyncResolver = (path, options) => {
const mjsExtRegex = /\.mjs$/i
const resolver = options.defaultResolver
if (mjsExtRegex.test(path)) {
try {
return resolver(path.replace(mjsExtRegex, '.mts'), options)
} catch {
// 回退到默认解析器
}
}
return resolver(path, options)
}
export default mjsResolver
然后在Jest配置中引用:
import type { Config } from 'jest'
const config: Config = {
resolver: '<rootDir>/path/to/custom-resolver.ts',
// 其他配置项
}
常见问题解决
- 模块加载问题:对于Angular库的ESM构建文件或node_modules外的ESM文件,可能需要使用
moduleNameMapper
或自定义解析器 - 扩展名处理:确保正确处理.mjs/.mts扩展名,特别是当它们位于不同位置时
- 类型检查:使用
isolatedModules: true
可以提高类型检查的可靠性
最佳实践建议
- 对于新项目,推荐使用
ES2022
或ESNext
模块系统 - 大型项目迁移时,考虑逐步过渡,可以同时维护CJS和ESM配置
- 密切关注Jest对ESM支持的更新,特别是模拟功能的改进
- 对于混合代码库,自定义解析器可以提供更好的灵活性
通过遵循上述指南,开发者可以在ts-jest项目中充分利用ESM的优势,同时保持与现有测试基础设施的兼容性。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考