ESLint 開始,說透我如何在團隊項目中基於 Vue 作代碼校驗

最近遇到了一個老項目,比較有意思的是這個項目集先後端的代碼於一塊兒,然後端也會去修改前端代碼,因此就出現了後端用 IntelliJ IDEA 來開發前端項目,而前端用 VSCode 來開發前端項目的狀況。 因而乎,出現了代碼規範的問題,因此就有了這篇文章,整理了一下前端代碼校驗以及在 Vue 項目中的實踐。javascript

閱讀完這篇文章,你能夠收穫:html

  • 可以本身親手寫出一套 ESLint 配置;
  • 會知道業界都有哪些著名的 JS 代碼規範,熟讀它們可讓你寫出更規範的代碼;
  • vue-cli 在初始化一個包含代碼校驗的項目時都作了什麼;
  • Prettier 是什麼?爲何要使用它?如何與 ESLint 配合使用?
  • EditorConfig 又是什麼?如何使用?
  • 如何在 VSCode 中經過插件來協助代碼校驗工做;
  • 如何保證 push 到遠程倉庫的代碼是符合規範的;

下面開始閱讀吧,若是你對 ESLint 比較熟悉,能夠直接跳過這個部分。前端

ESLint 是什麼

ESLint 是一個集代碼審查和修復的工具,它的核心功能是經過配置一個個規則來限制代碼的合法性和風格。vue

配置解析器和解析參數

ESLint 的解析器,早期的時候用的是 Esprima,後面基於 Esprima v1.2.2 版本開發了一個新的解析器 Espree,而且把它當作默認解析器。java

除了使用 ESLint 自帶的解析器外,還能夠指定其餘解析器:node

  • @babel/eslint-parser:使 Babel 和 ESLint 兼容,對一些 Babel 語法提供支持;
  • @typescript-eslint/parser:TSLint 被棄用後,TypeScript 提供了此解析器用於將其與 ESTree 兼容,使 ESLint 對 TypeScript 進行支持;

爲項目指定某個選擇器的原則是什麼?react

  • 若是你的項目用到了比較新的 ES 語法,好比 ES2021 的 Promise.any(),那就能夠指定 @babel/eslint-parser 爲解析器;
  • 若是項目是基於 TS 開發的,那就使用 @typescript-eslint/parser;

若是你對 ES 最新標準還不熟悉,能夠看看這篇文章:送你一份精心總結的3萬字ES6實用指南(下)jquery

除了指定解析器 parser 外,還能夠額外配置解析器參數 parserOption:webpack

{
    // ESLint 默認解析器,也能夠指定成別的
    parser: "espree", 
    parserOption: {
        // 指定要使用的 ECMAScript 版本,默認值 5
        ecmaVersion: 5,
        // 設置爲 script (默認) 或 module(若是你的代碼是 ECMAScript 模塊)
        sourceType: "script",
        // 這是個對象,表示你想使用的額外的語言特性,全部選項默認都是 false
        ecmafeatures: {
            // 是否容許在全局做用域下使用 return 語句
            globalReturn: false,
            // 是否啓用全局 strict 模式(嚴格模式)
            impliedStrict: false,
            // 是否啓用JSX
            jsx: false,
            // 是否啓用對實驗性的objectRest/spreadProperties的支持
            experimentalObjectRestSpread: false
        }
    }
}
複製代碼

指定環境 env

指定不一樣的環境能夠給對應環境下提供預設的全局變量。好比說在 browser 環境下,可使用 window 全局變量;在 node 環境下,可使用 process 全局變量等;git

ESLint 中可配置的環境比較多,這裏有份完整的環境列表,下面列出幾個比較常見的:

  • browser:瀏覽器全局變量;
  • node:Node.js 全局變量和做用域;
  • es6:es6 中除了模塊以外的其餘特性,同時將自動設置 parserOptions.ecmaVersion 參數爲 6;以此類推 ES2017 是 7,而 ES2021 是 12;
  • es2017:parserOptions.ecmaVersion 爲 8;
  • es2020:parserOptions.ecmaVersion 爲 11;
  • es2021:parserOptions.ecmaVersion 爲 12;

配置方式以下:

{
    env: {
        browser: true,
        node: true,
        es6: true,
        commonjs: true,
        mocha: true,
        jquery: true,
    }
}
複製代碼

能夠指定多個環境並不意味着配置的環境越多越好,實際配置的時候仍是得依據當前項目的環境來選擇。

配置全局變量 globals

ESLint 的一些核心規則依賴於對代碼在運行時可用的全局變量的瞭解。 因爲這些在不一樣環境之間可能會有很大差別,而且在運行時會進行修改,所以 ESLint 不會假設你的執行環境中存在哪些全局變量。

