阅读 4905

为create-react-app配置ESLint

『 文章首发于GitHub Blog

问题

项目一开始使用的是create-react-app创建的,配置的ESLint是用的AlloyTeam的eslint-config-alloy/react, 默认配置已经很合理了,并且每条配置都有相应的说明,只需要再根据个人喜好修改一些rule即可,我个人修改的.eslintrc.json配置如下

{
    "extends": [
        "eslint-config-alloy/react"
    ],
    "globals": {
        // 这里填入你的项目需要的全局变量
        // 这里值为 false 表示这个全局变量不允许被重新赋值,比如:
        //
        // jQuery: false,
        // $: false
    },
    "rules": {
        "indent": [
            "warn",
            2,
            {
                "SwitchCase": 1,
                "flatTernaryExpressions": true
            }
        ],
        "semi": [
            "error",
            "never"
        ],
        "react/jsx-indent": [
            "warn",
            2
        ],
        "react/jsx-indent-props": [
            "warn",
            2
        ],
        "no-unused-vars": [
            "warn",
            {
                "vars": "all",
                "args": "none",
                "caughtErrors": "none"
            }
        ]
    }
}
复制代码

但是在eject之后运行npm start后会直接报错

image

思考

按理说,eject前后配置不变,只不过是将配置弹出,npm start 应该可以直接运行,但是却报了ESLint的错误。

一开始我以为是eslint-config-alloy/react的问题,然后重新手写了一些配置依然会报错,证明不是eslint-config-alloy/react的问题。google之后在一个issue发现:

By default Eslint errors will raise webpack errors unless you change the config as shown above.

也就是说,ESLint的会在发现error级别错误的时候触发webpack报错,导致编译失败。

但是为什么在eject之前能通过审查的代码在eject后就遇到error报错了呢?

简单粗暴我们直接看create-react-app文档中关于ESLint的部分

If you want to enable even more accessibility rules, you can create an .eslintrc file in the root of your project with this content:

{
  "extends": ["react-app", "plugin:jsx-a11y/recommended"],
  "plugins": ["jsx-a11y"]
}
复制代码

However, if you are using Create React App and have not ejected, any additional rules will only be displayed in the IDE integrations, but not in the browser or the terminal.

现在回想一下create-react-app中ESLint是如何工作的,终端有warning/error的信息,但是这个打印出来的信息的其实并不是依照eslint-config-alloy/react规则,而是create-react-app的默认规则。在集成在编辑器(我用的VSCode)中的红色波浪线功能则是根据eslint-config-alloy/react规则显示的。

但是在eject后,编译与波浪提示都根据eslint-config-alloy/react规则进行代码审查,所以eject前根据默认规则审查通过的代码在eject后并不能通过eslint-config-alloy/react的审查报了错。(eslint-config-alloy/react规则真的很严格)。

ESLint的error该不该直接退出

在这里还有一个设计思路与使用思路上的冲突:ESLint默认error级别直接报错退出,是因为将某种rule的错误等级定为error时,当出错代码触发了这个rule,就意味着程序根据规则来说已经不对了,就不需要再往后进行编译等等了。所以代码必须先过了ESLint这关(也就是用户自己对代码定下的规则),才能放到babel里去进行编译。(具体的可以看zakas大神关于这个问题的讨论

(我个人之前本来比较喜欢error时不退出,然后选择性的去修改部分有问题的代码,有些报错的代码就不理会等重构的时候再说。但是仔细一想其实违背了ESLint的思想,既然有warning和error的区分,那些不重要的error其实就应该定义为warning。)

eslint-loader配置问题

按照ESLint-loader的文档

failOnError (default: false)

Loader will cause the module build to fail if there are any ESLint errors.

failOnError默认是false,按照说明应该是不会阻止build。

ESLint-loader的作者也提到(不过远在2015年3月)

failOn* are off by default to avoid webpack to break the build for "just some linting issues". So you should not have any error/warning that break the build by default.

然而,实际上build依然失败,具体原因我也不清楚,有几个issue也在反应failOnError不起作用,我猜可能是ESLint-loader没能成功的配置ESLint,这个坑以后仔细研究一下再来填(逃。

解决方案

方案1

eslint-loader的作者给出的解决方案

Like I said, you can use emitWarning: true option to force all ESLint error/warning being reported as warnings

emitWarning设为true就可以了,所有的error/warning信息都会打印出来,error也不会阻止编译,简单粗暴。

rules: [{
  enforce: 'pre',
  test: /\.jsx?$/,
  loader: 'ESLint-loader',
  options: {
    emitWarning: true
  }
}]
复制代码

方案2

遵照zakas大神的设计思路,报error的就阻止编译,改到通过为止,报warning的就打印出来,个人认为这才是正确遵照ESLint的使用方法。

方案3(粗暴)

./node_modules/ESLint-loader/index.js中的

emitter(webpack.version === 2 ? new ESLintError(messages) : messages)
复制代码

直接注释掉!不给ESLint传递任何错误信息,也不会返回错误码了,这样终端永远都是 0 errors 0 warnings(误),错误就只能通过编辑器的红线提示来看了。

tips

Also to note, the actual build still finishes and produces output. This only affects wrappers that would call webpack, such as webpack-dev-server (won't automatically reload the browser if lint errors exist) or frontend-maven-plugin (will fail the maven build if lint errors exist).

这位仁兄提到了关于ESLint其实并不会阻止build,只是会在遇到error时阻止像webpack-dev-server这种服务器对浏览器的自动刷新。

参考

关注下面的标签,发现更多相似文章
评论