fi3ework / blog

📝

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

为create-react-app配置ESLint

fi3ework opened this issue · comments

commented

问题

项目一开始使用的是 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,况且背着一堆 error 工作的代码本身就是有风险的,lint 工具就是来规避这些风险的)

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 这种服务器自动刷新页面,并弹出一个遮罩层显示错误。

参考

哈哈,把这个注释掉,就不会影响webpack编译了。直接用ide的插件改lint就好了。

{
        test: /\.(js|mjs|jsx)$/,
        enforce: 'pre',
        use: [
          {
            options: {
              formatter: require.resolve('react-dev-utils/eslintFormatter'),
              eslintPath: require.resolve('eslint'),
              emitWarning: true,
            },
            loader: require.resolve('eslint-loader'),
          },
        ],
        include: paths.appSrc,
      },