从0到1配置eslint (所有人一看就懂)

22,545 阅读8分钟

序言

我们有很多的理由去做代码检查。

比如,随着项目规模增大时,很小的错误都可能导致页面异常,不仅影响用户使用,还要耗费大量时间来调试。而原因可能是有个小伙伴手抖多打了一个字符,中途去做其他事情了,导致代码写了一半……我们不能指望肉眼解决所有问题。

如果能有一个趁手的代码检查工具,帮助我们去做代码检查,该有多好?这便是本文的目的,从0到1带领大家将ESlint应用到我们的开发环境当中。让我们开始吧!

ESlint基本配置

$ yarn add eslint --dev

有了eslint之后,我们就能通过它来检查指定的代码文件了。我们在npm scripts加入如下脚本

{
  ...
  "scripts": {
    ...
    "test-eslint": "eslint src/**/*.js src/**/*.jsx"
    ...
  }
  ...
}

在命令行中运行 yarn run test-eslint 会提示缺少eslint的配置

yarn run v0.23.2
$ eslint src/**/*.js src/**/*.jsx 

Oops! Something went wrong! :(

ESLint couldn't find a configuration file. To set up a configuration file for this project, please run:

    eslint --init

ESLint looked for configuration files in /Users/mytream/WebstormProjects/tezign-web-customer/src/common and its ancestors.

If you think you already have a configuration file or if you need more help, please stop by the ESLint chat room: https://gitter.im/eslint/eslint

error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

下面我们就准备配置配置文件 .eslintrc

touch .eslintrc

yarn run test-eslint

控制台输出如下信息

/Users/mytream/WebstormProjects/tezign-web-customer/src/common/cache.js
  3:1  error  Parsing error: The keyword 'export' is reserved

/Users/mytream/WebstormProjects/tezign-web-customer/src/common/constants.js
  1:5  error  Parsing error: Unexpected token pkg

/Users/mytream/WebstormProjects/tezign-web-customer/src/common/dom.js
  1:1  error  Parsing error: The keyword 'import' is reserved

/Users/mytream/WebstormProjects/tezign-web-customer/src/common/enum.js
  3:1  error  Parsing error: The keyword 'const' is reserved

/Users/mytream/WebstormProjects/tezign-web-customer/src/common/history.js
  1:1  error  Parsing error: The keyword 'import' is reserved

这是因为我们还没有在配置文件.eslintrc中配置parserOptions来指定语言版本为和模块类型。

于是我们在.eslintrc添加如下配置, 指定ES版本ecmaVersion为7,也就是ES2016, 指定模块类型sourceType为module,如此便支持export和import来导出并引用文件

{
  "parserOptions": {
    "ecmaVersion": 7,
    "sourceType": "module"
  }
}

再执行yarn run test-eslint之后,控制台输出如下信息

/Users/mytream/WebstormProjects/tezign-web-customer/src/containers/Root.jsx
  110:5  error  Parsing error: Unexpected token <

/Users/mytream/WebstormProjects/tezign-web-customer/src/layouts/default.jsx
  14:7  error  Parsing error: Unexpected token <

/Users/mytream/WebstormProjects/tezign-web-customer/src/layouts/screen.jsx
  9:7  error  Parsing error: Unexpected token <

/Users/mytream/WebstormProjects/tezign-web-customer/src/views/404.jsx
  21:7  error  Parsing error: Unexpected token <

eslint还不能识别JSX语法,我们添加如下配置

{
  "parserOptions": {
    "ecmaVersion": 7,
    "sourceType": "module",
    "ecmaFeatures": { // 添加ES特性支持,使之能够识别ES6语法
      "jsx": true
    }
  }
}

eslint配置文件中是支持行后注释的

如此,test-eslint之后,检查就通过了。

怎么会这么顺利呢?怎么可能一行警告或报错都没有呢?这是因为eslint配置文件默认是不提供任何代码的检查规则的,这都需要我们在配置文件中进行。于是我们添加下面两行规则:

{
  ...
  "rules": {
    "semi": "warn"
  }
  ...
}

控制台开始出现大量的警告信息:

/Users/mytream/WebstormProjects/tezign-web-customer/src/common/cache.js
  38:47  warning  Missing semicolon  semi

/Users/mytream/WebstormProjects/tezign-web-customer/src/common/dom.js
  1:23  warning  Missing semicolon  semi

/Users/mytream/WebstormProjects/tezign-web-customer/src/common/history.js
  1:43  warning  Missing semicolon  semi

/Users/mytream/WebstormProjects/tezign-web-customer/src/common/http.js
    3:32  warning  Missing semicolon  semi
    5:36  warning  Missing semicolon  semi
    6:26  warning  Missing semicolon  semi
    7:40  warning  Missing semicolon  semi
  103:7   warning  Missing semicolon  semi
  107:5   warning  Missing semicolon  semi

/Users/mytream/WebstormProjects/tezign-web-customer/src/common/notice.js
  16:4  warning  Missing semicolon  semi
  17:3  warning  Missing semicolon  semi

我们设置的规则 "semi": "warn" 生效了,规则semi的意思是行末必须使用分号,它的值可以是"off"(或0), "warn"(或 1), "error"(或2),具体含义也很明确。

页面规则下列出了eslint内部支持的所有的规则,包含可能的错误、最佳实践、变量使用等等分类的规则,我们只要根据需要在配置文件中添加我们需要校验的规则即可。

当然我们不想手动的加入这么多规则,我们使用 extends 关键字加入eslint推荐的规则。同时我们关闭(覆盖)掉 semi 规则的检查。

{
  ...
  "extends": "eslint:recommended",
  "rules": {
    "semi": "off"
  }
  ...
}

校验结果出来了,也没有再对分号进行校验,这很好,有的同学喜欢这样的风格,我们不想强制。

/Users/mytream/WebstormProjects/tezign-web-customer/src/common/cache.js
   5:16  error  'Promise' is not defined            no-undef
   5:43  error  'reject' is defined but never used  no-unused-vars
   6:7   error  'localStorage' is not defined       no-undef
  12:16  error  'Promise' is not defined            no-undef
  15:15  error  'localStorage' is not defined       no-undef
  22:16  error  'Promise' is not defined            no-undef
  22:43  error  'reject' is defined but never used  no-unused-vars
  25:9   error  'localStorage' is not defined       no-undef
  31:16  error  'Promise' is not defined            no-undef
  31:43  error  'reject' is defined but never used  no-unused-vars
  33:7   error  'localStorage' is not defined       no-undef
  38:5   error  'window' is not defined             no-undef
  41:5   error  'window' is not defined             no-undef

/Users/mytream/WebstormProjects/tezign-web-customer/src/common/constants.js
   1:11  error  'require' is not defined        no-undef
  18:4   error  '__DEV_MODEL__' is not defined  no-undef
  22:5   error  '__DEV__' is not defined        no-undef
  25:5   error  '__QA__' is not defined         no-undef
  28:5   error  '__YZ__' is not defined         no-undef
  31:5   error  '__DEMO__' is not defined       no-undef
  34:5   error  '__PROD__' is not defined       no-undef

我们来分析一下其他的结果,Promise、window提示未定义是因为我们没有指定代码执行的环境es6 和 browser, 这可以在env配置中添加。DEV QA 这些配置字符,我们可以指定为全局变量

{
  ...
  "env": {
    "es6": true,
    "browser": true
  },
  "globals": {
    "__DEV_MODEL__": true,
    "__DEV__": true,
    "__QA__": true,
    "__YZ__": true,
    "__DEMO__": true,
    "__PROD__": true
  }
  ...
}

再次执行之后,我们看到了真正想要的检查结果 😄

/Users/mytream/WebstormProjects/tezign-web-customer/src/common/cache.js
   5:43  error  'reject' is defined but never used  no-unused-vars
  22:43  error  'reject' is defined but never used  no-unused-vars
  31:43  error  'reject' is defined but never used  no-unused-vars

/Users/mytream/WebstormProjects/tezign-web-customer/src/common/constants.js
  1:11  error  'require' is not defined  no-undef

/Users/mytream/WebstormProjects/tezign-web-customer/src/common/dom.js
  132:24  error  'getPageOffset' is not defined  no-undef

/Users/mytream/WebstormProjects/tezign-web-customer/src/common/history.js
  13:3  error  '_' is not defined  no-undef

/Users/mytream/WebstormProjects/tezign-web-customer/src/common/http.js
   7:9   error  'message' is defined but never used  no-unused-vars
  10:40  error  'err' is defined but never used      no-unused-vars
  13:38  error  'err' is defined but never used      no-unused-vars
  16:38  error  'err' is defined but never used      no-unused-vars

我们要做的就是,去修改这些错误就可以了。

ESlint规则的扩展

到现在为止我们都很顺利,但是有没有针对React、Vue甚至Angular相关的一些检查规则呢,我们可以把测试框架比如Jest集成到这个流程当中来呢?大家可以查看awesome-eslint来查看社区为我们提供的工具、插件、配置甚至学习文档。

我们以插件eslint-plugin-react为例,增加React相关的检查规则。首先,需要安装这个插件,然后在.eslintrc增加相应的配置

# 增加插件
yarn add --dev eslint-plugin-react

# 添加react检查规则,并且排除我们不想要的规则
{
  "extends": [
    "eslint:recommended",
    "plugin:react/recommended"
  ],
  "rules": {
    ...
    "react/prop-types": "off"
  },
}

检查之后我们获得了想要的结果

:11  error  Unexpected console statement                           no-console
  147:11  error  Unexpected console statement                           no-console
  388:20  error  Using this.refs is deprecated                          react/no-string-refs
  393:5   error  Unexpected console statement                           no-console
  404:5   error  Using this.refs is deprecated                          react/no-string-refs
  414:30  error  '_' is not defined                                     no-undef
  490:21  error  Using string literals in ref attributes is deprecated  react/no-string-refs
  518:34  error  Using string literals in ref attributes is deprecated  react/no-string-refs

有的小伙伴在执行的时候会提示,模块eslint-plugin-react找不到,这是因为你的eslit 和 插件不在一个环境下,要么都是全局的,要么都在工程下的 node_modules 中。

不过我们建议都安装在node_modules下面,并且记录到package.json中,方便其他小伙伴使用。

将ESlint整合到git流程

So far so good ! 唯一让我们感觉不够完美的就是每次我们想做eslitn检查的时候,我们都要手动的执行一下yarn run test-eslint。能不能在我提交代码的时候给我自动检查(强制检查 😋)。

答案是可以的。还差最后几步我们就可以把这一套应用于开发环境了。

# 使用husky来设置git hooks
yarn add husky --dev

# 在npm scripts中增加precommit prepush(必须这么拼写)
{
  "scripts": {
    "precommit": "npm run test-eslint",
    "prepush": "npm run test-eslint",
    "test-eslint": "eslint src/**/*.js src/**/*.jsx"
    ...
  }
}

之后我们便直接commit代码

git commit -m 'eslint before commit'

husky > npm run -s precommit (node v8.1.4)


/Users/mytream/WebstormProjects/tezign-web-customer/src/common/cache.js
   5:43  error  'reject' is defined but never used  no-unused-vars
  22:43  error  'reject' is defined but never used  no-unused-vars
  31:43  error  'reject' is defined but never used  no-unused-vars
...

我们提交失败了,这也是我们期望的结果,只有把信息中提到的问题都修改掉,才能提交成功。

在一些紧急情况下,我们需要马上提交代码,需要跳过检查,加上-n 选项既可

git commit -m 'eslint before commit' -n

总结

在前面我们从0到1介绍了eslint在开发环境中的使用,我们再来回顾一下。

  1. 安装ESlint及相关插件或配置
  2. ESlint基本配置:语言选项、运行环境、全局变量、规则选项等
  3. ESlint plugin及config配置:ESlint的扩展特性
  4. 将ESlint检查集成到git hooks当中

所以,你准备好使用ESlint来做代码检查了吗?

参考资料

  1. 官方文档中文
  2. A Comparison of JavaScript Linting Tools
  3. MDN ESlint
  4. awesome-eslint