前言
为什么要进行代码质量检查呢,原因有三:
- 一些常见代码问题,如果在编译或运行时不能及时发现,代码中的语法问题会直接导致编译或运行时错误,影响开发效率和代码质量;
- 统一代码习惯,每一个团队或个人都会有一些代码规范或者代码习惯,为了便于后期维护和阅读,我们编写的代码也需要符合一定的格式规范:
- 空格;
- 统一缩进;
- 命名规范;
- 保证线上代码质量。在版本管理中,我们需要在提交或发布之前自动执行一些代码检查工作,确保我们的代码符合最终版本要求。
前端代码中的常见问题
书写风格
简单来说,太过随意的代码会让开发者难以阅读,而难以阅读的代码有时甚至不如推倒重来。
// bad
var once
, upop
, aTime;
// good
var once,
upon,
aTime;
// bad
var hero = {
firstName: 'Bob'
, lastName: 'parr'
, heroName: 'Mr.Incredible'
, superPower: 'strength'
};
// good
var hero = {
firstName: 'Bob',
lastName: 'parr',
heroName: 'Mr.Incredible',
superPower: 'strength'
};
代码规范
不遵守编码标准和惯例的代码会让你看一眼就不想继续看、甚至看半天而不知所云。有人认为初级程序员才会有这种问题,其实不然,一些工作经验两三年的同学写的代码依然如此。对于一些个人自学意识不够积极、没有团队规范性指引的程序员,很容易出现代码格式不规范的问题。
Lint 会通过源代码去查找:
- 格式问题;
- 不遵守编码标准和惯例;
- 精确定位程序中的可能存在的逻辑错误。
代码 Lint 是动态的监测代码边写的错误,以便我们能写出高质量的代码。
要与 Prettier 或者 Format 要区别开来,Lint 只会告诉你代码中的错误或者不规范的地方,而 Format 是用来对格式进行调整的。
ESlint 介绍
ESlint 是 JavaScript 的 linting 实用程序。
ESlint 不依赖与特定的编码约定,用户也可以自由地启用或禁用各个编码约定。从这个意义上讲,它的一个主要特点是其高度可定制性。
用户可以通过定义原始规则来灵活的设置编码标准,这些规则是 Elint 中默认可用的编码规则。
核心概念
-
配置文件:
.eslintrc,.eslintrc.js,.eslintrc.yml -
Rules:
- "off"或0:关闭规则;
- "wran"或1:开启规则,使用警告级别的错误:warn(不会导致程序退出);
- "error"或2:开启规则,使用错误级别的错误:error(当贝触发的时候,程序会退出)。 看一个例子:
{ "rules":{ "semi":["error","never"], "quotes":["error","single"] } }
看一个例子:
{ "rules":{ "semi":["2","never"], "quotes":["2","single"] } }
-
Extends:
使用别人提供的包,如 Google:{ "extends":"google" }
-
Plugins:
ESlint 提供的默认规则涵盖了基本规则,但 JavaScript 可以 使用的范围非常广泛。因此,您可能希望规则不在默认规则中。这种情况下,可以在 ESlint 中开发自己的独立规则。为了让第三方开发自己的规则,ESlint 允许使用插件,如果你在 npm 中搜索 eslint-plugin-*,你可以找到第三方提供的大量自定义插件。如果 ESlint 的默认规则未提供要使用的规则,则建议您查找插件。与可共享配置类似,它很容易设置。例如,如果要对 React 代码进行静态分析,可以安装名为 eslint-plugin-react 的插件,并使用以下设置来执行 React 语法特有的静态分析。
{ "extends":"google", "plugins": ["react"], "rules":{ "semi":[2,"never"], "quotes":[2,"single"] } }
起步与安装
在项目中使用
// --dev 会把 eslint 安装到package.json 文件中的 devDependencies 属性中,意思是知识开发阶段用到这个包,上线时就不需要这个包了
yarn add eslint --dev
新增 package.json 脚本:
"scripts": {
"lint": "eslint app.js",
"lint:create": "eslint --init"
},
然后使用 run 命令:
yarn lint:create
在全局使用
yarn global add eslint
eslint --init
生成的 .eslintrc.js 文件导出一个对象,对象包含属性 env、extends、parserOptions、plugins、rules 五个属性:
- env:指定脚本的运行环境。每种环境都有一组特定的预定义全局变量,(如:nodejs,browser,commonjs 等)中。
- parserOptions:用于指定想要支持的 JavaScript 语言选项:
- ecmaVersion:默认设置为3,5(默认),你可以使用6、7、8或9来指定你想要使用的 ECMAScript 版本。你也可以用使用年份命名的版本号指定为2015(同6),2016(同7),或2017(同8)或2018(同9);
- sourceType:设置为 "script"(默认)或"module"(如果你的代码是 ECMAScript)。
- globals:执行代码时脚本需要访问的额外全局变量;
- rules:开启某些规则,也可以设置规则的等级。
.eslintignore
可以在项目根目录创建,告诉 ESlint 忽略某些文件或者目录。相当于 .gitignore 都是纯文本文件。
ESlint 的使用方法
在你根据以上步骤设置 .eslintrc.js 配置文件后,你可以在项目更目录运行 ESlint,检查你的 js 文件:
yarn lint index.js
vscode 使用 eslint 保存自动格式化
-
在项目跟目录添加.eslintrc.js 文件
// https://cn.eslint.org/docs/rules/ // /* * "off"或者0,不启用这个规则 * "warn"或者1,出现问题会有警告 * "error"或者2,出现问题会报错 */ module.exports = { root: true, //此项是用来告诉eslint找当前配置文件不能往父级查找 env: { //环配置 如 "browser": true, node: true, node: true, }, extends: [ 'google', ], rules: { 'array-callback-return': 1, //return 后面是否允许省略 "arrow-parens": ["error", "as-needed"], // 箭头函数的参数可以不使用圆括号 'consistent-return': 0, //要求 return 语句要么总是指定返回的值,要么不指定 'camelcase': 0, //强制驼峰法命名 'eqeqeq': 0, //强制全等( === 和 !==) 'func-names': 0, //函数表达式必须有名字 "global-require": 0, // 取消对require的验证,使得可以使用require来加载图片的相对路径 "import/no-unresolved": 0, // 取消自动解析路径,以此开启alias的别名路径设置 'import/extensions': 0, // 取消对文件扩展名的验证 'indent': 'off', //缩进风格(强制使用一致的缩进) "linebreak-style": 0, // 取消换行符\n或\r\n的验证() 'max-len': 0, //字符串最大长度 "no-unused-vars": 1, //禁止出现未使用过的变量 "no-redeclare": 1, //禁止多次声明同一变量 'no-use-before-define': 1, //禁止在变量定义之前使用它们 "no-unused-expressions": 0, // 允许使用未使用过的表达式,以此来支持a && a()的代码形式 'no-restricted-syntax': 1, //禁用特定的语法 'no-plusplus': 1, //禁止使用++,-- 'no-underscore-dangle': 0, // 允许在标识符中使用下划线 'no-param-reassign': 0, // 禁止对 function 的参数进行重新赋值 'no-nested-ternary': 0, // 禁止嵌套三元表达式 'no-else-return': 0, //禁止 if 语句中 return 语句之后有 else 块 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 'no-shadow': [1, { //外部作用域中的变量不能与它所包含的作用域中的变量或参数同名 "allow": ["resolve", "reject", "done", "cb"] }], 'prefer-rest-params': 1, //要求使用剩余参数而不是 arguments 'prefer-arrow-callback': 0, //要求回调函数使用箭头函数 'prefer-const': 1, //首选const "semi": false, // 使用分号, 默认true "singleQuote": true, // 使用单引号, 默认false(在jsx中配置无效, 默认都是双引号) "tabWidth": 4, // tab缩进大小,默认为4 'template-curly-spacing': 'off', //要求或禁止模板字符串中的嵌入表达式周围空格的使用 }, parserOptions: { parser: 'babel-eslint', }, };
-
在vscode中添加 eslint。
-
配置保存时按eslint规则自动格式化。
可在“首选项”--“设置”中找到settings.json添加如下配置:
```JavaScript "editor.codeActionsOnSave": { "source.fixAll.eslint": true }, "eslint.format.enable": true ```
可以看下eslint的详细说明,有如图的配置说明,就使用新版本的配置:
这样配置完成后保存文件时就会自动格式化了。
Vue 项目中使用 ESLint 和 Prettier
虽然ESLint会对我们的代码格式进行一些检测(比如分号、单双引号等),但是并不能完全统一代码风格,我们还需要一个工具Prettier。它并不关心你的语法是否正确,只关心你的代码格式,比如是否使用单引号,语句结尾是否使用分号等等,不仅可以用来检测 JavaScript 代码格式,还可以检测 vue 文件,react 文件。
深入 VSCode 配置
大部分的同学开启了插件以后,VSCode 仍然没有高亮。因为需要对 VSCode 中的相关参数继续配置。
"eslint.probe": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"html",
"vue",
"markdown"
],
eslint.probe
这个规定 ESlint 插件需要校验的语言类型,添加上对应的语言后 VSCode 才会在代码编辑器中正确的高亮错误的语法,并且会在窗口中输出错误信息。如果开发 vue 的同学需要在这里添加上 ["html", "vue"]
这样才会在 .vue
单文件中开启 ESlint 检测,这两个选项需要 eslint-plugin-vue
eslint-plugin-html
两个包支持,需要安装到项目中。
eslint插件以eslint-plugin-
开头,使用时可以省略;比如我们上面检测 .vue 文件就用到eslint-plugin-vue
插件;需要注意的是,我们在配置eslint-plugin-vue
这个插件时,如果仅配置"plugins": ["vue"]
,vue 文件中 template 内容还是会解析失败。
这是因为不管是默认的 espree 还是 babel-eslint 解析器都无法解析 .vue 中 template 的内容;eslint-plugin-vue
插件依赖vue-eslint-parser
解析器,而vue-eslint-parser
解析器只会解析template
内容,不会检测 script 标签中的 JS 内容,因此我们还需要指定一下解析器:
{
"extends": ["eslint:recommended"],
"plugins": ["vue","html"],
"parser": "vue-eslint-parser",
"parserOptions": {
"parser": "babel-eslint",
"ecmaVersion": 12,
"sourceType": "module",
},
}
上面parserOptions.parser
不少同学肯定看的有点迷糊,这是由于外层的解析器只能有一个,我们已经用了vue-eslint-parser
就不能再写其他的;因此vue-eslint-parser
的做法是在解析器选项中再传入一个解析器选项用来处理script
中的JS内容。
开启 prettier 格式化
开启上面的选项后,VSCode 已经能正确的显示 ESlint 的报错信息,接下来要开启 prttier 的格式化。前面有说到,prettier 是一个校验代码格式化的工具,而 ESlint 的是校验语法的工具。一个项目维护两种配置可能有些麻烦,因此 ESlint 直接以插件的形式提供了支持。
安装
要使用Prettier
当然先得安装它,然后还需要安装 eslint-plugin-prettier
。
为了防止Prettier
和ESLint
格式化功能冲突,还需要安装 eslint-config-prettier
来关闭ESLint
中的代码格式化功能。
yarn add -D eslint
yarn add -D eslint-plugin-prettier
yarn add -D eslint-config-prettier
在 .prettierignore
和 .eslintignore
文件中可以添加那些不需要格式化的文件或文件夹,在美化代码挑bug时忽略这些文件。
配置
下面来看看在ESLint
中添加Prettier
插件的配置文件是什么样子的:
{
plugins: ["prettier"],
rules: {
prettier/prettier: "error"
}
}
在eslint-plugin-prettier
的GitHub
上给出了一种推荐配置:
{
extends: ["plugin:prettier/recommended"]
}
我们可以在项目中新建一个.prettierrc.json
文件:
{
// 尾逗号
"trailingComma": "es5",
// 缩进长度
"tabWidth": 4,
// 代码末尾分号
"semi": false,
// 单引号
"singleQuote": true,
// 单行代码最大长度
"printWidth": 100,
// 对象字面量的括号
"bracketSpacing": true,
// 箭头函数参数加括号
"arrowParens": "always",
}
这里简单贴一些常用的,我们可以在官网选项配置找到更多的配置规则。
这样配置后虽然能修复代码了,但是如果遇到另一个也固执己见的扩展,比如我们引入eslint-config-standard
这个扩展,它也有自己的代码风格;如果通过 Prettier 格式化,standard 不干了;如果通过 standard 自动修复,那么 Prettier 又要报错了。
我们可以利用extends中最后一个覆盖前面扩展的特性,我们将eslint-config-prettier
配置在 extends 最后,就能够关闭一些与Prettier的规则:
{
extends: ["standard","plugin:prettier/recommended"]
}
之后需要在 setting.json
中配置
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
"editor.codeActionsOnSave": {
"source.fixAll": true
("source.fixAll.eslint": true)
}
}