ESLint Prettier 代码规范实践
date
Mar 13, 2020
slug
gyvvvmbh
status
Published
tags
前端
summary
type
Post
介绍
代码规范校验使用 ESLint,但是一开始 ESLint 只有检测告诉你哪里有问题,常常出现的情况就是一堆 warning,改起来很痛苦。后来 ESLint 提供了
$ ESLint filename --fix
的命令可以自动帮你修复一些不符合规范的代码。Prettier 是一个代码格式化工具,可以帮你把代码格式化成可读性更好的格式,最典型的就是一行代码过长的问题。
eslint 和 prettier 区别
eslint(包括其他一些 lint 工具)的主要功能包含代码格式的校验,代码质量的校验。 prettier 只是代码格式的校验(并格式化代码),不会对代码质量进行校验。 代码格式问题通常指的是:单行代码长度、tab 长度、空格、逗号表达式等问题。而代码质量问题指的是:未使用变量、三等号、全局变量声明等问题。
eslint 和 prettier 配合使用
为什么要两者配合使用?因为,第一在 ESLint 推出 –fix 参数前,ESLint 并没有自动化格式代码的功能,要对一些格式问题做批量格式化只能用 Prettier 这样的工具。第二 ESLint 的规则并不能完全包含 Prettier 的规则,两者不是简单的谁替代谁的问题。但是在 ESLint 推出 –fix 命令行参数之后,如果你觉得 ESLint 提供的格式化代码够用了,也可以不使用 Prettier。
ESLint 和 Prettier 相互合作的时候有一些问题,对于他们交集的部分规则,ESLint 和 Prettier 格式化后的代码格式不一致。导致的问题是:当你用 Prettier 格式化代码后再用 ESLint 去检测,会出现一些因为格式化导致的 warning。 这个时候有两个解决方案:
- 运行 Prettier 之后,再使用 eslint –fix 格式化一把,这样把冲突的部分以 ESLint 的格式为标准覆盖掉,剩下的 warning 就都是代码质量问题了。
- 在配置 ESLint 的校验规则时候把和 Prettier 冲突的规则 disable 掉,然后再使用 Prettier 的规则作为校验规则。那么使用 Prettier 格式化后,使用 ESLint 校验就不会出现对前者的 warning。
为什么不能先使用 ESLint 再使用 Prettier? 针对方案 1,如果你后使用 Prettier,那么格式化后提交的代码在下一次或者别人 checkout 代码后是通不过 lint 校验的。 针对方案 2,其实是可以的,但是本人在实践中看社区方案的时候有提到某些情况下 eslint –fix 和 prettier 混用会出现格式问题。所以保险起见还是先用 perttier 格式化,再用 eslint 命令校验,而不用 eslint –fix 命令去格式化。
使用总结
1、前端项目必然要使代码规范,不论是 js 还是 ts 项目。 2、如前面说说 prettier 是擅长代码格式的校验,eslint 擅长代码质量的校验。虽说 eslint 也能格式校验,但是并没有 prettier 那么强势。对于 eslint 和 prettier 使用顺序问题,前面已做解释。 3、eslint 和 prettier 的配置和依赖一定要跟随依赖,比如环境差异导致无谓的 git commit。比如 vscode 及其插件(prittier)很容易做到编码格式风格统一,逐步强化团队协作中代码统一问题,再结合 git hook 做到 eslint 检验通过,这时团队代码风格和质量就能保持一致。
项目实践
package.json 内容概览:
{ "scripts": { "prettier": "prettier --write --single-quote \"src/**/*.tsx\"", "lint": "eslint --fix --ext .tsx ./src", "format": "yarn prettier && yarn lint " } "lint-staged": { "src/**/*.tsx": [ "yarn format", "git add" ] }, "husky": { "hooks": { "pre-commit": "lint-staged" } }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^2.13.0", "@typescript-eslint/parser": "^2.13.0", "babel-eslint": "^10.0.1", "eslint": "^6.8.0", "eslint-config-prettier": "^6.9.0", "eslint-import-resolver-babel-module": "^5.1.0", "eslint-plugin-import": "^2.19.1", "eslint-plugin-prettier": "^3.1.2", "eslint-plugin-react": "^7.17.0", "lint-staged": "^8.1.7", "prettier": "^1.19.1", "react-native-typescript-transformer": "^1.2.12", "typescript": "^3.7.4" },}
首先安装基础依赖:
yarn add -D prettier eslint
,安装到项目中的目的是,在其他电脑上免得再配置环境。.eslintrc.js
module.exports = { env: { browser: true, es6: true, node: true, }, extends: [ 'airbnb-base', ], globals: { Atomics: 'readonly', SharedArrayBuffer: 'readonly', }, parser: '@typescript-eslint/parser', parserOptions: { ecmaVersion: 2018, sourceType: 'module', }, plugins: [ '@typescript-eslint', ], rules: { },};
env 用于指定环境,每个环境都有自己预定义的全局变量,可以同时指定多个环境,不矛盾。如 console 属性只有在 browser 环境下才会存在,如果不设置支持 browser,那么可能会 console is undefined。
env: { browser: true, es6: true, node: true, commonjs: true, mocha: true, },
extends 属性值可以是一个字符串或字符串数组,数组中每个配置项继承它前面的配置,可以对继承的规则进行修改、覆盖和拓展。比如我们的 extends 就继承了 Airbnb 的配置规则。
extends: [ 'airbnb-base', // 'eslint:recommended', // 'plugin:react/recommended', // 'plugin:@typescript-eslint/eslint-recommended', // 'plugin:@typescript-eslint/recommended', // 'prettier/@typescript-eslint', // 'plugin:prettier/recommended', ]
globals 脚本在执行期间访问的额外的全局变量。(好像没啥用)
parser 指定一个不同的解析器。ESLint 默认使用 Espree 作为其解析器, TypeScript 项目使用 TypeScript 团队与 ESLint 联合发布的 typescript-eslint 解析器,它非常好地兼容了 TypeScript 和 eslint 的解析特性。还有 Esprima、Babel-ESLint 等解析器。
yarn add -D @typescript-eslint/parser @typescript-eslint/eslint-plugin
parserOptions 指定解析器要想使用的环境配置参数。
parserOptions: { ecmaVersion: 2019, // 默认是5,在我们这里是用了最新的 2019。 sourceType: 'module', // 默认'script',但一般使用ECMAScript模块形式''module ecmafeatures: { globalReturn: false, //允许在全局作用域下使用return语句 impliedStrict: false, //启用全局strict模式(严格模式) jsx: false, //启用JSX experimentalObjectRestSpread: false //启用对实验性的objectRest/spreadProperties的支持 } }
plugins 添加第三方插件,记得提前安装对应 devDependencies。extend 提供的是 eslint 现有规则的一系列预设,而 plugin 则提供了除预设之外的自定义规则,当你在 eslint 的规则里找不到合适的的时候,就可以借用插件来实现。
plugins: ['prettier', '@typescript-eslint'],
rules 额外的 ESLint 具体规则,完整的规则列表。
prettier.config.js
官方配置说明,入门可看prettier 指北。
如前面的介绍,prettier 只是用来对代码的格式进行校验,并格式化代码,所以规则比 eslint 简单很多,所以才有
eslint --fix --ext .tsx ./src
能取代 preittier 的说法。 在 vscode 中安装插件Prettier - Code formatter
后,开启 vscode 的保存时格式化,可自动帮你完成 preittier 的格式化。我一般配置 prettier.config.js,而不是 vscode-prettier 插件的配置,这样子能做到项目独立性。实战
因为是 React 项目,所以需要添加 React 相关的 eslint 扩展和插件。
yarn add -D eslint prettieryarn add -D @typescript-eslint/parser @typescript-eslint/eslint-pluginyarn add -D eslint-plugin-reactyarn add -D eslint-config-prettier eslint-plugin-prettier
依赖说明:
- @typescript-eslint/parser:将 TypeScript 转换为 ESTree,使 eslint 可以识别。
- @typescript-eslint/eslint-plugin:可以打开或关闭的规则列表。
- eslint-plugin-react:检测和规范 React 代码。
- eslint-config-prettier:解决 ESLint 中的样式规范和 prettier 中样式规范的冲突,以 prettier 的样式规范为准,使 ESLint 中的样式规范自动失效。
- eslint-plugin-prettier:将 prettier 作为 ESLint 规范来使用。
prettier.config.js如下:
module.exports = { printWidth: 120, // 每行代码最大长度 tabWidth: 2, //一个tab代表几个空格数,默认为80 useTabs: false, //是否使用tab进行缩进,默认为false,表示用空格进行缩减 semi: true, // 声明后带分号 singleQuote: true, // 使用单引号 jsxSingleQuote: true, // 使用单引号 jsxBracketSameLine: true, // 启用jsx语法,> 放在末尾 trailingComma: 'all',};
.eslintrc.js如下:
module.exports = { env: { //指定代码的运行环境 browser: true, node: true, }, settings: { //自动发现React的版本,从而进行规范react代码 react: { pragma: 'React', version: 'detect', }, }, parser: '@typescript-eslint/parser', parserOptions: { //指定ESLint可以解析JSX语法 ecmaVersion: 2019, sourceType: 'module', ecmaFeatures: { jsx: true, }, }, extends: [ //使用推荐的React代码检测规范 'plugin:react/recommended', 'plugin:@typescript-eslint/recommended', 'prettier/@typescript-eslint', 'plugin:prettier/recommended', ], plugins: ['@typescript-eslint'], rules: {},};
新增的 extends 的配置中:
- prettier/@typescript-eslint:使得@typescript-eslint 中的样式规范失效,遵循 prettier 中的样式规范
- plugin:prettier/recommended:使用 prettier 中的样式规范,且如果使得 ESLint 会检测 prettier 的格式问题,同样将格式问题以 error 的形式抛出
vscode 插件
为了开发方便,我们常常在 VSCode 中集成一些辅助插件。如 prettier、eslint,使得代码在保存或者代码变动的时候自动进行 prettier、eslint –fix 等。 在 settings.json 文件中修改 eslint 配置:
{ 'eslint.enable': true, //是否开启vscode的eslint 'eslint.autoFixOnSave': true, //是否在保存的时候自动fix eslint 'eslint.options': { //指定vscode的eslint所处理的文件的后缀 extensions: ['.js', '.ts', '.tsx'], }, 'eslint.validate': [ //确定校验准则 'javascript', 'javascriptreact', { language: 'html', autoFix: true, }, { language: 'typescript', autoFix: true, }, { language: 'typescriptreact', autoFix: true, }, ],};
参考: