不以規矩,不能成方圓-完全搞懂 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 工做流打磨到極致,把更多時間專一在解決真正的問題上,成爲真正高效的工程師。

相關文章
相關標籤/搜索