标签: travis

  • 解决 mocha 测试时 `cannot use import statement outside a module` 错误,以及配置 travis

    解决 mocha 测试时 `cannot use import statement outside a module` 错误,以及配置 travis

    前些天同事突然发现一个库项目的测试无法运行,报错的内容大概是:cannot use import statement outside a module "should",即无法在模块外使用 import 导入内容。这个错误比较奇怪,简单 Google 之,基本上大家的解决方案都是使用 <script type="module"> 即在浏览器里用 ESM 加载 JS,这明显和我们的环境不同。

    Node.js 当然也支持 ESM,不过这应该也不是问题症结。大体上我可以判断,因为测试集(JS 文件)用到 import 语法,而且用 mocha --require @babel/register 启动测试,所以应该是 Babel 没有正确转译导致的问题。

    检查 Babel 的相关配置,发现同事为了能同时编译现代浏览器和 IE 两个版本的库,.babelrc 大概是这样的:

    {
      "env": {
        "default": {
          "presets": [],
        },
        "withie": {
          "presets": [],
        }
      }
    }

    猜测 mocha 走了 default 分支,然后没有转译,所以出错。解决方案就是添加 node 分支,以当前 node 版本为 target,这样该转译就转译,不转译就用原生,性能更好,修改好的配置大概是这样的:

    {
      "env": {
        "default": {"presets": []},
        "withie": {"presets": []},
        "node": {
          "presets": [
            [
              "@babel/preset-env",
              {
                "targets": {
                  "node": "current"
                },
                "useBuiltIns": false
              }
            ]
          ]
        }
      }
    }

    使用时,需要增加环境变量用来切换配置:BABEL_ENV=node mocha --require @babel/register。比较奇怪的是,其他脚本使用 BROWSERSLIST_ENV 切换,这里只能使用 BABEL_ENV,我暂时不知道为什么。

    修改之后的脚本就可以正常测试了。接下来我打算给它加上 Travis,这样就能自动 lint + 测试,比较方便控制质量。加 Travis 很简单,拷过来一个 .travis.yml 改吧改吧就行了,但是第一次运行失败了,而且是超时。经过研究,原来 mocha 从 v4 开始,完成测试后不会自动退出,除非手动指定,方法是增加 --exit 参数。

    所以最终的测试脚本是(其它配置略去):

    {
      "scripts": {
        "test": "BABEL_ENV=node mocha --require @babel/register --exit",
      }
    }

    最终 Travis 配置是:

    sudo: required
      dist: trusty
     
    
      language: node_js
      node_js:
        - 14
     
    
      branches:
        only:
          - master
     
    
      cache:
        directories:
          - ~/.npm # cache npm's cache
          - ~/npm # cache latest npm
     
    
      install:
        - npm ci
     
    
      script:
        - npm run lint
        - npm run test