若是你想使用這些全局變量,那就能夠經過 globals 來指定。好比在 react .eslintrc.js 裏就把 spyOnDev、 spyOnProd 等變量掛在了 global 下做爲全局變量:

{
    globals: {
        spyOnDev: true,
        spyOnProd: true,
    }
}
複製代碼

對於它的值須要特別說明下:

  • false、readable、readonly 這 3 個是等價的,表示變量只可讀不可寫;
  • true、writeable、writable 這 3 個是等價的,表示變量可讀可寫;

配置擴展 extends

實際項目中配置規則的時候,不可能團隊一條一條的去商議配置,太費精力了。一般的作法是使用業內你們普通使用的、遵循的編碼規範;而後經過 extends 去引入這些規範。extends 配置的時候接受字符串或者數組:

{
    extends: [
        'eslint:recommended',
        'plugin:vue/essential',
        'eslint-config-standard', // 能夠縮寫成 'standard'
        '@vue/prettier',
        './node_modules/coding-standard/.eslintrc-es6'
    ]
}
複製代碼

從上面的配置,能夠知道 extends 支持的配置類型能夠是如下幾種

  • eslint 開頭的:是 ESLint 官方的擴展;
  • plugin 開頭的:是插件類型擴展,好比 plugin:vue/essential;
  • eslint-config 開頭的:來自 npm 包,使用時能夠省略前綴 eslint-config-,好比上面的能夠直接寫成 standard;
  • @開頭的:擴展和 eslint-config 同樣,只是在 npm 包上面加了一層做用域 scope;
  • 一個執行配置文件的相對路徑或絕對路徑;

那有哪些經常使用的、比較著名擴展能夠被 extends 引入呢

使用插件 plugins

ESLint 提供插件是幹嗎用的

ESLint 雖然能夠定義不少的 rules,以及經過 extends 來引入更多的規則,可是說到底只是檢查 JS 語法。若是須要檢查 Vue 中的 template 或者 React 中的 jsx,就一籌莫展了。 因此引入插件的目的就是爲了加強 ESLint 的檢查能力和範圍。

如何配置插件

ESLint 相關的插件的命名形式有 2 種:不帶命名空間的和帶命名空間的,好比:

  • eslint-plugin- 開頭的能夠省略這部分前綴;
  • @/ 開頭的;
{
    plugins: [
        'jquery',          // 是指 eslint-plugin-jquery
        '@jquery/jquery',  // 是指 @jquery/eslint-plugin-jquery
        '@foobar',         // 是指 @foobar/eslint-plugin
    ]
}
複製代碼

當須要基於插件進行 extends 和 rules 的配置的時候,須要加上插件的引用,好比:

