不以规矩,不能成方圆-完全搞懂 ESLint 和 Prettier

代码规范是软件开发领域经久不衰的话题,几乎全部工程师在开发过程当中都会遇到,并或多或少会思考过这一问题。随着前端应用的大型化和复杂化,愈来愈多的前端团队开始重视 JavaScript 代码规范。javascript

1. 为何写这篇文章?

2020 年 3 月,懵懂的蔡小真怀揣着对技术的向往无比乐观地进入部门实习,入职当天就收到了来自导师的两份礼物,一是代码仓库连接,二是代码开发规范。机智如斯的蔡小真按照规范里的教程,安装好了ESLintPrettier等插件,带上安全帽,拉起小推车,就这样风平浪静地度过了半年的搬砖生涯。然而,遇上最近项目交接,在熟悉代码的过程当中,碰见了以下事情,让蔡小真自乱阵脚。前端

这里是一个案例录屏,加载可能有点慢哦~

如图所示,是项目中的某个文件,按照如今比较流行的前端代码规范,这个文件存在两个问题,一是每行代码末尾并未添加分号,二是单行代码长度过长。若是你安装在 IDE 中安装了Pretter插件并勾选了format on save,那么在你保存文件的时候会按照Pretter提供的规则对代码进行格式化。格式化后的文件如图所示,每行代码末尾都加上了分号,且每行的长度都不超过 140 个字符。vue

事情本该往美好的方向发展,但是若是你同时安装了ESLint插件来检查代码质量问题,就会发现大面积地提示Strings must use singlequote,即“字符串必须使用单引号”,有强迫症的你确定会按下右键修复全部的ESLint问题,即把字符串的双引号所有修改成单引号。java

当你觉得大功告成,兴奋地按下ctrl + s保存这一成果时,你发现字符串的单引号又变成双引号了???why???一脸懵逼???react

若是你是个成熟的码农,你必定知道这是PrettierESLint规则冲突了,但你知道如何高效地修复这种“死循环”问题吗?你知道项目根目录配置和插件配置的优先级问题吗?你了解为了执行统一的前端代码规范安装了无数个ESLintPrettier相关的包,每一个包的使用意义和具体的配置方法吗?jquery

这即是本文所要阐述的内容。git

那么这篇文章适合哪些人阅读呢?程序员

  1. 初学者: 这篇文章详细介绍了业内最火的前端代码规范配置教程 ESLint + Prettier + husky + lint-staged,让你轻松部署一套趁手的搬砖工具。
  2. 老司机:这篇文章以抛砖引玉、承上启下的方式介绍ESLintPrettierhuskylint-staged等每一个功能包及其配套插件的配置方法和使用意义,有益于读者系统性地学习整套前端代码规范,很是适合老司机查缺补漏。
  3. 感兴趣的路人: 若是你愿意花十分钟阅读个人文章,而且为我点个赞,那么你必定是个可爱又博学的人。

2. ESLint

2.1 ESLint 是什么?

首先,咱们来看看ESLint官网的简介:es6

代码检查是一种静态的分析,经常使用于寻找有问题的模式或者代码,而且不依赖于具体的编码风格。对大多数编程语言来讲都会有代码检查,通常来讲编译程序会内置检查工具。github

JavaScript 是一个动态的弱类型语言,在开发中比较容易出错。由于没有编译程序,为了寻找 JavaScript 代码错误一般须要在执行过程当中不断调试。像 ESLint 这样的可让程序员在编码的过程当中发现问题而不是在执行的过程当中

ESLint 是一款插件化的 JavaScript 代码静态检查工具,其核心是经过对代码解析获得的 AST(Abstract Syntax Tree,抽象语法树)进行模式匹配,来分析代码达到检查代码质量和风格问题的能力。

ESLint 的使用并不复杂。依照 ESLint 的文档安装相关依赖,能够根据我的/团队的代码风格进行配置,便可经过命令行工具或借助编辑器集成的 ESLint 功能对工程代码进行静态检查,发现和修复不符合规范的代码。若是想下降配置成本,也能够直接使用开源配置方案,例如 eslint-config-airbnbeslint-config-standard

2.2 ESLint 使用方式

2.2.1 ESLint 配置方式

