目标:
ESLint 是一个 Javascript Linter,ESLint 主要解决的其实是代码质量问题,因为代码质量出问题那就意味着有很大几率会出现 BUG。ESLint 是完全插件化的,每一个规则都是一个插件并且你可以在运行时添加更多的规则。
使用 eslint 好处:
eslint 这里使用 ts 相关版本,安装相应的 eslint 包有:
运行安装:
npm install eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-react -D
我们把所有关于 eslint 的配置都放到 eslintrc.js 文件中,删除 package.json 里面关于 eslint 的配置:
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
新建 .eslintrc.js
module.exports = {
extends: ['react-app', 'plugin:prettier/recommended'],
rules: {
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-console': 0,
'prettier/prettier': 2,
},
};
module.exports = {
// 默认情况下,ESLint会在所有父级组件中寻找配置文件,一直到根目录。ESLint一旦发现配置文件中有 "root": true,它就会停止在父级目录中寻找。
root: true,
// 指定环境
env: {
browser: true, // 预定义的全局变量
es6: true, // 启用 ES6 语法支持以及新的 ES6 全局变量或类型
},
// 扩展配置文件,主要用来使用第三方的eslint的完整配置,一般输出的是整个eslint配置,也可以是别的形式
extends: [
'plugin:vue/essential',
'eslint:recommended',
// 'prettier', // Prettier 是一个代码格式化插件。它并不关心你的语法是否正确,只关心你的代码格式,比如是否使用单引号,语句结尾是否使用分号等等。但是有部分规则和Eslint的冲突。
// 'airbnb-base', // 包含 ECMAScript 6 + 代码规范。 Airbnb 是其中一个最流行的 JavaScript 代码规范,它差不多包含所有 JavaScript 的角度。校验比较严格。
// 'eslint:recommended', // eslint官方扩展
// 'plugin:react/recommended', // 插件类型的扩展,也可以直接在 plugins 属性中进行设置
// 'eslint-config-standard', // 第三方扩展,eslint-config-*
//避免与 prettier 冲突
'plugin:prettier/recommended',
// @vue/cli集成ESLint 使用
/**
'plugin:vue/essential',
【ESLint + Airbnb】
'@vue/airbnb',
【ESLint + Standard】
'@vue/standard'
*/
// 【ESLint + Prettier】
// '@vue/prettier',
],
// 配置插件,使用第三方的eslint的rules,命名格式eslint-plugin-*,插件一般输出的是规则
plugins: [],
parserOptions: {
// 对Babel解析器的包装使其与 ESLint 兼容。
parser: 'babel-eslint'
},
// 启用的规则及其各自的错误级别
rulse: {},
// 指定全局变量
// 1. 将每个全局变量名称设置为等于以true允许覆盖变量或false禁止覆盖
// 2. 还支持在单独的js文件中通过注释配置全局变量 `/* global var1:false, var2:false */`
globals: {
Atomics: 'readonly',
SharedArrayBuffer: 'readonly',
ENV: true,
},
// 禁用一组文件的配置文件中的规则
overrides: [
{
files: ['*-test.js', '*.spec.js'],
rules: {
'no-unused-expressions': 'off',
},
},
],
}
1.parser 解析器及解析参数
parser 指的是将 .js、.ts 文件处理为 AST 使用的解析器。ESLint 附带了一个内置的解析器(espree),因此如果你只编写标准的 JavaScript,就不需要自定义解析器了
如果我们想支持非标准 JavaScript 语法,我们需要做的就是为 ESLint 提供一个可供使用的替代解析器。比如基于 vue 工程需要用到能解析 vue 语法解析器;再比如使用到 TypeScript 的工程,需要配置能解析 TypeScript 的解析器
这里可以类比 webpack,自身只能处理 js、及 json 文件,css、html 等文件需要通过自定义添加 loader 处理来理解
常用解析器:
{
"parserOptions": {
parser: '@babel/eslint-parser',
// 使用的 ECMAScript 版本
"ecmaVersion": 6,
// 设置为 "script" (默认) 或 "module"(如果你的代码是 ECMAScript 模块)。
"sourceType": "module",
}
}
2.rules 规则
启用的规则及其各自的错误级别,ESLint 附带有大量的规则,要改变一个规则设置,你必须将规则 ID 设置为下列值之一:
"rules": {
"eqeqeq": "off", // 要求使用 `===` 和 `!==`
"curly": "error", // 强制所有控制语句使用一致的括号风格
"quotes": ["error", "double"] // 引号
}
3.plugins 插件
ESLint 虽然可以定义很多的 rules,以及通过 extends 来引入更多的规则,但是说到底只是检查 JS 语法。如果需要检查 Vue 中的 template 或者 React 中的 jsx,就束手无策了。所以引入插件的目的就是为了增强 ESLint 的检查能力和范围。
{
"plugins": [
"vue", // 等价于"eslint-plugin-vue"
"@typescript-eslint" // 等价于@typescript-eslint/eslint-plugin
]
}
4.extends 配置扩展
实际项目中配置 rules 的时候,不可能团队一条一条的去商议配置,太费精力了。通常的做法是使用业内大家普通使用的、遵循的编码规范;然后通过 extends 去引入这些规范。extends 配置的时候接受字符串或者数组:
extends 可以理解为 rules 的快捷配置字段,一般先配置 extends 为业内通用规范,且数组时后面的会覆盖前面的,并自定义配置 rules 覆盖 extends 中不满足你想要规范的规则
{
"extends": [
"eslint:recommended",
"plugin:vue/essential", // 实际npm包插件eslint-config-vue/essential [插件名:配置名]
"airbnb-base", // 实际npm包插件eslint-config-vue/airbnb-base
"@vue/prettier",
"./node_modules/coding-standard/.eslintrc-es6"
]
}
从上面的配置,可以知道 extends 支持的配置类型可以是以下几种
常用 extends 配置:
完成配置就可以运行 eslint 对 js 文件进行校验了
// 校验 a.js 和 b.js
npx eslint a.js b.js
// 校验 src 和 scripts 目录
npx eslint src scripts
通常 ESLint 只能校验 js 文件。比如需要校验 .vue 文件,只配置 vue 插件和 vue-eslint-parser 解析器是不够的,还需要让 ESLint 在查找文件的时候找到 .vue 文件。ESLint 提供了 --ext 来指定具体需要校验的文件
npx eslint --ext .js,.vue src
ESLint提供了–fix 来根据规则进行修复
在 pakage.json 中配置
"scripts": {
"lint": "npx eslint --ext .js,.vue src",
"lint:fix": "npx eslint --fix --ext .js,.vue src",
}
对于一些公共的 JS、测试脚本或者是特定目录下的文件习惯上是不需要校验的,因此可以在项目根目录通过创建一个 .eslintignore 文件来配置,告诉 ESLint 校验的时候忽略它们:
# Ignore artifacts:
build
config
node_modules
public
README.md
package.lock
前面做的配置,都需要执行命令才能进行检查和修复代码,还是挺不方便的,如果我希望编辑完或者保存时去检查代码该如何做呢?可以直接在 IDE 里安装 ESLint 插件
在全局配置文件中配置,或者工作区新建 .vscode/settings.json 文件添加保存是进行 eslint 校验和修复
{
"eslint.alwaysShowStatus": true, // 总是在 VSCode 显示 ESLint 的状态
"eslint.quiet": true, // 忽略 warning 的错误
"editor.codeActionsOnSave": { // 保存时使用 ESLint 修复可修复错误
"source.fixAll": true,
"source.fixAll.eslint": true
}
}
当你引入改写引入的组件时,通常需要关闭ESLint检测,以下是集中关闭方式
(1)关闭所有规则/* eslint-disable */
/* eslint-disable */
...
/* eslint-enable */
(2)关闭某一行的所有规则// eslint-disable-line
...; // eslint-disable-line
// eslint-disable-next-line
...;
(3)在某一行关闭指定的规则 // eslint-disable-line no-alert
...; // eslint-disable-line no-alert
// eslint-disable-next-line no-alert
...;
上面的 eslint 我们可以采用比较出名的 airbnb、 standart 规范来格式化代码风格。ESLint 主要是解决代码质量问题,对于代码风格问题并没有太多的约束,而且就算是 Airbnb 也并不是覆盖方方面面的风格,而且也不是所有人都能接受的。Prettier 是代码格式化工具,它是 opinionated 的。采用 Prettier 的最大原因是为了停止所有关于代码风格的争论,它认为使用哪种代码风格不重要,重要的是用没用。所以 Prettier 提倡先提高代码的可读性和可维护性,至于具体使用什么风格它给我们定,这也是 opinionated 的意义。所以最好的处理方式是 Prettier 只负责代码格式的检测并修复,ESLint 只负责代码质量的检测,各自负责自己专项的领域就好了。
Prettier 做的事情是它不管你写的代码是什么样子的,它会去掉代码里的所有样式风格,然后用统一固定的格式重新输出。它通常是考虑行长(line length)来获取代码并重新输出。统一的编码风格能很好的保证代码的可读性。
安装:
npm install prettier eslint-config-prettier eslint-plugin-prettier -D
新建 .prettierrc.js 放入自己定义的规则
module.exports = {
singleQuote: true, // 单引号
tabWidth: 2,
quoteProps: 'as-needed', // 对象中属性加引号
bracketSpacing: true, // 对象字面量括号中的空格
trailingComma: 'all', // 尾逗号
printWidth: 80,
useTabs: false,
endOfLine: 'lf',
bracketSameLine: true,
jsxSingleQuote: true,
singleQuote: true,
semi: true,
arrowParens: 'always',
jsxBracketSameLine: true,
};
需要在.eslintrs.js 的配置中将
'plugin:prettier/recommended'
放到extends最后,这个配置包含两个内容:
在 extends 中使用 eslint-config-pretter 配置关掉与 eslint 规则的冲突
// .eslintrc
{
"extends": ["prettier"] // prettier 一定要是最后一个,才能确保覆盖
}
(可选,推荐) 然后再启用 eslint-plugin-prettier ,将 prettier 的 rules 以插件的形式加入到 ESLint 里面。这里插一句,为什么"可选" ?当你使用 Prettier + ESLint 的时候,其实格式问题两个都有参与,disable ESLint 之后,其实格式的问题已经全部由 prettier 接手了。那我们为什么还要这个 plugin?其实是因为我们期望报错的来源依旧是 ESLint ,使用这个,相当于把 Prettier 推荐的格式问题的配置以 ESLint rules 的方式写入,这样相当于可以统一代码问题的来源。
// .eslintrc
{
"plugins": ["prettier"],
"rules": {
"prettier/prettier": "error"
}
}
将上面两个步骤和在一起就是下面的配置,也是官方的推荐配置
{
"extends": ["plugin:prettier/recommended"]
}
安装依赖:
npm install stylelint stylelint-config-standard stylelint-config-standard-scss stylelint-order stylelint-config-rational-order stylelint-prettier stylelint-config-prettier stylelint-scss -D
根目录新建.stylelintrc.js 文件
module.exports = {
extends: [
'stylelint-config-standard',
'stylelint-config-standard-scss',
'stylelint-config-rational-order',
'stylelint-prettier/recommended',
],
rules: {
indentation: 2, // 用来定义缩进的单位
'no-missing-end-of-source-newline': null, // 为true的时候,每一段css或者scss在最后必须要以新的空行为结尾
'max-nesting-depth': 10, // 限制scss中&字符嵌套深度
'selector-max-compound-selectors': 10, // 限制选择器深度
'at-rule-no-unknown': null, // 为true sass有些语法会报错
'scss/at-rule-no-unknown': true, //如果@extend错写成@exend,则stylelint会因为此规则而报错。
},
plugins: [
'stylelint-scss',
'stylelint-order',
'stylelint-config-rational-order/plugin',
],
};
extends 定义了一个数组,该配置项允许我们 extend 一个已存在的配置文件(无论是你自己的还是第三方的配置)。当一个配置继承了另一个配置,它将会添加自己的属性并覆盖原有的属性。
如果extends 中包含多个配置项,那么数组中的每一项都优先于前一项,也就是说第二项会覆盖第一项,第三项会覆盖第一项和第二项,最后一项将覆盖其它所有项。跟eslint的配置文件 .eslintrc.js 中的 extends 属性用途一样
plugins 定义了一个数组,该配置项允许我们使用第三方插件。一旦声明了插件,在rules中需要为插件的规则添加选项,就像其他标准的规则一样。你需要查看插件的文档去了解规则的名称。
rules 就是用来定义 css 的规则,因为优先级比 extends 高,所以可以用来覆盖extends 中包含在集合里的规则。有时候想要禁用某些规则,只需要在rules里添加上对应的规则,并将值设置为 null,如:
"selector-class-pattern": null
根目录新建 .stylelintignore 文件(忽略的文件)
node_modules
public
dist
es
lib
*.d.ts
在 vscode 中安装插件 stylelint, 并在 settings.json 添加规则,(如果是仅在工作区生效,可在根目录下建立.vscode文件夹,并新建settings.json)
{
// 关闭编辑器内置样式检查(避免与stylelint冲突)
"css.validate": false,
"less.validate": false,
"scss.validate": false,
// 配置stylelint检查的文件的范围
"stylelint.validate": ["css", "less", "postcss", "scss", "sass", "stylus", "vue"],
"editor.codeActionsOnSave": {
"source.fixAll": true,
"source.fixAll.stylelint": true,
},
}
上面的配置添加后,每次保存的时候会自动进行格式化,(比如删除空行,重新排序需要再次 ctrl+s)
package.json 中添加 stylelint 相应的自动修复
"scripts": {
"lint:style":"stylelint src\"/**/*.+(css|scss|less|stylus|sass|postcss)\" --fix",
}
主要是方便我们写前端工程化的时候,我们可以同时启动多个命令用,如:我运行 lint 时,既要用 eslint、prettier 格式化和修复逻辑代码,又要使用 stylelint 格式化 scss 文件代码
工具: concurrently
npm install concurrently -D
同时执行多个命令:
"lint:format": "concurrently \"npm run lint\" \"npm run format\""
当我们需要执行 eslint, prettier,和 stylelint 时 可以只运行一条 npm run lint:format
"lint:prettier": "prettier --write src\"/**/*.+(js|ts|tsx|jsx|json|md|json)\"",
"lint:fix": "eslint --fix --ext .js,.jsx,.ts,.tsx src",
"lint:style":"stylelint src\"/**/*.+(css|scss|less|stylus|sass|postcss)\" --fix",
"lint:format": "concurrently \"npm run lint:prettier\" \"npm run lint:style\" \"npm run lint:fix\""
解决以上问题的一个方案就是,在提交代码的时候,自动修复格式问题,并且只修复自己改动的代码,可以通过配置 git hooks 的 pre-commit 钩子来实现这个目的。主要是利用了 husky 和 lint-staged 这 2 个包。
我们需要引入强制的手段来保证提交到 git 仓库的代码是符合我们的要求的。husky 是一个用来管理 git hook 的工具,git hook 即在我们使用 git 提交代码的过程中会触发的钩子。简单来说,我们需要用 husky 安装 pre-commit 钩子,这样就可以在 git commit 之前运行脚本来检测提交的代码是否规范并且格式化不规范的代码。
安装 husky
npm install husky -D
安装钩子,该命令会创建 .husky/ 目录并指定该目录为 git hooks 所在的目录
npx husky install
为了让拉取项目的其他同事一定会这样执行一次。这时候我们需要用 npm scripts的钩子:prepare,prepare 脚本会在 npm install 之后自动执行
"scripts": {
"prepare": "husky install",
}
接下来我们就为 git 添加一个 pre-commit 钩子
npx husky add .husky/pre-commit "npm run lint:style && npm run lint:prettier && npm run lint"
这样上面的代码在提交前会将我们整个项目的全部代码进行格式化和检查,通过分析我们发现,commit 前应该只需 lint 暂存区的代码即可。需要用到 lint-staged,lint-staged 中 staged 指的是 git 的提交区。
当我们运行上面命令的时候可能会报错:
Usage husky install [dir] (default: .husky) husky uninstall husky set|add
[cmd] 原因:应该是语法太多,导致他好像有点不能识别这么多的语法,一步步拆开就行了
解决:
1.先在 .husky 目录下创建一个 pre-commit 文件
npx husky add .husky/pre-commit
2.然后打开 pre-commit 文件,将我们要运行的命令(npm run lint…)替换里面的 undefined 即可
#!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" npm run lint:style & npm run lint:prettier & npm run lint:fix
### 配置 lint-staged
如果发现不符合代码规范的文件则直接退出 commit,且会自动将 prettier 格式化后的代码添加到此次 commit 中
安装 lint-staged
npm install lint-staged -D
在packge.json 中增加配置
```json
"lint-staged": {
"*.{css,less,scss,stylus,sass,postcss}": [
"stylelint --fix", "stylelint --fix", "prettier --write"
],
"*.{html,ts,js,json,jsx,tsx}": [
"prettier --write",
"eslint"
]
}
上面的第二个正则配置是指对 .html、.js、.jsx、.ts、.tsx 文件进行 prettier 格式化,然后执行 eslint
在 .husky/pre-commit 中添加 lint-staged 的调用,修改 ./husky/precommit 内容,将之前运行 husky add 生成的命令注释或者删除即可,我们现在只运行 lint-stage 相关的命令
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
# npm run lint:style & npm run lint:prettier & npm run lint:fix
npx lint-staged
现在在 pre-commit 阶段就只会去对 stage 的文件运行 packge.json lint-stage 中的格式化命令
添加一个 bash 命令来将安装的钩子和 husky 文件复制到标准钩子文件夹,我们就可以解决 GitKraken 的问题
cp -a .husky/. .git/hooks/
我们可以将 prepare 进行修改:
"scripts": {
"prepare": "husky install && cp -a .husky/. .git/hooks/",
}
由于运行 npm install 是所有开发人员在克隆存储库时都会开始的操作,因此我们可以确保我们的基础配置,并允许开发人员想要使用的任何 git 客户端 详细参考