跳到主要内容

ESLint And Prettier

ESLint

npm i eslint -D

npx eslint --init # 创建配置文件
npx eslint index.js # 只输出正确格式的文件内容,不修改源文件
npx eslint indexjs --fix # 自动修复语法或格式错误

配置文件

eslint社区存在诸多第三方配置文件(以eslint-config-开头)和插件(以eslint-plugin-开头)以供我们使用,我们可以在extendsplugins字段中引用这些类库,此时我们可以省略对应的前缀。

对于作用域模块,规则如下

{
"extends": ["@akara/test", "prettier"], // 等于@akara/eslint-config-test eslint-config-prettier
"plugins": ["@akara"] // 等于@akara/eslint-plugin
}
extends

有几种常见的配置文件可以提供给我们继承。

  1. eslint核心规则eslint:recommendedeslint:all
  2. eslint-config-*导出的配置
  3. eslint-plugin-*导出的配置
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended", // @typescript-eslint/eslint-plugin
"prettier" // eslint-config-prettier
]
}
parser

如同我在编译器一节所述,eslint默认解析器espree并不支持对TS代码的解析,我们可以使用@typescript-eslint/parser进行替代。

npm i --save-dev typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin
module.exports = {
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint"
],
};

parserOptions

解析器的选项,默认为espree的选项。当我们使用其他解析器时,解析器选项的属性可能有一些出入。

{
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module",
"ecmaFeature": {
"jsx": true
}
}
}
ecmaVersion

set to 3, 5 (default), 6, 7, 8, 9, 10, 11, or 12 to specify the version of ECMAScript syntax you want to use. You can also set to 2015 (same as 6), 2016 (same as 7), 2017 (same as 8), 2018 (same as 9), 2019 (same as 10), 2020 (same as 11), or 2021 (same as 12) to use the year-based naming. You can also set "latest" to use the most recently supported version.

sourceType

set to "script" (default) or "module" if your code is in ECMAScript modules.

代码存在importexport时需要设置为module

ecmaFeature

an object indicating which additional language features you'd like to use:

  • globalReturn - allow return statements in the global scope
  • impliedStrict - enable global strict mode (if ecmaVersion is 5 or greater)
  • jsx - enable JSX

我们需要先安装eslint-plugin-react,再将JSX设置为true

{
"parserOptions": {
"ecmaFeature": {
"jsx": true
}
},
"extends": [
"plugin:react/recommended"
],
}

If you do not use a preset you will need to specify individual rules and add extra configuration.

{
"parserOptions": {
"ecmaFeatures": {
"jsx": true
}
},
"plugins": [
"react"
],
"rules": {
// 定制规则
}
}
env

支持不同环境的内置变量

{
"env": {
"browser": true,
"commonjs": true,
"es2021": true
}
}
browser

支持window等浏览器环境变量

node

支持process等node环境变量

commonjs

CommonJS global variables and CommonJS scoping (use this for browser-only code that uses Browserify/WebPack).

支持module变量

es2021
{
"env": {
"es2021": true
}
}

supporting ES6 syntax is not the same as supporting new ES6 globals (e.g., new types such as Set). For ES6 syntax, use { "parserOptions": { "ecmaVersion": 6 } }; for new ES6 global variables, use { "env": { "es6": true } }. { "env": { "es6": true } } enables ES6 syntax automatically, but { "parserOptions": { "ecmaVersion": 6 } } does not enable ES6 globals automatically.

globals

指定全局变量

{
"globals": {
"Promise": 'off'
},
}
plugins

列出几个常见插件。

@typescript-eslint/eslint-plugin
eslint-plugin-react

通过ecmaFeature.JSX,支持react代码提示

eslint-plugin-react-hooks

支持hook提示,比如提示useCallback函数依赖项

eslint-plugin-prettier

prettier作为eslint的格式化工具

rules

定义规则,每个eslint规则有三种模式:offwarnerror。分别是:关闭,警告,报错。

module.exports = {
"rules": {
"quotes": ["warn", "double"], // 不是双引号就提醒
"semi": ["error", "always"] // 不带分号就报错
}
}

Prettier

npm i prettier -D
prettier filename # 只输出正确格式的文件内容,不修改源文件
prettier filename --check # 检查文件格式是否错误
prettier filename --write # 格式化源文件

使用prettier并不强制要求存在配置文件,不过为了自定义我们都会创建个配置文件

// prettier.config.js or .prettierrc.js
module.exports = {
// 结尾不加分号
semi: false,
// 字符串单引号
singleQuote: true,
useTabs: false,
// 四格缩进
tabWidth: 4,
// 箭头函数 总是有小括号
arrowParens: 'always',
printWidth: 120,
}

