jest报错SyntaxError: Cannot use import statement outside a module解决方法总结

15,586 阅读3分钟

前言

前段时间在项目中配置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)/)"
  ]
}

结语

希望对大家有帮助,求点赞!