使用 ESlint、lint-staged 半自动提升项目代码质量

2字数 2418阅读 12557

最近在项目部署了ESlint还有一些配套的工具,比如 prettier husky lint-staged,有些心得写出来分享下。

依据本篇可以实现在git commit之时,重新格式化代码,同时进行代码检查预防一些低级错误。最终期待项目中的开发人员提交到线上的代码符合代码规范、风格统一,看起来像是一个人写的。

实现过程

-> 待提交的代码
-> git add 添加到暂存区
-> 执行 git commit
-> husky注册在git pre-commit的钩子调起 lint-staged
-> lint-staged 取得所有被提交的文件依次执行写好的任务(ESLint 和 Prettier)
-> 如果有错误(没通过ESlint检查)则停止任务,等待下次commit,同时打印错误信息
-> 成功提交

嗯……这个任务链看起来挺长的,但不要怕,也只是需要装的模块有点多罢了。
可以看成两个部分,代码整理部分、pre-commit 函数部分。

husky 注册 git hook

安装

npm i --save-dev husky lint-staged

添加 hook 函数

// package.json
{
...
    "scripts": {
        ...
        "precommit": "lint-staged", // git commit 执行这个命令,这个命令在调起 lint-staged
    },
    "lint-staged": {   // lint-staged 配置
        "app/**/*.{js,jsx}": [
            "prettier --tab-width 4 --write",
            "eslint --fix",
            "git add"
        ]
    },
...
}

这里 lint-staged 的配置是:在 git 的待提交的文件中,在 app 目录下的所有 .js .jsx 都要执行三条命令。前两条一会儿说,后一条是将处理过的代码重新 add 到 git 中。

粘贴的时候记得删掉注释,我们知道JSON是没有注释的

prettier 格式化代码

prettier 是强大的代码格式化工具,目的是统一团队的代码格式。相对于 ESlint 代码检查能力较弱。

安装

npm i --save-dev --save-exact prettier 

然后……就完成了~ 🎉🎉🎉

这里解释下刚才写在 lint-staged 里的命令参数

prettier --tab-width 4 --write

--tab-width 4 :使用4个空格作为缩进 (嗯,我更喜欢2个,不过……我们的代码规范是4个 😷)
如果想用tab作为缩进可以加上--use-tabs, 这时--tab-width代表tab数量。

--write:默认prettier是直接标准输出到终端的,这个配置代表直接改写文件。

关于prettier的还有一些配置参考这里

ESLint

ESLint 相对来说是比较复杂的部分,很多次我都被繁多的规则和海量的报错吓退过,但好在概念很容易理解,在翻看别的开源项目的时候,发现真正要自行配置的规则也不过尔尔。

而ESLint的作用主要是为了检查代码有没有错误,有没有不和代码规范的地方。虽然 ESLint 有 --fix 的选项,可以自动修复一些格式上的问题,但程度并不能和 Prettier 相当。

Prettier的概念更像是无论你怎么写,走到我这里,都会被格式成我这一种样子。而ESLint 只在发现问题的地方进行 fix,这是两者在逻辑上有区别。

配置 ESLint 主要是配置规则,规则从何而来,那当然是人写的。所以我们在很多项目里都能见到类似 .eslintrc.json等类似的文件,这就是 ESLint 的配置文件。建议是初始化后一点一点修改这个配置文件,不要照抄Airbnb等等类似的规范,不然上来可能就报非常多的错误,一看就头大。

安装:

npm install --save-dev eslint 

// 如果项目使用了 React 需要再安一个 babel-eslint
npm install --save-dev eslint babel-eslint

ESLint 也可以全局安装,全局安装后可以方便用 ESLint 直接执行。

ESLint 初始化

ESLint 初始化可以帮助开发者快速生成一个基本的配置框架。

在项目文件夹下执行

node_modules/.bin/eslint --init
// 如果全局安装了 可以直接 eslint --init

这里会给我们三种方式来初始化ESlint

image

分别是 1. 问问题 2. 使用大厂的 3. 检查现有的代码自动生成

�我们这里直接选第一个,回答一些问题来确定配置。

image

根据实际情况回答就好了,即使不小心答错也没关系,都在配置文件里随时可以修改。


image

部分同学可能有疑惑关于line endings ,其实看一下编辑器下面,如果是 LF 选择 Windows,CR 就选 Linux 就好了 。这个关于windows和linux对换行符的定义不同导致的,有兴趣的同学可以自己搜搜。

image

生成的.eslintrc.json 根据选择的回答不同,大体都长这样

{
    "env": { 
        "browser": true,
        "commonjs": true,
        "es6": true
    },
    "extends": "eslint:recommended",
    "parserOptions": {
        "ecmaFeatures": {
            "experimentalObjectRestSpread": true,
            "jsx": true
        },
        "sourceType": "module"
    },
    "plugins": [
        "react"
    ],
    "rules": {
        "indent": [
            "error",
            4
        ],
        "linebreak-style": [
            "error",
            "windows"
        ],
        "quotes": [
            "error",
            "single"
        ],
        "semi": [
            "error",
            "always"
        ]
    }
}

