前端代码规范最佳实践:eslint+prettier+editorconfig+lint-staged

【前言】

项目开发过程中,用到各种代码规范性工具。

时不时就会出现,多种工具重复作用,相互之间有冲突的情况。

比如:按照 prettier 的规则格式化的代码,不符合 eslint 的规定。于是 eslint 报错。


本文,旨在彻底理清各代码规范工具的作用,并提供无冲突配合使用的解决方案。

文章整理自:https://blog.theodo.com/2019/08/empower-your-dev-environment-with-eslint-prettier-and-editorconfig-with-no-conflicts/

其中附带了一些自己的理解。如有偏差,烦请指正。


一、开始做事之前,先明确目的

问自己一个问题:

为项目配置代码规范,要达到什么目的?


【答案】

1.开发过程中,如果写出不符合我们规范的代码,能够及时提醒开发者,便于及时修复(eslint的能力)

2.保存/粘贴代码时、使用格式化快捷键时,能够自动按照我们制定的规范、格式化代码(prettier的能力)

3.不同开发者如果使用不同的编辑器(sublime/vscode)或系统(windows/mac),能够执行统一的代码风格标准。比如:缩进是tab还是space,结尾end_of_line是lf还是crlf(editorconfig的能力 —— 用于覆盖编辑器的默认配置)


二、再次明确 eslint、prettier、editorconfig 各自能力

1.eslint

通过配置 .eslintrc.* 制定团队代码规范。

在代码编写的过程中,出现不符合规范的代码,进行红线提示。帮助开发者及时更正不符合规范的代码。

同时,提供命令行检查规范及 auto-fix 能力。

【具体】

检查 main.js 文件的代码规范:

npx eslint main.js

自动修复 main.js 部分规范问题(通常如:缺少/多余分号,缩进格式等):

npx eslint main.js --fix

【注意】

eslint 的 auto-fix,能够修复的规范问题比较有限。

通常,需要较大变动才能修复的规范问题,eslint 无法自动修复。如:单行不能超过 80 个字符。

2.prettier

根据规范,自动格式化代码。具有比 eslint auto-fix 更加强大的代码规范性修复能力。

npx prettier main.js --write

prettier 会根据 .eslintrc.* 的约定,修复 main.js 的规范性问题。包括较大变动才能修复的规范问题。如:单行不能超过 80 个字符。

3.editorconfig

编辑器配置。用于覆盖编辑器默认配置,以确保不同编辑器之间,代码格式的统一。

比如,使用 editorconfig,规定开发过程中,点击 tab 按钮,是以 tab 格式进行缩进,还是以 space 格式进行缩进。

如果没有约定,不同的编辑器,或者相同编辑器、不同开发者的配置存在差异,可能出现,有的人是 tab 缩进、有的人是 space 缩进的情况,造成代码风格的差异。

【注】

vscode 这类编辑器,需要自行安装 editorconfig 插件。


三、进行配置(js文件)

1.安装 eslint + prettier

yarn add eslint prettier -D

2.安装 eslint-config-prettier

yarn add eslint-config-prettier -D

【作用】

让所有可能会与 prettier 规则存在冲突的 eslint rule,失效,并使用 prettier 的规则进行代码检查。

相当于,用 prettier 的规则,覆盖掉 eslint:recommended 的部分规则。

后面 prettier 格式化,也会根据这个规则来。因此,不会再有冲突。

【使用】

.eslintrc.js

{

    "extends": ["eslint:recommended", "prettier"]

}


3.安装 eslint-plugin-prettier

yarn add eslint-plugin-prettier -D

【作用】

将 prettier 的能力集成到 eslint 中。按照 prettier 的规则检查代码规范性,并进行修复。

【使用】

.eslintrc.js

{

    "rules":{

        "prettier/prettier":"error" // 不符合 prettier 规则的代码,要进行错误提示(红线)

    },

    "plugins": ["prettier"]

}

{

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

}

【看一下效果】

npx eslint --fix main.js

至此,eslint 会拥有和 prettier 一样的修复能力。

像 prettier 一样,格式化所有不符合规范的代码。


4.使用编辑器,自动格式化代码

(1)使用自己编辑器的快捷键,格式化代码

以 vscode 为例:shift + option + f

默认格式化规则选择 prettier,即可完成代码格式化。

(2)保存代码,自动格式化

同样以 vscode 为例,打开你的 settings.json,添加下面这句话:

"editor.formatOnSave": true

【注】

至此,js、json、less等文件,均可实现自动格式化。

文件格式化规则,遵从我们在 .eslintrc.js 里的配置。也就是,使用我们的 prettier 插件默认规则去格式化。

【附】

如果你使用的是 webstorm,或许可以参考这个 https://www.jianshu.com/p/2f3cad152192


5.规则定制化

保存任意 js 文件,观察当前规则是否符合期望。如果不符合,根目录下创建 .prettierrc,进行定制化配置。

如 .prettierrc 如下:

{

      "singleQuote": true

}

再次保存代码,prettier 将会把 js 文件中的双引号,全部格式化为单引号。


至此,对 js 文件的规范定义与自动格式化配置,全部完成。

【注】

这里的 .prettierrc,具有格式化规则的最高优先级。


四、让 eslint 认识 js 以外的更多语法【以 typescript 为例】

1.安装

(1)使用 ts,自然要安装 typescript

(2)为了让 eslint 认识 ts 语法,要安装相应的 parser

(3)为了指定 ts 代码的规范,要安装相应的 plugin

yarn add typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin -D


2.配置

{

    "parser":"@typescript-eslint/parser",

    "extends":["plugin:@typescript-eslint/recommended", "eslint:recommended", "prettier"],

    "env":{

        "es6":true,

        "node":true

    },

    "rules":{

        "prettier/prettier":"error"

    },

    "plugins": ["prettier"]

}

【注】extends 的含义

告诉 eslint,根据指定的规范,去检查指定类型的文件。

如上例:

根据 @typescript-eslint/recommended 规范,检查 ts 代码。

根据 eslint:recommended + prettier 规范,去检查 js 代码。

当某一类型的文件,被制定了不止1个规范,存在某些规范冲突时,后面的会覆盖掉前面的。

在本例中,prettier 制定的规范,会覆盖掉 eslint:recommended 的某些规范。

eslint 会按照覆盖后的规则,去检查 js 文件。


3.使用

npx eslint --fix main.ts

【如果能够正常格式化】

done。

【如果出现问题】

这里,eslint 会使用 prettier 插件,根据 prettier 的规则格式化代码。

但同时,eslint 会根据 @typescript-eslint/recommended 的规则,检查代码规范性。

当 @typescript-eslint/recommended 的规则和 prettier 的规则出现不一致,就会造成,格式化后的代码,报 eslint 错误的问题。


4.解决冲突(如果存在冲突)

使用相应的 prettier 插件,消除冲突。

也就是说,prettier 的规则和 @typescript-eslint/recommended 存在冲突,那就使用 prettier/@typescript-eslint 插件。

和前面,使用 eslint-config-prettier 消除 eslint:recommended 与 prettier 的规则冲突,同理。

具体可以使用那些插件,查阅:https://github.com/prettier/eslint-config-prettier

它们全部由 eslint-config-prettier 这个库提供。

{

   "parser":"@typescript-eslint/parser",

    "extends":[

        "plugin:@typescript-eslint/recommended", 

        "eslint:recommended", 

        "prettier", 

        "prettier/@typescript-eslint"

    ],

    "env":{

        "es6":true,

        "node":true

    },

    "rules":{

        "prettier/prettier":"error"

    },

    "plugins": ["prettier"]

}

【注意】

这里,不要通过手动写 rules,去消除出现的冲突。

因为,已经发现的冲突,可能只是部分冲突,手写 rule 不能完整解决冲突问题,会存在遗漏。


5.自定义规则

当 prettier 插件的默认规则,与团队习惯不符合时,进行规则自定义。

(1)校验规则定义(.eslintrc.js)

{

   "parser":"@typescript-eslint/parser",

    "extends":[

        "plugin:@typescript-eslint/recommended", 

        "eslint:recommended", 

        "prettier", 

        "prettier/@typescript-eslint"

    ],

    "env":{

        "es6":true,

        "node":true

    },

    "rules":{

        "prettier/prettier":"error",

        // 比如,自定义缩进约束为4格(注意:这个规则会对所有文件生效,不只是ts)      

        "@typescript-eslint/indent": ["error", 4]     

    },

    "plugins": ["prettier"]

}

(2)格式化规则定义(.prettierrc)

{

    "tabWidth": 4  // 与 eslint 的自定义规则保持一致

}


五、Prettier 和 EditorConfig

有些规则,editorconfig 和 .prettierrc 同时可以定义。

因此,我们要避免冗余、重复的定义。

这些规则如下:

end_of_line

indent_style

indent_size/tab_width

max_line_length

我们将这些规则的定义,均放在 .editorconfig 中。

配置好 .editorconfig 后,保存代码,即使没有配置 .prettierrc,prettier 也会按照 .editorconfig 的定义来格式化代码。


六、规范检查增强(husky + lint-staged)

在 git commit 之前,先强制执行prettier格式化(防止某些成员开发期间不开启编辑器格式化)、再检查代码规范,如果检查不通过、阻止提交。

1.新建 .eslintignore + .prettierignore

.eslintignore、.prettierignore,参考如下:

.DS_Store

node_modules

dist


.gitignore

.eslintignore

.prettierignore

LICENSE

README.md

yarn.lock

# local env files

.env.local

.env.*.local

# Log files

npm-debug.log*

yarn-debug.log*

yarn-error.log*

# Editor directories and files

.idea

.vscode

*.suo

*.ntvs*

*.njsproj

*.sln

*.sw?


2.安装

yarn add husky lint-staged -D


3.使用

package.json添加:

"scripts": {

    "lint": "eslint .",

    "prettier": "prettier --write ."

},

"husky": {

    "hooks": {

      "pre-commit": "lint-staged"

    }

  },

  "lint-staged": {

    "*": [

        "npm run prettier", 

        "npm run lint",

        "git add ."

    ]

  }

git commit 之前,会自动使用 prettier 格式化 ignore 之外的代码。格式化后,自动检查所有文件,是否全部符合 eslint 规范。

存在不符合规范的代码,git commit 将被终止。

【注】

因为 prettier 只是会帮我们格式化代码,并不能够修复所有 eslint 错误,比如定义未使用的变量,prettier 不会自动帮我们删除,要手动删除。

因此,prettier 后再 eslint,是有必要的。