{
    plugins: [
        'jquery',   // eslint-plugin-jquery
        '@foo/foo', // @foo/eslint-plugin-foo
        '@bar, // @bar/eslint-plugin ], extends: [ 'plugin:jquery/recommended', 'plugin:@foo/foo/recommended', 'plugin:@bar/recommended' ], rules: { 'jquery/a-rule': 'error', '@foo/foo/some-rule': 'error', '@bar/another-rule': 'error' }, } 複製代碼

以上配置來自 ESLint plugins

配置規則 rules

ESLint 提供了大量內置的規則,這裏是它的規則列表 ESLint Rules,除此以外你還能夠經過插件來添加更多的規則。

規則的校驗說明,有 3 個報錯等級

  • off 或 0:關閉對該規則的校驗;
  • warn 或 1:啓用規則,不知足時拋出警告,且不會退出編譯進程;
  • error 或 2:啓用規則,不知足時拋出錯誤,且會退出編譯進程;

一般規則只須要配置開啓仍是關閉便可;可是也有些規則能夠傳入屬性,好比:

{
    rules: {
        'quotes': ['error', 'single'],  // 若是不是單引號,則報錯
        'one-var': ['error', {
            'var': 'always',  // 每一個函數做用域中,只容許 1 個 var 聲明
            'let': 'never',   // 每一個塊做用域中,容許多個 let 聲明
            'const': 'never', // 每一個塊做用域中,容許多個 const 聲明
        }]
    }
}
複製代碼

如何知道某個擴展有哪些規則能夠配置,以及每一個規則具體限制? 這裏直接給出業內著名且使用比較多的規則列表的快速連接:

規則的優先級

  • 若是 extends 配置的是一個數組,那麼最終會將全部規則項進行合併,出現衝突的時候,後面的會覆蓋前面的;
  • 經過 rules 單獨配置的規則優先級比 extends 高;

其餘配置

配置當前目錄爲 root

ESLint 檢測配置文件步驟:

    1. 在要檢測的文件同一目錄裏尋找 .eslintrc.* 和 package.json;
    1. 緊接着在父級目錄裏尋找,一直到文件系統的根目錄;
    1. 若是在前兩步發現有 root:true 的配置,中止在父級目錄中尋找 .eslintrc;
    1. 若是以上步驟都沒有找到,則回退到用戶主目錄 ~/.eslintrc 中自定義的默認配置;

一般咱們都習慣把 ESLint 配置文件放到項目根目錄,所以能夠爲了不 ESLint 校驗的時候往父級目錄查找配置文件,因此須要在配置文件中加上 root: true。

{
    root: true,
}
複製代碼

添加共享數據

ESLint 支持在配置文件添加共享設置,你能夠添加 settings 對象到配置文件,它將提供給每個將被執行的規則。若是你想添加的自定義規則並且使它們能夠訪問到相同的信息,這將會頗有用,而且很容易配置:

{
    settings: {
        sharedData: 'Hello'
    }, 
}
複製代碼

參考:ESLint配置文件.eslintrc參數說明

針對個別文件設置新的檢查規則

好比 webpack 的中包含了某些運行時的 JS 文件,而這些文件是隻跑在瀏覽器端的,因此須要針對這部分文件進行差別化配置:

overrides: [
    {
        files: ["lib/**/*.runtime.js", "hot/*.js"],
        env: {
            es6: false,
            browser: true
        },
            globals: {
            Promise: false
        },
        parserOptions: {
            ecmaVersion: 5
        }
    }
]
複製代碼

以上配置來自 webpack .eslintrc.js

如何校驗

上面細說了 ESLint 的各類配置項,以及針對 Vue 項目如何進行差別配置的說明。

如今咱們知道了如何配置,可是你知道這些配置都是配置到哪裏的嗎?

配置方式

ESLint 支持 3 種配置方式:

  • 命令行:不推薦,不作介紹;
  • 單文件內註釋:不推薦,不作介紹;
  • 配置文件:配置文件的類型能夠是好幾種,好比:.js、.yml、json 等。推薦使用 .eslintrc.js;

下面經過命令來生成一個配置文件:

# 安裝 eslint
npm i eslint -D

# 初始化一個配置文件
npx eslint --init
複製代碼

最後會在當前目錄生成一個 .eslintrc.js 文件。這裏就不把代碼貼出來了,沒參考意義。

上面咱們知道了能夠將配置統一寫到一個配置文件裏,可是你知道該如何去觸發這個配置文件的校驗規則嘛?

校驗單個文件

// 校驗 a.js 和 b.js
npx eslint a.js b.js

// 校驗 src 和 scripts 目錄
npx eslint src scripts
複製代碼

校驗別的類型的文件

一般 ESLint 只能校驗 JS 文件。好比須要校驗 .vue 文件,光配置 vue 插件和 vue-eslint-parser 解析器是不夠的,還須要讓 ESLint 在查找文件的時候找到 .vue 文件。

能夠經過 --ext 來指定具體須要校驗的文件:

npx eslint --ext .js,.jsx,.vue src
複製代碼

自動修復部分校驗錯誤的代碼

rules 列表項中標識了一個扳手 🔧 圖案的規則就標識該規則是能夠經過 ESLint 工具自動修復代碼的。 如何自動修復呢?經過 --fix 便可。好比對於 ESLint Rules 裏的這個 semi 規則,它就是帶扳手圖案的。

對於以下的 a.js 代碼:

const num = 12
複製代碼

當在配置文件配置了 'semi': [2, 'always'] 後,運行命令:

npx eslint --fix a.js
複製代碼

校驗直接就經過了,且會自動修復代碼,在代碼末尾自動加上分號。

把校驗命令加到 package.json

檢驗命令比較長,也難記,習慣上會把這些命名直接寫到 package.json 裏:

{
    "scripts": {
        "lint": "npx eslint --ext .js,.jsx,.vue src",
        "lint:fix": "npx eslint --fix --ext .js,.jsx,.vue src",
    }
}
複製代碼

過濾一些不須要校驗的文件

對於一些公共的 JS、測試腳本或者是特定目錄下的文件習慣上是不須要校驗的,所以能夠在項目根目錄經過建立一個 .eslintignore 文件來配置,告訴 ESLint 校驗的時候忽略它們:

public/
src/main.js
複製代碼

除了 .eslintignore 中指定的文件或目錄,ESLint 老是忽略 /node_modules/ 和 /bower_components/ 中的文件;所以對於一些目前解決不了的規則報錯,可是若是又急於打包上線,在不影響運行的狀況下,咱們就能夠利用 .eslintignore 文件將其暫時忽略。

在 Vue 項目中的實踐

上面把 ESLint 的幾乎全部的配置參數和校驗方式都詳細的介紹了一遍,可是若是想在項目中落地,僅僅靠上面的知識仍是不夠的。下面將細說如何在 Vue 中落地代碼校驗。

關於如何在 Vue 中落地代碼校驗,通常是有 2 種狀況:

  • 經過 vue-cli 初始化項目的時候已經選擇了對應的校驗配置
  • 對於一個空的 Vue 項目,想接入代碼校驗

其實這 2 種狀況最終的校驗的核心配置都是同樣的,只是剛開始的時候安裝的包有所區別。下面經過分析 vue-cli 配置的代碼校驗,來看看它到底作了哪些事情,經過它安裝的包以及包的做用,咱們就會知道如何在空項目中配置代碼校驗了。

經過 vue-cli 初始化的項目

若是你的項目最初是經過 vue-cli 新建的,那麼在新建的時候會讓你選

  • 是否支持 eslint;
  • 是否開啓保存校驗;
  • 是否開啓提交前校驗;

若是都開啓了話,會安裝以下幾個包:

  • eslint:前面 2 大章節介紹的就是這玩意,ESLint 出品,是代碼校驗的基礎包,且提供了不少內置的 Rules,好比 eslint:recommended 常常被做爲項目的 JS 檢查規範被引入;
  • babel-eslint:一個對 Babel 解析器的包裝,使其可以與 ESLint 兼容;
  • lint-staged:請看後面 pre-commit 部分;
  • @vue/cli-plugin-eslint
  • eslint-plugin-vue

下面重點介紹 @vue/cli-plugin-eslint 和 eslint-plugin-vue,說下這 2 個包是幹嗎的。

@vue/cli-plugin-eslint

這個包它主要乾了 2 件事情:

第一件事

往 package.json 裏註冊了一個命令:

{
    "scripts": {
        "lint": "vue-cli-service lint"
    }
}
複製代碼

執行這個命令以後,它會去檢查和修復部分能夠修復的問題。默認查找的文件是 src 和 tests 目錄下全部的 .js,.jsx,.vue 文件,以及項目根目錄下全部的 js 文件(好比,也會檢查 .eslintrc.js)。

固然你也能夠自定義的傳入參數和校驗文件:

vue-cli-service lint [options] [...files]
複製代碼

支持的參數以下:

  • --no-fix: 不會修復 errors 和 warnings;
  • --max-errors [limit]:指定致使出現 npm ERR 錯誤的最大 errors 數量;

第二件事

增長了代碼保存觸發校驗的功能 lintOnSave,這個功能默認是開啓的。若是想要關閉這個功能,能夠在 vue.config.js 裏配置,習慣上只開啓 development 環境下的代碼保存校驗功能:

module.exports = {
    lintOnSave: process.env.NODE_ENV === 'development',
}
複製代碼

lintOnSave 參數說明:

  • true 或者 warning:開啓保存校驗,會將 errors 級別的錯誤在終端中以 WARNING 的形式顯示。默認的,WARNING 將不會致使編譯失敗;
  • false:不開啓保存校驗;
  • error:開啓保存校驗,會將 errors 級別的錯誤在終端中以 ERROR 的形式出現,會致使編譯失敗,同時瀏覽器頁面變黑,顯示 Failed to compile。

eslint-plugin-vue

eslint-plugin-vue 是對 .vue 文件進行代碼校驗的插件。

針對這個插件,它提供了這幾個擴展

  • plugin:vue/base:基礎
  • plugin:vue/essential:預防錯誤的(用於 Vue 2.x)
  • plugin:vue/recommended:推薦的,最小化任意選擇和認知開銷(用於 Vue 2.x);
  • plugin:vue/strongly-recommended:強烈推薦,提升可讀性(用於 Vue 2.x);
  • plugin:vue/vue3-essential:(用於 Vue 3.x)
  • plugin:vue/vue3-strongly-recommended:(用於 Vue 3.x)
  • plugin:vue/vue3-recommended:(用於 Vue 3.x)

各擴展規則列表:vue rules

看到這麼一堆的擴展,是否是都不知道選哪一個了

代碼規範的東西,原則仍是得由各自的團隊去磨合商議出一套適合你們的規則。不過,若是你用的是 Vue2,我這裏能夠推薦 2 套 extends 配置:

{
    // Vue 官方示例上的配置
   extends: ['eslint:recommended', 'plugin:vue/recommended'],  
   
   // 或者使用 AlloyTeam 團隊那套
   extends: ['alloy', 'alloy/vue']
}
複製代碼

配置和插件對應的解析器

若是是 Vue 2.x 項目,配置了 eslint-plugin-vue 插件和 extends 後,template 校驗仍是會失效,由於無論是 ESLint 默認的解析器 Espree 仍是 babel-eslint 都只能解析 JS,沒法解析 template 的內容。

而 vue-eslint-parser 只能解析 template 的內容,可是不會解析 JS,所以還須要對解析器作以下配置:

{
    parser: 'vue-eslint-parser',
    parseOptions: {
        parser: 'babel-eslint',
        ecmaVersion: 12,
        sourceType: 'module'
    },
    extends: [
        'eslint:recommended', 
        'plugin:vue/recommended'
    ],
    plugins: ['vue']
}
複製代碼

參考:eslint-plugin-vue faq

讓 Prettier 管控代碼風格

針對 Prettier 不得不提出如下疑問?

  • Prettier 是什麼?
  • 爲何有了 ESLint,還須要引入 Prettier 呢?它兩之間有什麼區別?
  • 如何配置 Prettier?
  • Prettier 如何和 ESLint 結合使用?

Prettier 是什麼

用它本身的話來講:我是一個自覺得是的代碼格式化工具,並且我支持的文件類型不少,好比:

  • JavaScript(包括實驗中的特性)
  • JSX
  • Vue
  • TypeScript
  • CSS、Less、SCSS
  • HTML
  • JSON
  • Markdown

以及還有一些其餘類型的文件。

Prettier 對比 ESLint

咱們知道 ESLint 負責了對代碼的校驗功能,而且主要提供了 2 類規則:

  • 檢查格式化的規則
  • 檢查代碼質量的規則

說到底 ESLint 就是經過一條條的規則去限制代碼的規範,可是這些規則畢竟是有限的,並且更重要的是這些規則的重點並不在代碼風格上,因此單憑 ESLint 並不能徹底的統一代碼風格。

這個時候就須要引入 Prettier 了,由於它乾的事就是隻管代碼格式化,無論代碼質量。

Prettier:在代碼風格這一塊,我一直拿捏的死死的。

如何配置 Prettier

初始化操做:

# 安裝包
npm i prettier -D  

# 新建 .prettierrc.js
echo module.exports = {} > .prettierrc.js

# 新建 .prettierignore
echo > .prettierignore
複製代碼

Prettier 支持能夠配置參數很少,總共才 21 個,這裏是全部參數的說明 prettier options

全部參數都有默認值,也就是說即便你沒有配置 .prettierrc.js,當你用 Prettier 去格式化代碼的時候所有都會走默認配置。針對個別參數,你不想用默認設置的話,就能夠在 .prettierrc.js 配置具體想要的值。

以下,把項目中會用到的參數進行一個說明:

module.exports = {
    printWidth: 80,                    //(默認值)單行代碼超出 80 個字符自動換行
    tabWidth: 2,                       //(默認值)一個 tab 鍵縮進至關於 2 個空格
    useTabs: true,                     // 行縮進使用 tab 鍵代替空格
    semi: false,                       //(默認值)語句的末尾加上分號
    singleQuote: true,                 // 使用單引號
    quoteProps: 'as-needed',           //(默認值)僅僅當必須的時候纔會加上雙引號
    jsxSingleQuote: true,              // 在 JSX 中使用單引號
    trailingComma: 'all',              // 不用在多行的逗號分隔的句法結構的最後一行的末尾加上逗號
    bracketSpacing: true,              //(默認值)在括號和對象的文字之間加上一個空格
    jsxBracketSameLine: true,          // 把 > 符號放在多行的 JSX 元素的最後一行
    arrowParens: 'avoid',              // 當箭頭函數中只有一個參數的時候能夠忽略括弧
    vueIndentScriptAndStyle: false,    //(默認值)對於 .vue 文件,不縮進 <script> 和 <style> 裏的內容
    embeddedLanguageFormatting: 'off', // 不容許格式化內嵌的代碼塊,好比 markdown 文件裏的代碼塊
};
複製代碼

擴展閱讀:關於 Trailing commas 你或許想了解更多。

而後能夠經過命令來格式化代碼:

# 將格式化當前目錄及子目錄下全部文件
npx prettier --write .

# 檢查某個文件是否已經格式化
npx prettier --check src/main.js
複製代碼

若是有些文件不想被 Prettier 格式化,能夠將其寫入到 .prettierignore 裏:

build/
package.json
public/
test/*.*
複製代碼

Prettier 和 ESLint 一塊兒幹活更配哦

上面介紹了 Prettier 的具體配置,這裏主要介紹和 ESLint 結合使用的配置和注意事項。

和 ESLint 配合使用須要用到 eslint-plugin-prettier 這個插件:

npm i eslint-plugin-prettier -D
複製代碼

配置:

{
    plugins: ['prettier'],
    rules: {
        'prettier/prettier': 'error'
    }
}
複製代碼

這個插件的工做原理是先調用 Prettier 對你的代碼進行格式化,而後會把格式化先後不一致的地方進行標記,經過配置 'prettier/prettier': 'error' 此條規則會將標記地方進行 error 級別的報錯提示,而後能夠經過 ESLint 的 --fix 自動修復功能將其修復。

衝突了怎麼辦

經過前面的介紹,咱們知道 ESLint 也是會對代碼風格作一些限制的,而 Prettier 主要就是規範代碼風格,因此在把它們結合一塊兒使用的時候是存會在一些問題的。對於個別規則,會使得雙方在校驗後出現代碼格式不一致的問題。

那麼當 Prettier 和 ESLint 出現衝突以後,該怎麼辦呢?

用 Prettier 的話來講很簡單,只要使用 eslint-config-prettier 就能夠了。解決衝突的思路就是經過將這個包提供的擴展放到 extends 最後面引入,依據 rules 生效的優先級,因此它會覆蓋前面起衝突的規則,好比:

{
    extends: [
        'eslint:recommended',
        'prettier',  // 必須放最後
    ],
}
複製代碼

除了能覆蓋和 ESLint 中起衝突的規則以外,eslint-config-prettier 還能覆蓋來自如下插件的規則(只列了部分):

  • eslint-plugin-standard
  • eslint-plugin-vue

那 eslint-config-prettier 到底提供了哪些覆蓋規則呢?直接看這個列表:eslint-config-prettier rules

若是想覆蓋某些插件的規則,須要引入對應插件的擴展,好比:

{
    extends: [
        'standard',
        'plugin:vue/recommended',
        'prettier/standard',      // 覆蓋 eslint-config-stanard 
        'prettier/vue',           // 覆蓋 eslint-plugin-vue 
    ],
}
複製代碼

提示:在 eslint-config-prettier 8.0.0 版本後,extends 再也不須要爲單獨的插件引入對應擴展來覆蓋衝突了,統一引入 'prettier' 便可。

若是同時使用了 eslint-plugin-prettier 和 eslint-config-prettier 能夠這麼配置:

{
    extends: ['plugin:prettier/recommended'],
}
複製代碼

它其實和下面這些配置是等價的:

{
    extends: ['prettier'],  // eslint-config-prettier 提供的,用於覆蓋起衝突的規則
    plugins: ['prettier'],  // 註冊 eslint-plugin-prettier 插件
    rules: {
        'prettier/prettier': 'error',
        'arrow-body-style': 'off',
        'prefer-arrow-callback': 'off'
    }
}
複製代碼

因此若是是在 Vue 2 項目中配置 ESLint 和 Prettier 會這麼配置:

{
    parser: 'vue-eslint-parser',
    parseOptions: {
        parser: 'babel-eslint',
        ecmaVersion: 12,
        sourceType: 'module'
    },
    extends: [
        'eslint:recommended', 
        'plugin:vue/recommended',
        'plugin:prettier/recommended',  // 在前面 Vue 配置的基礎上加上這行
    ],
    plugins: ['vue']
}
複製代碼

其實若是你的項目是用 vue-cli 初始化的,且選擇了 eslint + prettier 方案的話,生成的項目中,.eslintrc.js 配置文件中 extends 的配置是這樣的:

{
    extends: [
        'plugin:vue/essential',
        'eslint:recommended', 
        '@vue/prettier'
    ]
}
複製代碼

它的最後一項擴展是 @vue/prettier,這個對應的是 @vue/eslint-config-prettier 這個包,讓咱們看看這個包下面的 index.js 內容:

{
    plugins: ['prettier'],
    extends: [
        require.resolve('eslint-config-prettier'),
        require.resolve('eslint-config-prettier/vue')
    ],
    rules: {
        'prettier/prettier': 'warn'
    }
}
複製代碼

這個和咱們上面配置的內容是相差無幾的,而引入 eslint-config-prettier/vue 是由於這個 @vue/eslint-config-prettier 包依賴的 eslint-config-prettier 版本是 ^6.0.0 版本的,因此在處理衝突的時候須要特別指定和對應類型插件匹配的擴展。

讓 EditorConfig 助力多編輯器開發吧

EditorConfig 是個啥玩意? 它能夠對多種類型的單文件進行簡單的格式化,它提供的配置參數不多:

# 告訴 EditorConfig 插件,這是根文件,不用繼續往上查找
root = true

# 匹配所有文件
[*]

# 設置字符集
charset = utf-8

# 縮進風格,可選 space、tab
indent_style = tab

# 縮進的空格數,當 indent_style = tab 將使用 tab_width
# 不然使用 indent_size
indent_size = 2
tab_width = 2

# 結尾換行符,可選 lf、cr、crlf
end_of_line = lf

# 在文件結尾插入新行
insert_final_newline = true

# 刪除一行中的先後空格
trim_trailing_whitespace = true

# 匹配md結尾的文件
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false
複製代碼

雖然它提供的格式化的配置參數不多,就 3 個,縮進風格、是否在文件末尾插入新行和是否刪除一行中先後空格。可是它仍是很是有必要存在的,理由有 3 個:

  • 可以在不一樣的編輯器和 IDE 中保持一致的代碼風格;
  • 配合插件打開文件即自動格式化,很是方便
  • 支持格式化的文件類型不少;

若是須要讓以上的配置生效,還得在 VSCode 裏安裝 EditorConfig for VS Code 這個插件配合使用。

重點來了

能夠看到 EditorConfig 和 Prettier 會存在一些重複的配置,好比都提供了對縮進的配置參數,因此在實際使用的時候須要避免它們,或者把他們的參數設置爲一致。

在 VSCode 中支持 ESLint

前面作的配置,都須要執行命令才能進行檢查和修復代碼,仍是挺不方便的,若是我但願編輯完或者保存的時候去檢查代碼該如何作呢?能夠直接在 IDE 裏安裝 ESLint 插件,由於我使用的是 VSCode,因此這裏只介紹在 VSCode 中的配置。

在使用前,須要把 ESLint 擴展安裝到 VSCode 裏,這裏我就不細說安裝步驟了。 安裝完成後,須要在設置裏寫入配置:

  • 在 VSCode 左下角找到一個齒輪 ⚙ 圖標,點擊後選擇設置選項,這個時候打開了設置面板;
  • 而後在 VSCode 右上角找到打開設置(json)的圖標,點擊後,會打開 settings.json 文件;
  • 而後把如下配置貼進去便可;
{
    "eslint.alwaysShowStatus": true,  // 老是在 VSCode 顯示 ESLint 的狀態
    "eslint.quiet": true,             // 忽略 warning 的錯誤
    "editor.codeActionsOnSave": {     // 保存時使用 ESLint 修復可修復錯誤
        "source.fixAll": true,
        "source.fixAll.eslint": true
    }	
}
複製代碼

配置說明,在 ESLint 2.0.4 版本開始:

  • 不須要經過 eslint.validate 來指定校驗的文件類型了,已經自動支持了 .vue 文件;
  • editor.codeActionsOnSave 開啓保存自動修復功能;

當這樣配置以後呢,每次編輯代碼 ESLint 都會實時校驗代碼,且當保存的時候會自動 fix,是否是很方便呢。不過對於有些沒法自動 fix 的代碼就須要你手動去修改了,若是不想修改的話就能夠配置 rules 把該條規則給關閉掉。

其實在團隊開發的時候,最好把針對 VSCode 的配置,寫一個文件跟隨着項目,一塊兒提交到遠程倉庫,這樣的話就保證了項目成員都是用的這套配置。好比能夠在項目根目錄新建 .vscode/settings.json,而後寫入上面的那串配置內容。

在提交前作校驗 pre-commit

以上只是經過 ESLint 自動修復可以修復的錯誤以及經過 Prettier 進行代碼的格式化,可是在實際開發的時候不免會遇到沒法 fix 的錯誤,可能開發人員也忘記修改,若是這個時候把代碼提交到遠程倉庫,那就把糟糕的代碼給提交上去了。

那麼如何杜絕把糟糕的代碼提交上去呢?能夠經過配置 git hooks 的 pre-commit 鉤子來實現這個目的。主要是利用了 huskylint-staged 這 2 個包。husky 就是用來配置 git hooks 的,而 lint-staged 則是對拿到的 staged 文件進行處理,好比執行 npx eslint --fix 進行代碼校驗。

具體操做分兩種狀況:

  • package.json 和 .git 在同一個目錄下
  • package.json 和 .git 在不一樣的目錄下

package.json 和 .git 在同一個目錄下

一、執行如下命令:

npx mrm lint-staged
複製代碼

會自動安裝 lint-staged 和 husky 而且在 package.json 裏寫入 lint-staged。

注意:mrm 是一個自動化工具,它將根據 package.json 依賴項中的代碼質量工具來安裝和配置 husky 和 lint-staged,所以請確保在此以前安裝並配置全部代碼質量工具,如 Prettier 和 ESlint。

若是上面順利會在 package.json 裏寫入 lint-staged,能夠自行修改讓它支持 .vue 文件的校驗:

{
    "lint-staged": {
        "*.{js,vue}": "eslint --cache --fix"
    }
}
複製代碼

可能你在別的地方有看過以下這種在 lint-staged 最後一項加了 git add 的配置,這樣也是沒問題的。須要說明的是,若是 lint-staged 是 11.x.x 的版本已經自動實現了將修改過的代碼自動添加暫存區的功能,因此不須要再加 git add。

"lint-staged": {
    "*.{js,vue}": ["eslint --cache --fix", "git add"]
}
複製代碼

二、啓動 git hooks

npx husky install
複製代碼

通過上面的命令後,v6 版本的 husky 會在項目根目錄新建一個 .husky 目錄。若是是 v4 版本的則會寫入到 package.json 裏。

三、建立 pre-commit 鉤子

npx husky add .husky/pre-commit "npx lint-staged"
複製代碼

到這裏後,git commit 前自動執行代碼校驗和修復的功能就算完成了。而後你能夠試試修改文件,而後提交試試。

package.json 和 .git 在不一樣的目錄下

若是你的項目不是純前端項目,而是先後端代碼放在同一個項目下,好比以下這個 shop-system 的項目結構:

├─.git            // .git 目錄
├─shop-service    // 後端項目
├─shop-web        // 前端項目
複製代碼

若是 package.json 和 .git 在不一樣的目錄下,那麼經過第一種方式的 npx mrm lint-staged 來建立會失敗,將沒法建立 .husky 目錄。這個時候就須要稍微麻煩點了。

在 shop-web 目錄的終端下執行:

# 安裝 husky
npm install husky --save-dev

# 啓動 git hooks
cd .. && husky install shop-web/.husky

# 添加 pre-commit 鉤子
npx husky add .husky/pre-commit "cd shop-web && npx lint-staged"

# 安裝 lint-staged
npm install lint-staged -D
複製代碼

而後在 package.json 裏配置 lint-staged,就能夠大功告成。

{
    "lint-staged": {
        "*.{js,vue}": "eslint --cache --fix"
    }
}
複製代碼

參考:自定義目錄啓動 git hook

總結

這篇文章比較長,前先後後講了不少代碼校驗的東西,如今咱們來梳理下。

首先用 ESLint 來作代碼校驗,它自帶的 ruels 能提供 2 種類型的校驗,分別是代碼錯誤校驗和代碼格式校驗,而 ESLint 自己的核心工做其實就是校驗和修復錯誤的代碼,而對格式化的規則提供的很少。

因此若是想要對代碼格式化進行一個更加精細的配置則須要藉助 Prettier,由於它是隻負責風格的管控,因此用它再適合不過了。可是若是把 ESLint 和 Prettier 結合起來一塊兒使用的話,就可能會出現規則的衝突了,畢竟它們二者都會對風格進行處理,因此這個時候就能夠經過 eslint-config-prettier 這個擴展來把衝突的規則進行關閉,這個擴展不只能夠關閉和 ESLint 內置規則的衝突,還能夠關閉實際項目中引用到的擴展規則的衝突,好比和 Vue、React、TypeScript、Flow 的衝突。

在把 ESLint 和 Prettier 結合的時候,咱們但願讓 ESLint 來檢查代碼錯誤,而 Prettier 校驗代碼風格,那麼這個時候實際上是有 2 個任務的,須要用 2 條命令來處理的。可是有了 eslint-plugin-prettier 這個插件後就能夠很方便的把它們結合起來,當須要校驗代碼錯誤的時候 ESLint 自動會給你校驗,固然前提是 VSCode 裏必須按照 ESLint 插件,而當須要校驗代碼風格的時候 ESLint 就會調用 Prettier 的能力進行代碼風格的檢查。

文章的後面分別又細說了 EditorConfig 和提交代碼前校驗的處理,這裏就很少講了。

看到這裏但願你對代碼校驗和規範有一個新的認識,不過我最但願的是你可以本身動手爲你的項目配置一套校驗規則,若是不能成功,必定是個人文章寫的有問題,歡迎評論區留言指出不足之處,我是大海我來了,下篇文章見。

相關文章
相關標籤/搜索