ESlint 被设计为彻底可配置的,这意味着你能够关闭每个规则而只运行基本语法验证,或混合和匹配 ESLint 默认绑定的规则和你的自定义规则,以让 ESLint 更适合你的项目。有两种主要的方式来配置 ESLint:

2.2.1.1 Configuration Comments - 使用注释把 lint 规则嵌入到源码中

使用 JavaScript 注释把配置信息直接嵌入到一个代码源文件中。

新建一个test.ts文件,直接在源代码中使用 ESLint 可以识别的注释方式,进行 lint 规则的定义。以下内容定义使用console语法便会报错:

/* eslint no-console: "error" */
console.log('this is an eslint rule check!');
复制代码

命令行运行 ESLint 校验,出现报错:

2.2.1.2 Configuration Files - 使用配置文件进行 lint 规则配置

在初始化 ESLint 时,能够选择使用某种文件类型进行lint配置,有以下三种选项:

  1. JavaScript(eslint.js
  2. YAML(eslintrc.yaml
  3. JSON(eslintrc.json

另外,你也能够本身在 package.json 文件中添加 eslintConfig 字段进行配置

2.2.2 初始化

若是想在现有项目中引入 ESLint,能够直接运行下面的命令:

# 全局安装 ESLint
$ npm install -g eslint

# 进入项目
$ cd ESLint-test

# 强制初始化 package.json
$ npm init -force

# 初始化 ESLint 配置
$ eslint --init
复制代码

在使用 eslint --init 后,会出现不少用户配置项,具体能够参考:eslint-cli 部分的源码

通过一系列一问一答的环节后,你会发如今你文件夹的根目录生成了一个 .eslintrc.js 文件。

.eslintrc.js 文件配置以下(这是根据上图所示的选择生成的配置,选择不一样,配置不一样):

module.exports = {
	env: {
		// 环境
		browser: true,
		es2021: true,
	},
	extends: [
		// 拓展
		'eslint:recommended',
		'plugin:@typescript-eslint/recommended',
	],
	parser: '@typescript-eslint/parser', // 解析器,本解析器支持Ts
	parserOptions: {
		// 解析器配置选项
		ecmaVersion: 12, // 指定es版本
		sourceType: 'module', // 代码支持es6,使用module
	},
	plugins: [
		// 插件
		'@typescript-eslint',
	],
	rules: {
		// 规则
	},
};
复制代码

下面将详细解释每一个配置项的含义。

2.3 ESLint 配置项解析

2.3.1 parser - 解析器

ESLint 默认使用Espree做为其解析器,可是该解析器仅支持最新的ECMAScript(es5)标准,对于实验性的语法和非标准(例如 FlowTypeScript类型)语法是不支持的。所以,开源社区提供了如下两种解析器来丰富TSLint的功能:

  • bable-eslintBabel是一个工具链,主要用于将 ECMAScript 2015+(es6+) 版本的代码转换为向后兼容的 JavaScript 语法,以便可以运行在当前和旧版本的浏览器或其余环境中。所以,若是在项目中使用es6,就须要将解析器改为bable-eslint

  • @typescript-eslint/parser:该解析器将 TypeScript 转换成与 estree 兼容的形式, 容许ESLint验证TypeScript源代码。如上图 ESlint 初始化时,Does your project use TypeScript?选择了Yes,因此提示咱们安装@typescript-eslint/parser包。

2.3.2 parserOptions - 解析器选项

除了能够自定义解析器外,ESLint 容许你指定你想要支持的 JavaScript 语言选项。默认状况下,ESLint 支持 ECMAScript 5 语法。你能够覆盖该设置,以启用对 ECMAScript 其它版本和 JSX 的支持

解析器选项能够在 .eslintrc.* 文件使用 parserOptions 属性设置。可用的选项有:

  • ecmaVersion -你可使用 六、七、八、9 或 10 来指定你想要使用的 ECMAScript 版本。你也能够用使用年份命名的版本号指定为 2015(同 6),2016(同 7),或 2017(同 8)或 2018(同 9)或 2019 (same as 10)。
  • sourceType - 设置为 script (默认) 或 module(若是你的代码是 ECMAScript 模块)。
  • ecmaFeatures - 这是个对象,表示你想使用的额外的语言特性:
    • globalReturn - 容许在全局做用域下使用 return 语句
    • impliedStrict - 启用全局 strict mode (若是 ecmaVersion 是 5 或更高)
    • jsx - 启用 JSX

设置解析器选项能帮助 ESLint 肯定什么是解析错误,全部语言特性选项默认都是 false

2.3.3 env 和 golbals - 环境和全局变量

ESLint 会检测未声明的变量,并发出警告,可是有些变量是咱们引入的库声明的,这里就须要提早在配置中声明。每一个变量有三个选项,writablereadonlyoff,分别表示可重写,不可重写和禁用。

{
  "globals": {
    // 声明 jQuery 对象为全局变量
    "$": false, // true表示该变量为 writeable,而 false 表示 readonly
    "jQuery": false
  }
}
复制代码

globals 中一个个的进行声明未免有点繁琐,这个时候就须要使用到 env ,这是对一个环境定义的一组全局变量的预设。

{
  "env": {
    "browser": true,
    "es2021": true,
    "jquery": true // 环境中开启jquery,表示声明了jquery相关的全局变量,无需在globals二次声明
  }
}
复制代码

可选的环境不少,预设值都在这个文件中进行定义,查看源码能够发现,其预设变量都引用自 globals 包。

同时,能够在golbals中使用字符串 off 禁用全局变量来覆盖env中的声明。

例如,在大多数 ES2015 全局变量可用但 Promise 不可用的环境中,你可使用如下配置:

{
    "env": {
        "es6": true
    },
    "globals": {
        "Promise": "off"
    }
}
复制代码

固然,若是是微信小程序开发,env并无定义微信小程序变量,须要在globals中手动声明全局变量,不然在文件中引入变量,会提示报错。声明以下所示:

{
  globals: {
    wx: true,
    App: true,
    Page: true,
    Component: true,
    getApp: true,
    getCurrentPages: true,
    Behavior: true,
    global: true,
    __wxConfig: true,
  },
}
复制代码

2.3.4 rules - 规则

ESLint 附带有大量的规则,你能够在配置文件的 rules 属性中配置你想要的规则。要改变一个规则设置,你必须将规则 ID 设置为下列值之一:

  • off 或 0:关闭规则
  • warn 或 1:开启规则,warn 级别的错误 (不会致使程序退出)
  • error 或 2:开启规则,error级别的错误(当被触发的时候,程序会退出)

有的规则没有属性,只需控制是开启仍是关闭,像这样:"eqeqeq": "off",有的规则有本身的属性,使用起来像这样:"quotes": ["error", "double"]。具体内容能够查看规则文档

能够经过rules配置任何想要的规则,它会覆盖你在拓展或插件中引入的配置项。

2.3.5 plugins - 插件

虽然官方提供了上百种的规则可供选择,可是这还不够,由于官方的规则只能检查标准的 JavaScript 语法,若是你写的是 JSX 或者 TypeScript,ESLint 的规则就开始一筹莫展了。

这个时候就须要安装 ESLint 的插件,来定制一些特定的规则进行检查。ESLint 的插件与扩展同样有固定的命名格式,以 eslint-plugin- 开头,使用的时候也能够省略这个头。

举个例子,咱们要在项目中使用TypeScript,前面提到过,须要将解析器改成@typescript-eslint/parser,同时须要安装@typescript-eslint/eslint-plugin插件来拓展规则,添加的 plugins 中的规则默认是不开启的,咱们须要在 rules 中选择咱们要使用的规则。也就是说 plugins 是要和 rules 结合使用的。以下所示:

// npm i --save-dev @typescript-eslint/eslint-plugin // 注册插件
{
  "parser": "@typescript-eslint/parser",
  "plugins": ["@typescript-eslint"],   // 引入插件
  "rules": {
    "@typescript-eslint/rule-name": "error"    // 使用插件规则
    '@typescript-eslint/adjacent-overload-signatures': 'error',
    '@typescript-eslint/ban-ts-comment': 'error',
    '@typescript-eslint/ban-types': 'error',
    '@typescript-eslint/explicit-module-boundary-types': 'warn',
    '@typescript-eslint/no-array-constructor': 'error',
    'no-empty-function': 'off',
    '@typescript-eslint/no-empty-function': 'error',
    '@typescript-eslint/no-empty-interface': 'error',
    '@typescript-eslint/no-explicit-any': 'warn',
    '@typescript-eslint/no-extra-non-null-assertion': 'error',
    ...
  }
}
复制代码

rules中写一大堆的配置来启用@typescript-eslint/eslint-plugin插件规则,显然是十分愚蠢的作法,这时候extends派上了用场。

2.3.6 extends - 拓展

extends 能够理解为一份配置好的 pluginrules。好比在 @typescript-eslint/eslint-plugin 中咱们能够看到根目录的 index.jsmodule.exports 输出为:

import rules from './rules';
import all from './configs/all';
import base from './configs/base';

export = {
  rules,
  configs: {
    all,
    base,
    recommended: {
      extends: ['./configs/base', './configs/eslint-recommended'], // 内容看下面例子
      rules: {...}
    },
    'eslint-recommended': {
      extends: ['./configs/base', './configs/eslint-recommended'],
      rules: {...}
    },
    'recommended-requiring-type-checking': {
     extends: ['./configs/base', './configs/eslint-recommended'],
      rules: {...}
    },
  },
};

// 举例: ./configs/base 文件内容以下:
export = {
  parser: '@typescript-eslint/parser',
  parserOptions: { sourceType: 'module' },
  plugins: ['@typescript-eslint'], // 重点看这里
};
复制代码

经过扩展的方式加载插件的规则以下:

extPlugin = `plugin:${pluginName}/${configName}`;
复制代码

好比:

{
  "extends": ["plugin:@typescript-eslint/recommended"]
}

// 或者:
{
  "extends": ["plugin:@typescript-eslint/eslint-recommended"]
}
复制代码

对照上面的案例,插件名pluginName@typescript-eslint ,也就是以前安装 @typescript-eslint/eslint-plugin 包,配置名configNamerecommended 或者 eslint-recommended,表示前面封装的recommended或者 eslint-recommendedpluginrules经过这种方式,就无需添加大量的规则来启用插件

extends 属性值能够是:

  • 指定配置的字符串: 好比官方提供的两个拓展eslint:recommendedeslint:all,能够启用当前安装的 ESLint 中全部的核心规则,免得咱们在rules中一一配置。
  • 字符串数组每一个配置继承它前面的配置。以下所示,拓展是一个数组,ESLint 递归地扩展配置, 而后使用rules属性来拓展或者覆盖extends配置规则。
{
    "extends": [
        "eslint:recommended", // 官方拓展
        "plugin:@typescript-eslint/recommended", // 插件拓展
        "standard", // npm包,开源社区流行的配置方案,好比:eslint-config-airbnb、eslint-config-standard
    ],
    "rules": {
    	"indent": ["error", 4], // 拓展或覆盖extends配置的规则
        "no-console": "off",
    }
};
复制代码

自此,不知看官是否明白extendspluginsrules三剑客的关系,若是不明白,建议多读两遍,由于它真的挺重要滴。

2.4 在注释中使用 ESLint

前面提到过,除了添加 ESLint 配置文件进行lint规则配置外,也可使用注释把lint规则嵌入到源码中。

/* eslint eqeqeq: "off", curly: "error" */
复制代码

在这个例子里,eqeqeq 规则被关闭,curly 规则被打开,定义为错误级别。

固然,人无完人,lint规则也同样,只是一种木得感情的辅助工具。在咱们平常开发中,总会生产出一些与lint规则八字相冲的代码,频繁地 error告警总会让人心烦意乱,这时,禁用lint规则就显得十分讨巧。

  • 块注释: 使用以下方式,能够在整个文件或者代码块禁用全部规则或者禁用特定规则:
/* eslint-disable */
alert('该注释放在文件顶部,整个文件都不会出现 lint 警告');

/* eslint-disable */
alert('块注释 - 禁用全部规则');
/* eslint-enable */

/* eslint-disable no-console, no-alert */
alert('块注释 - 禁用 no-console, no-alert 特定规则');
/* eslint-enable no-console, no-alert */
复制代码
  • 行注释: 使用以下方式能够在某一特定的行上禁用全部规则或者禁用特定规则:
alert('禁用该行全部规则'); // eslint-disable-line

// eslint-disable-next-line
alert('禁用该行全部规则');

/* eslint-disable-next-line no-alert */
alert('禁用该行 no-alert 特定规则');

alert(
	'禁用该行 no-alert, quotes, semi 特定规则'
); /* eslint-disable-line no-alert, quotes, semi*/
复制代码

2.5 你必须了解的配置优先级

对于以下结构:

your-project
├── .eslintrc  - 父目录配置A
├── lib - 使用A
│ └── source.js
└─┬ tests
  ├── .eslintrc - 子目录配置B
  └── test.js - 使用B和A, 优先级 B>A
复制代码

有两个.selintrc文件,规则是使用离要检测的文件最近的 .eslintrc文件做为最高优先级。所以,lib/目录使用父目录的.selintrc做为配置文件,而tests/目录使用两个.selintrc做为配置文件,且子目录 A 的优先级大于父目录 B 的优先级,若是两个文件有冲突,子目录 A 配置覆盖父目录 A 配置。若是只想使用子目 A 录配置,能够在子目录 A 配置.selintrc中设置"root": true,这样就不会向上查找。

若是在你的主目录下有一个自定义的配置文件 (~/.eslintrc,好比在 IDE 中使用 ESLint 插件,就会生成这样一个配置文件) ,若是没有其它配置文件时它才会被使用。由于我的配置将适用于用户目录下的全部目录和文件,包括第三方的代码,当 ESLint 运行时可能会致使问题。

综上所述,对于完整的配置层次结构,从最高优先级最低的优先级,以下:

  1. 行内配置: 好比/*eslint-disable*//*eslint-enable*//*global*//*eslint*/
  2. 命令行选项(或 CLIEngine 等价物):好比 --global--rule--env
  3. 项目级配置:
    1. 与要检测的文件在同一目录下的 .eslintrc.*package.json 文件
    2. 继续在父级目录寻找 .eslintrcpackage.json文件,直到根目录(包括根目录)或直到发现一个有"root": true的配置。
  4. 若是不是(1)到(3)中的任何一种状况,退回到 ~/.eslintrc 中自定义的默认配置(即 IDE 环境安装的 ESLint 插件的配置)。

这也是为何工友们使用的搬砖工具(IDE、插件配置)不尽相同,可是提交代码时,冲突却不多的缘由。由于对于成熟的项目,确定会在根目录下添加ESLint配置文件,这个文件的优先级高于 ide 插件优先级。

3. Prettier

3.1 Prettier 是什么?

Prettier 是一个有见识的代码格式化工具。它经过解析代码并使用本身的规则从新打印它,并考虑最大行长来强制执行一致的样式,并在必要时包装代码。现在,它已成为解决全部代码格式问题的优选方案;支持 JavaScriptFlowTypeScriptCSSSCSSLessJSXVueGraphQLJSONMarkdown 等语言,您能够结合 ESLintPrettier,检测代码中潜在问题的同时,还能统一团队代码风格,从而促使写出高质量代码,来提高工做效率。

3.2 ESLint 和 Prettier 的区别?

在格式化代码方面, Prettier 确实和 ESLint 有重叠,但二者侧重点不一样:ESLint 主要工做就是检查代码质量并给出提示,它所能提供的格式化功能颇有限;而 Prettier 在格式化代码方面具备更大优点。所幸,Prettier 被设计为易于与 ESLint 集成,因此你能够轻松在项目中使二者,而无需担忧冲突。

3.3 Prettier 使用方式

3.3.1 安装使用

最基础的使用方式就是使用 yarn 或者 npm 安装,而后在命令行使用。

$ npm install --save-dev --save-exact prettier

$ yarn add --dev --exact prettier
复制代码

而后在文件夹中建立配置文件和 ignore 文件。关于配置文件支持多种形式:

  • 根目录建立.prettierrc 文件,可以写入YMLJSON的配置格式,而且支持.yaml.yml.json.js后缀;
  • 根目录建立.prettier.config.js 文件,并对外export一个对象;
  • package.json中新建Prettier属性。

上面的工做所有完成就可使用命令格式化咱们的代码了。

npx prettier --write . #格式化全部文件
复制代码

3.3.2 与 ESLint 配合使用

ESLintPrettier 相互合做的时候有一些问题,对于他们交集的部分规则,ESLintPrettier 格式化后的代码格式不一致。致使的问题是:当你用 Prettier 格式化代码后再用 ESLint 去检测,会出现一些由于格式化致使的 warning,当你用eslint --fix修复问题,又没法经过Prettier校验,致使陷入一开始提到的“死循环问题”。

这种问题的主要解决思路是ESLint 的规则配置文件上作文章,安装特定的 plugin,把其配置到规则的尾部,实现 Prettier 规则对 ESLint 规则的覆盖

实现方案以下:

// 安装eslint-config-prettier
$ npm install --save-dev eslint-config-prettier

// 在 .eslintrc.* 文件里面的 extends 字段添加:
{
  "extends": [
    ...,
    "已经配置的规则",
+   "prettier",
+   "prettier/@typescript-eslint"
  ]
}
复制代码

前面提到过,extends的值为数组,会继承和覆盖前面的配置,Prettier配置添加到其它拓展的后面,能够实现 Prettier 规则对 ESLint 规则的覆盖。

完成上述两步能够实现的是运行 ESLint 命令会按照 Prettier 的规则作相关校验,可是仍是须要运行 Prettier 命令来进行格式化。为了不画蛇添足,万能的社区早就提出了整合上面两步的方案:在使用 eslint --fix 时候,实际使用 Prettier 来替代 ESLint 的格式化功能。方案以下:

// 安装eslint-plugin-prettier
$ npm install --save-dev eslint-plugin-prettier

// 在 .eslintrc.* 文件里面的 extends 字段添加:
{
  "extends": [
    ...,
    "已经配置的规则",
+   "plugin:prettier/recommended"
  ],
  "rules": {
    "prettier/prettier": "error",
  }
}
复制代码

这个时候你运行 eslint --fix 实际使用的是 Prettier 去格式化文件。在rules中添加"prettier/prettier": "error",当代码出现Prettier校验出的格式化问题,ESLint会报错。eslint-plugin-prettier 具体详细的配置点这里

3.3.3 如何对 Prettier 进行配置

同 ESLint 相似,咱们可使用prettierrc.js的方式对Prettier进行配置,下面讲解下各个配置的做用。

module.exports = {
	printWidth: 80, //一行的字符数,若是超过会进行换行,默认为80
	tabWidth: 2, //一个tab表明几个空格数,默认为80
	useTabs: false, //是否使用tab进行缩进,默认为false,表示用空格进行缩减
	singleQuote: false, //字符串是否使用单引号,默认为false,使用双引号
	semi: true, //行位是否使用分号,默认为true
	trailingComma: 'none', //是否使用尾逗号,有三个可选值"<none|es5|all>"
	bracketSpacing: true, //对象大括号直接是否有空格,默认为true,效果:{ foo: bar }
	parser: 'babylon', //代码的解析引擎,默认为babylon,与babel相同。
};
复制代码

4. 提高效率

4.1 VS Code 集成

4.1.1 Prettier 插件安装

当咱们提交代码时,使用命令行校验文件格式,再回去逐行改动格式,从新提交代码是十分影响效率的行为。这时候Prettier插件便派上用场了。咱们能够在编辑器中安装Prettier插件,这样在保存文件时就能格式化文件。边写边格式化,快得飞起~

这里以 VS Code 为例,首先安装 Prettier - Code formatter插件,而后按快捷键 command + + (windows 是 ctrl + +)来打开setting.json文件,添加以下代码在 VS Code 中将Prettier设置为默认格式化程序:

{
  // 设置所有语言的默认格式化程序为prettier
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  // 设置特定语言的默认格式化程序为prettier
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  }
}
复制代码

想要在保存时自动格式化,咱们能够用在 VS Code 的配置文件setting.json中添加"editor.formatOnSave": true。以下所示:

// 设置所有语言在保存时自动格式化
"editor.formatOnSave": ture,
// 设置特定语言在保存时自动格式化
"[javascript]": {
    "editor.formatOnSave": true
}
复制代码

支持的语言有以下几种:

javascript;
javascriptreact;
typescript;
typescriptreact;
json;
graphql;
复制代码

您可使用 VS Code 设置来配置 PrettierPrettier 将按如下优先级读取设置:

  1. Prettier 配置文件,好比.prettierrc.prettier.config.js
  2. .editorconfig文件,用于覆盖用户/工做区设置,具体可了解EditorConfig for VS Code
  3. Visual Studio 代码设置(分用户/工做区设置)。

注意:若是存在任何本地配置文件(即.prettierrc),则将不使用 VS Code 设置。

4.1.2 ESLint 插件安装

前面提到过,与 linters 集成的最简单且推荐的方法是让 Prettier 进行格式化,并将 linter 配置为不处理格式化规则。 您能够在 Prettier docs 网站上找到有关如何配置每一个 linter 的说明。 而后,您能够像往常同样使用每一个扩展插件。

这里以ESLint插件举例,安装该插件,能够将 ESLint 规则集成到 VS Code 中,这样在编程过程当中,违背 ESLint 规则会自动提示。固然也能够为ESLint启用“保存时自动修复”,而且仍然具备格式和快速修复功能:

"editor.codeActionsOnSave": {
    // For ESLint
    "source.fixAll.eslint": true,
}
复制代码

4.1.3 editorconfig for vs code 插件安装

百密必有一疏,并不是全部的工程项目都能配置尽善尽美的ESLintPrettier,因为每一个人本地的 VS Code 代码格式化配置不拘一格,在实际的项目开发中,多多少少会由于格式化问题产生争议。所以须要有一个统一的规范覆盖本地配置,editorconfig for vs code承担起了这个做用,只要在项目工程的根目录文件夹下添加.editorconfig文件,那么这个文件声明的代码规范规则能覆盖编辑器默认的代码规范规则,从而实现统一的规范标准。

4.2 Husky + lint-staged 打造合格的代码检查工做流

若是你安装前面提到过的插件,在实际开发中能够格式化代码和提示 Lint 规则报错问题,但总有人视“提示”而不见,疯狂地往代码里“下毒”,偷偷摸摸地提交代码,日积月累的,ESLint也就形同虚设。

试想若是将代码已经push到远程后,再进行扫描发现多了一个分号而后被打回修改后才能发布,这样是否是很崩溃,最好的方式天然是确保本地的代码已经经过检查才能 push 到远程,这样才能从必定程度上确保应用的线上质量,同时也可以避免 lint 的反馈流程过长的问题

那么何时开始进行扫描检查呢?这个时机天然而然是本地进行git commit的时候,若是能在本地执行git commit操做时可以触发对代码检查就是最好的一种方式。这里就须要使用的git hook

这里以最多见的git hook工具——husky举例:

首先,安装依赖:

npm install -D husky
yarn add --dev husky
复制代码

而后修改 package.json,增长配置:

{
  "scripts": {
    "precommit": "eslint src/**/*.js"
  }
}
复制代码

这样,在 git commit 的时候就会看到 pre-commit 执行了。

针对历史项目,在中途安装代码检查工做流,提交代码时,对其余未修改的“历史”文件都进行检查,一下出现成百上千个错误,估计会吓得立马删掉eslint等相关配置,冒出一身冷汗。如上图所示,明明只修改了 A 文件,B、C、D 等文件的错所有都冒出来了。针对这样的痛点问题,就是每次只对当前修改后的文件进行扫描,即进行git add加入到stage区的文件进行扫描便可,完成对增量代码进行检查

如何实现呢?这里就须要使用到lint-staged工具来识别被加入到stage区文件。

首先安装依赖:

npm install -D lint-staged
yarn add --dev lint-staged
复制代码

而后修改 package.json,增长配置:

"husky": {
  "hooks": {
    "pre-commit": "lint-staged"
  }
},
"lint-staged": {
  "src/**/*.{js,vue}": ["prettier --write", "eslint --cache --fix", "git add"]
}
复制代码

在进行git commit的时候会触发到git hook进而执行precommit,而precommit脚本引用了lint-staged配置代表只对git add到 stage 区的文件进行扫描,具体lint-staged作了三件事情:

  1. 执行Prettier脚本,这是对代码进行格式化的;
  2. 执行eslint --fix操做,进行扫描,对eslint问题进行修复;
  3. 上述两项任务完成后将代码从新add进 stage 区,而后执行commit

5 写在最后

经过引入以上这些工具可以在必定程度上保证应用的质量问题,并能达到事半功倍的效果。但归根结底,对代码质量的提高须要自身与心里达成契约,也须要团队之间“志趣相投”。但愿读到这里的你能把 Lint 工做流打磨到极致,把更多时间专一在解决真正的问题上,成为真正高效的工程师。

相关文章
相关标签/搜索