ESLint With Prettier

Prettier用于实现代码的格式化,而ESLint虽然主要功能是代码质量的检查,但也能够实现代码的格式化。如果我们需要同时使用这两个工具,那么就可能要面对两个工具代码格式化的冲突,现在主流的思想是ESLint只用来检查代码质量,用Prettier实现格式化。

我们通常有两种办法实现这两个工具的整合。

  • 方案一:prettier-eslint

    这个方案的思路是先使用prettier格式化源码,再使用ESLint --fix来处理代码。那么这个方案最大的问题就是Prettier的格式化规则会被ESlint覆盖。

    npm install -D prettier-eslint prettier-eslint-cli
    npx prettier-eslint index.js
  • 方案二(推荐):eslint-config-prettier + eslint-plugin-prettier

    这个方案的思路是使用eslint-config-prettier屏蔽ESLint的代码格式化功能,让ESLint专注于代码质量的检查,同时使用eslint-plugin-prettierprettier作为ESLint的插件来实现代码的格式化。

    这两个工具能够分别单独使用,只是主流都会搭配着使用

    npm install -D eslint-config-prettier eslint-plugin-prettier
    // .eslintrc.json
    {
    "extends": ["prettier"], // eslint-config-prettier
    "plugins": ["prettier"], // eslint-plugin-prettier
    "rules": {
    "prettier/prettier": "error" // eslint-plugin-prettier
    }
    }

    extendsprettier需要放置在最后

    或者我们可以使用eslint-plugin-prettier提供的一种便捷写法,效果几乎等同于上述的配置。

    // .eslintrc.json
    {
    "extends": ["plugin:prettier/recommended"]
    }

    在这之后,我们就可以在.eslintrc.js中配置语法规则,在.prettierrc.js中配置代码格式化规则了。

    由于我们实际上使用的是eslint实现语法检查和格式化(以prettier为插件实现),我们在VSCode安装ESLint扩展也支持代码提示自动格式化功能

    // .vscode/setting.json
    "editor.codeActionsOnSave": {
    "source.fixAll": true,
    },

CommitLint

在成熟的项目中我们需要保持commit message的整齐和一致,使用commitlint可以对其内容进行检查和约束。

npm i -D @commitlint/cli @commitlint/config-conventional
// commitlint.config.js
module.exports = {
extends: ['@commitlint/config-conventional']
}

默认情况commitlint会对标准输入流进行检查。

echo 'chore: nothing' | npx commitlint

通常我们会搭配husky使用CommitLint

npx husky add .husky/commit-msg 'npx --no-install commitlint --edit $1'
git commit -m 'chore: nothing'

常见的提交类型如下

[
'build', // 构建相关
'chore', // 琐事
'ci', // ci相关
'docs', // 文档相关
'feat', // 新特性
'fix', // 修复bug
'perf', // 性能相关
'refactor', // 重构
'revert', // 回退
'style', // 代码样式相关
'test' // 测试相关
]

Husky

当项目中存在eslintprettier,开发者只需要安装VSCode插件即可做到对代码错误的检查自动格式化,除此之外我们还希望能在代码提交之前做一些检查自动格式化,或者是对commit message格式进行检查,防止意外的提交出现。

事实上git自带了hooks功能,创建.git/hook/pre-commit并编写脚本内容,即可做到在代码提交前执行某些操作。不过由于.git文件夹不会被提交进代码仓库,在多人项目协作上这成为了一个痛点,此时我们可以使用Husky库来实现git hook

npm install husky -D
npx husky install # 使用.husky作为git hooks目录
npm set-script prepare "husky install" # 多人项目中默认启用husky
npx husky add .husky/pre-commit "eslint --fix"
npx husky add .husky/commit-msg "commitlint"

通常git hook的配置都会被放进.git/hooks文件夹内部,而git已经引入了core/hooksPath,即能够让我们指定hooks存放的目录。npx husky install会在项目创建.husky目录来存放hooks

老版本的Husky是基于.huskyrcpackage.json进行配置,而现在已经放弃了这种做法 Why husky has dropped conventional JS config

Lint-Staged

通过Husky我们能够在提交代码前使用ESLint对代码进行检查,但此时我们需要手动指定ESLint作用的文件,但其实我们知道我们只想要检查已经stagedgit add)的代码,Lint-Staged库可以轻松的实现这个功能。

{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.js": "eslint --cache --fix",
"*.{js,css,md}": "prettier --write"
}
}