前言
前段时间在项目中配置jest,一直遇到SyntaxError: Cannot use import statement outside a module
的问题,查了很多资料,虽然最后发现导致错误的原因比较简单,但是既然都花了时间去研究,就记录一下各种解决方法吧。
解决方法
1.没有用babel转换es6语法
jest是运行在node环境的,所以不支持es6语法,我们需要通过配置babel来讲es6语法转换为es5语法。
安装babel-jest、@babel/core、@babel/preset-env
npm i babel-jest @babel/core @babel/preset-env -D
在根目录新建babel.config.js文件,添加如下配置:
module.exports = {
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": true
}
}
]
]
}
注意:这是babel7的配置,babel6有所不同,如果是用babel6可以到jest文档看看babel6配置。
假如你项目中用到typescript,还需要安装ts-babel
npm i ts-babel -D
这个时候需要在jest.config.js中添加如下配置:
module.exports = {
...其他配置...
transform: {
'^.+\\.jsx?$": "babel-jest', //这个是jest的默认配置
'^.+\\.ts?$': 'ts-jest', //typescript转换
}
}
2.依赖定位错误
这个是我所犯的错误,姑且将原因归结为依赖定位错误吧,原因是跟alias有关。相信用cli工具搭建过项目的同学都知道用@
来代替根目录的src目录这个用法吧,既然你在webpack中配置了alias,那在jest中也要进行相应配置,在jest.config.js中添加如下配置:
module.exports = {
...其他配置...
moduleNameMapper:{
'@': '<rootDir>/src'
}
}
大家也许会觉得这样子就ok了,但是有没有发现babel的库是@
开头的,问题来了,因为jest中配置了@
别名,因此也会将@babel开头的库也一起转换了,导致无法使用babel,因此就相当于是没有安装babel,所以我们需要进行如下改造:
module.exports = {
...其他配置...
moduleNameMapper:{
'@/(.*)$': '<rootDir>/src/$1'
}
}
3.玄学原因
我在jest的github中看到好几个issue,发起的人给出的配置正常,但是仍然出现这个报错,然后有人说自己也是一样的问题,然后通过将babel的配置文件.babelrc
改为babel.config.js
就可以了,我觉得这个比较玄学,因为babel7仍然兼容.babelrc
文件,不知道是不是真的,姑且康康。
4.需要转换node_modules中的文件
jest默认配置是不转换node_modules文件夹的,因为一般来说我们通过npm下载的库都是已经转换过的了,但是也有例外,像react-native相关的一些库就会出现这种情况,遇到这种情况,拿react-native举例,我们需要在jest.config.js中进行如下配置:
module.exports = {
...其他配置...
'transformIgnorePatterns': [
"node_modules/(?!(react-native|my-project|react-native-button)/)"
]
}
结语
希望对大家有帮助,求点赞!