ESLint 配置解释:

env: Environments,指定代码的运行环境。不同的运行环境,全局变量不一样,指明运行环境这样ESLint就能识别特定的全局变量。同时也会开启对应环境的语法支持,例如:es6。

parser:ESLint 默认使用Espree作为其解析器,但它并不能很好的适应 React 环境,所以刚才安装了 babel-eslint 用来代替默认的解析器,在配置里这么写"parser": "babel-eslint"

plugins:顾名思义就是插件,插件是单独的npm包,命名一般以eslint-plugin开头,写的时候用字符串数组的形式,可以省略eslint-plugin开头。plugins一般包含一个或多个规则配置,可以在extends中引入。

extends:ESLint 不需要自行定义大量的规则,因为很多规则已被分组作为一个规则配置。

例如:eslint:recommended就是 ESLint 的推荐规则配置,包含了ESLint的规则 里前面有✔︎的部分,recommended 规则只在ESLint升级大版本的才有可能改变。

相对的 eslint:all 是应用所有的规则,但并不推荐这么做。另外,all 规则是根据版本随时变化的。
extends 还可以以字符串数组的形式定义。

"extends": ["eslint:recommended", "plugin:react/recommended"],

plugin:react/recommended 即为 eslint-plugin-react 插件中的提供的推荐规则配置

另外还有一点,extends定义的规则如果有重复的,后面的规则会覆盖前面的。

rules:这里可以对规则进行细致的定义了,覆盖之前前面说的extends中定义的规则。例如 indent就是对缩进的修改。"indent": ["error",4] 前面一项代表错误等级,第二项是具体配置,有些规则有第三项选项,例如 indent 就有 { "SwitchCase": 1 },代表对switch语句采取什么样的缩进策略,如果不设默认是0。具体可以定义什么 rules,可以参考这里

错误等级有三级 012,分别代表offwarningerror。error错误会终止 lint-staged 执行。

globals:全局变量,如果你的项目用到其他一些自定义的全局变量,"__DEV__": false这样配置,true
和 false 代表可不可以被修改。

其他可用的配置参考这个

React Native 项目的配置例子

{
  "parser": "babel-eslint",
  "env": {
    "commonjs": true,
    "es6": true,
    "react-native/react-native": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:react/recommended",
  ],
  "parserOptions": {
    "ecmaFeatures": {
      "experimentalObjectRestSpread": true,
      "jsx": true
    },
    "sourceType": "module"
  },
  "plugins": [
    "react",
    "react-native",
  ],
  "rules": {
    "no-unused-vars": 1,
    "react/prop-types": 1,
    "react/display-name": 0,
  }
}

~后面跟了一堆是全局变量,没有使用 react-native 的 config 是因为到目前还不适配 ESLint 4版本。~
eslint-plugin-react-native已经更新了,这样配置又简洁了一些。

调试配置

配置肯定是不能拿来就用的,推荐先就只使用 eslint:recommended 版本,如果你的项目 indent 比较特殊,再到 rules 定义 indent 就可以了。

然后先用命令行命令先对代码库里比较典型文件测试一下

node_modules/.bin/eslint app/app.js --fix

加上 --fix 会自动修复一些问题,规则列表里前面有小扳手的是可以自动修复的。

image

不用担心,一开始肯定特别多。根据报错信息最后的规则名称,搜索搞清楚到底是为什么错,看这个错误对于你的项目库是什么程度,再到rules里去自定义这条规则。

处理好这一步,就完成部署 commit 自动处理代码的流程了。如果代码没有通过 ESLint 检查,就会出现这种通知,停止commit。

Webstorm


Webstorm

Terminal


image

Webstorm 插件

从前面看出 Webstorm的通知是不太友好的,我们可以用Webstorm的配置,方便更快的找到错误的发生点(但不是必须的)。

内置了ESlint工具

Webstorm 内置了ESlint工具,启动之后可以在编辑的时候就能看到哪里出错需要修复。

image

选好 Node 环境路径和 ESLint 包路径,勾线Enable就好了,会自动寻找ESLint的配置。
ESlint 路径:~/Documents/{Your Project}/node_modules/eslint

还可以在快捷键设置里给 Fix ESLint Problem 添加一个快捷键,快速进行代码格式化的操作。

image

个人感觉在检查代码出错的时候比较好用,但在实际写代码的时候我个人还是倾向于不开这个来写,经常看到报错信息,令人心情不好。

External Tools

我更倾向于自己写一个 External Tools ,方便对当前文件执行命令,在提交之前或者提交报错之后跑一遍,有详细的报错清单,找起来也很方便(但没打开ESLint设置看起来更直观)。

image

下面三项填入

node_modules/.bin/eslint
--fix $FilePathRelativeToProjectRoot$
$ProjectFileDir$

External Tools 可以设置快捷键,也可以通过 Webstorm 的命令面板搜索打开 cmd + shift + a

image
image

推荐阅读更多精彩内容