前言
现在前端项目基本都采用 ESLint 和 Prettier 配合约束代码规范和代码自动化格式。
目的
- 团队中的所有开发人员用一套代码规范规则作为日常开发约束;
- 有一套自动化工具,来帮我们检测代码是否规范;如果不规范,则自动按照既定规范进行格式化。
工具
- ESLint:设置代码规范的规则,避免开发者使用方式的错误(负责代码质量检查,以及代码格式化);
- prettier:用于规范风格,格式化代码(只专注于代码格式化,不对代码做质量检查)。
一、ESLint
1、安装使用:
- 安装:
// 安装时 Node 版本需高于 12
npm install eslint --save-dev
- 生成配置文件:
./node_modules/.bin/eslint --init
- 进行简单配置:
// .eslintrc.js
module.exports = {
"env": { // 指定代码的运行环境
"browser": true,
"es6": true
},
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": "latest", // 支持 ES 最新版本的语法校验
"sourceType": "module" // 设置 ECMAScript modules
},
// rules: https://eslint.bootcss.com/docs/rules/
"rules": {
// 禁止出现定义了,但未使用过的变量
"no-unused-vars": "warn",
// 阻止 var 的使用,推荐用 let 和 const
"no-var": "warn",
}
};
- 指定文件或目录运行 ESlint:
./node_modules/.bin/eslint src/index.js
- 配置执行脚本:
通常,为了简化操作,我们会将运行命令配置在 scripts 执行命令中。
// package.json
{
"scripts": {
"lint": "eslint src --ext .js,.jsx,.ts,.tsx",
// 对代码自动修复(并非所有的错误和警告都能被自动修复,
// 只会修复一些格式类问题。例如:声明变量但未使用,这无法修复)
"lint-fix": "eslint src --ext .js,.jsx,.ts,.tsx --fix"
}
}
- VSCode 编辑器配置 ESLint: 在开发过程中,我们希望编辑器能够给出 ESLint 的规范校验提示,而不是执行 eslint 代码检查命令才去做检查,因此我们需要配置插件:
- 在 extensions 中搜索安装 ESLint 插件;
- 进入 Settings,可以配置保存代码自动根据 ESLint 规则进行代码修复:
{
...
// 缩进字符数为 2 个
"editor.tabSize": 2,
// 每次保存时将代码按eslint格式进行保存(可选的)
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
// 配置编辑器支持对 TS 文件类型的 ESlint 校验(TS 环境需要支持)
"eslint.validate": [
"typescript",
"typescriptreact"
],
}
- 定义要被 ESLint 校验忽略的文件/目录:
默认情况下,VSCode 编辑器会校验项目下的所有文件,可以定义 ignore 文件对指定目录(比如这里是 publish 目录)进行忽略。
// .eslintignore
publish
node_modules
注意:关于 .eslintignore 在 VSCode 编辑器下不生效情况:如果 eslintignore 配置文件,不在 VSCode 打开的工程跟目录下,可能造成不生效。
2、Parser 解析器:
ESLint 默认使用 Espree 作为解析器解析 JavaScript。通过配置 parserOptions 来设置 ECMAScript 版本以及 JSX。
// .eslintrc.js
{
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": "latest", // 支持 ES 最新版本的语法校验
"sourceType": "module" // 设置 ECMAScript modules
},
}
3、Environments 环境:
指定程序运行的环境,会根据设定的环境预定义相关全局变量。
{
"env": {
"browser": true, // 浏览器全局变量
"es6": true,
},
}
4、Globals 全局变量:
程序所用到的自定义全局变量在这里定义,避免 ESLint 对它们的使用发出警告(只有在配置 "extends": "eslint:recommended" 时会启用 no-undef 发出警告)。
{
"globals": {
"i18n": "writable", // 可写
"$": "readonly", // 只读
},
}
5、Plugins 插件:
ESLint 支持插件规则的配置,比如配置 React 环境插件:
- 安装:
npm install eslint-plugin-react --save-dev
- 配置:
{
"extends": [
"plugin:react/recommended"
],
"plugins": [
"react"
],
// 使用 eslint-plugin-react 插件时需要指定 React 版本
"settings": {
"react": {
"version": "16" // or "detect"
}
},
}
6、Rules 规则:
ESlint 的自定义配置规则在 rules 下进行配置,每一个规则值必须是以下值之一:
- 关闭:"off" 或者 0
- 警告:"warn" 或者 1
- 错误:"error" 或者 2
项目中推荐使用的规范规则如下:
{
// rules: https://eslint.bootcss.com/docs/rules/
"rules": {
// 统一缩进(2个空格)
"indent": ["error", 2, { "SwitchCase": 1 }],
// "@typescript-eslint/indent": ["error", 2, { "SwitchCase": 1 }],
// 运算符前后需要空格,如:let a = 12;
"space-infix-ops": "error",
// 对象 key 和 value 之间有空格,如:key: value
"key-spacing": "error",
// 强制在大括号中使用一致的空格,空{}除外。如:{ a: 1 } 符合,{ a: 1} 不符合
"object-curly-spacing": ["error", "always"],
// 逗号前后是否需要空格,如:let arr = [1, 2, 3];
"comma-spacing": "error",
// 强制所有控制语句使用一致的括号风格,影响 if,for,while 等的花括号风格;这里允许写在一行,要换行必须有花括号
"curly": ["error", "multi-line"],
// 强制在关键字前后使用一致的空格,如:if / else 关键字空格保持一致
"keyword-spacing": "error",
// 禁止在条件语句中出现赋值操作符,如:if (user.jobTitle = "manager")
"no-cond-assign": ["error", "except-parens"],
// 禁止对象字面量中出现重复的 key
"no-dupe-keys": "error",
// 禁止出现重复的 case 标签
"no-duplicate-case": "error",
// 要求使用 === 和 !==,禁用(== 和 !=)
"eqeqeq": "error",
// 禁止出现多个空格。如:if (key !== key2) {}
"no-multi-spaces": "error",
// 禁止重新声明变量。如:var a = 3;、var a = 10;
"no-redeclare": "error",
// 强制在 JSX 属性中使用一致的双引号。如:<div className="box">Box</div>
"jsx-quotes": ["error", "prefer-double"],
// 要求箭头函数的箭头之前或之后有空格。如:const fn = () => {}
"arrow-spacing": "error",
// ESModule 禁止重复导入。
"no-duplicate-imports": "error",
// JSX 元素上不能定义重复的 Prop
"react/jsx-no-duplicate-props": "error",
// 在一组数组中元素必须定义 key 属性
"react/jsx-key": "error",
// 禁止出现定义了,但未使用过的变量
"no-unused-vars": "warn",
// 禁用不必要分号(重复使用多个)
"no-extra-semi": "warn",
// 阻止 var 的使用,推荐用 let 和 const
"no-var": "warn",
// 防止在 React 组件定义中丢失 props 类型定义
"react/prop-types": "off",
// 禁止不使用 setState 的方式去更新 state,而是直接去赋值 state
"react/no-direct-mutation-state": "off",
// 禁止使用 string 类型的 ref 绑定 DOM 元素实例
"react/no-string-refs": "off",
}
}
7、配置 TS 语法校验:
- 安装:
npm install @typescript-eslint/eslint-plugin @typescript-eslint/parser -D
- 配置:
{
...
"parser": "@typescript-eslint/parser", // 配置ts解析器
"plugins": ["@typescript-eslint"],
}
- 注意:
通常我们会在 rules 中配置 "no-unused-vars": "warn" - 定义了但没有使用的变量进行警告;
但在 TS 环境下,ES enum 枚举类型属性也会收到影响,为此这里需要进行配置,使用 TS 特有的 "no-unused-vars" 规则:
"rules": {
// 禁止出现定义了,但未使用过的变量
"no-unused-vars": "off", // 禁用 ESLint 默认的规则
"@typescript-eslint/no-unused-vars": ["warn"], // 启用 TS 规则
}
8、配置 Webpack 打包语法校验:
在使用 Webpack 启动本地服务,或者是进行打包时,也可以在这个过程进行 ESLint 代码校验。
- 安装:
npm install eslint-webpack-plugin -D
- 配置:
// webpack.config.js
const ESLintPlugin = require('eslint-webpack-plugin'); // ESlint 代码检查
module.exports = {
...
plugins: [
...
// 在打包编译时进行代码验证并将结果输出到控制台
new ESLintPlugin({
context: 'src',
extensions: ['.ts', '.tsx', '.js', '.jsx']
}),
]
}
9、Git 代码提交时进行代码检测:
- 手动执行 npm run lint 命令进行代码校验,没有问题再进行提交;
- 另一种可以配置 hook 在代码提交时进行检测拦截。
下面我们借助 pre-commit 来实现 Git 提交检测拦截。
- 安装:
npm install pre-commit -D
- 配置:
{
"scripts": {
"lint": "eslint src --ext .js,.jsx,.ts,.tsx",
"lint-fix": "eslint src --ext .js,.jsx,.ts,.tsx --fix"
},
"pre-commit": [
"lint"
],
}
在执行 git commit 命令时会调用 lint 命令去检测代码,如果校验存在 error 警告,则会终止 commit 的提交,校验的警告信息允许 commit 提交。
10、忽略代码校验:
上面我们使用 .eslintignore
来忽略指定的目录或文件跳过 ESLint 的工作。
如果想在某一个文件中对部分代码的校验进行忽略,可以通过以下几种方式:
- 关闭整个文件代码的 ESLint 校验: 在文件最上方添加:
/* eslint-disable */
... code
- 关闭文件中某一段落代码的 ESLint 校验:
/* eslint-disable */
code
/* eslint-enable */
...code
- 关闭当前行校验:
code // eslint-disable-line
- 关闭下一行校验:
// eslint-disable-next-line
code
二、Prettier
Prettier 作用是对代码格式的校验和统一格式化,不会对代码质量进行校验。
代码格式问题通常指的是:单行代码展示长度、tab缩进空格长度、空格、单引号/双引号的统一使用。
代码质量问题指的是:未使用变量、三等号、全局变量声明等问题。
在 ESLint 推出 --fix 命令行参数之前,ESLint 并没有自动化格式代码的功能,要对一些格式问题做批量格式化只能用 Prettier 这样的工具。
而在 ESLint 推出 --fix 命令行参数之后会对代码做一定的格式化,如果你觉得 ESLint 提供的格式化代码够用了,也可以不使用 Prettier。
下面我们来看看 ESLint
结合 Prettier
一起使用。
1、安装 Prettier:
npm install --save-dev --save-exact prettier // --save-exact 精确版本安装
yarn add --dev --exact prettier
2、创建配置文件:
- 在项目根目录创建
.prettierrc
文件用作填入配置; - 在项目根目录下创建
.prettierignore
忽略对某些文件或目录进行格式化。
一旦结合编辑器开启后,会对项目内所有文件使用 Prettier 进行格式化。如项目中引入的 *.min.js 不希望被格式化而增大文件体积,可以在 .prettierignore 进行配置,其他类型文件同理。
// .prettierignore
*.md
*.min.js
...
尝试使用 .prettierrc.js、prettier.config.js 作为配置文件,在 VSCode 中结合使用时并未生效,这里使用 .prettierrc json 形式编写配置文件。
3、常用配置:
// 配置参考:https://www.prettier.cn/docs/options.html
{
// 指定一行所承载的字符长度,当超过设定值时,自动进行格式化换行排列
// (场景:函数参数过多过长、元素属性在一行内编写过多过长)
printWidth: 150,
// 代码缩进使用的空格数
tabWidth: 2,
// 元素的右括号显示在最后一行的末尾(比如 HTML 元素的 ">" 不会换行单独展示在一行)
bracketSameLine: true,
// 在代码结尾处打上分号 ;
semi: true,
// 对字符串统一使用单引号
singleQuote: false,
// 在 JSX 中统一使用单引号
jsxSingleQuote: false,
// 在箭头函数只有一个参数时,在参数周围添加括号 (x) => x
arrowParens: "always",
// 在 HTML、Vue、JSX 中执行每行单个属性
singleAttributePerLine: false,
// 对象括号和属性之间使用空格
bracketSpacing: true,
}
4、集成在编辑器:
借助 Code Editor 编辑器保存时自动进行格式化处理。这里以 VSCode 为例:
- 在 vscode 编辑器扩展插件中搜索
prettier-vscode
,选择Prettier - Code formatter
进行安装并启用; - 打开 vscode settings.json 添加配置(更多配置参考 Prettier - Code formatter 插件介绍):
{
"editor.defaultFormatter": "esbenp.prettier-vscode", // 所有文件均使用 Prettier 格式化
"editor.formatOnSave": true // 保存时自动进行格式化处理
}
现在,对文件进行保存时,会自动读取 Prettier 配置进行格式化处理。
5、兼容 ESLint:
prettier 和 ESLint 经常会冲突,比如 rule indent
,特别是在 React JSX 三目运算符中使用 ReactDOM.createPortal()
。
这种情况只能选择放弃其一。放弃的方式可以是:放弃全局配置 和 使用忽略代码格式化。
对于放弃全局配置,
- 如果使用 Prettier,则关掉 ESLint indent rules;
- 如果不使用 Prettier,则推荐开启 ESLint indent rules。
对于使用忽略代码格式化
- 要么采用 ESLint rule,使用 Prettier 忽略代码格式;
- 要么采用 Prettier 格式,使用 ESLint 忽略代码格式(上述示例 rule indent 冲突,可以考虑使用这种方式);
6、忽略代码格式化
官方文档:www.prettier.cn/docs/ignore…
忽略下一行代码的 Prettier 格式化,在代码上方添加:
# JS 文件的忽略使用方式
// prettier-ignore
# JSX 文件的忽略使用方式
{/* prettier-ignore */}
# HTML 文件的忽略使用方式
<!-- prettier-ignore -->
# CSS 文件的忽略使用方式
/* prettier-ignore */
# 更多文件的忽略编写方式参考:https://www.prettier.cn/docs/ignore.html
最后
如果团队成员代码编写格式规范自我约束较高,完全可以不用 Prettier 仅用 Eslint;反之推荐开启 Prettier。