淺析ESlint的作用、演進歷史、ESLint校驗文件方式及常見配置介紹、2種配置方式、eslint檢測配置文件的機制


一、為什么要用ESLint

1、總結為兩點:保持代碼風格一致、減少代碼出錯幾率

  為了解決這類靜態代碼問題,每個團隊都需要一個統一的 JS 代碼規范,團隊成員都遵守這份代碼規范來編寫代碼。當然,靠人來保障代碼規范是不可靠的,需要有對應的工具來保障,ESLint 就是這個工具

2、為什么不是Prettier

  Prettier確實可以按照設置的規則對代碼進行統一格式化,但是需要明確的一點是,Prettier只會在格式上對代碼進行格式化,一些隱藏的代碼質量問題Prettier是無法發現的,而ESLint可以。

3、目標:開發時提示、保存時自動修復、提交時檢測

二、ESlint 演進歷史

  提到ESLint,我們就不得不提及他的前輩們JSLint和JSHint,以及它們的區別。

1、JSLint:

  JSLint 的靈感來源於C語言的檢查工具 Lint,用來掃描C語言源文件以便找到其中的錯誤。

  JSlint 是在2010年開源的第一款針對JS的語法檢測工具,它和Lint做着相同的事,掃描JS的源文件來找到錯誤;它內部也是通過fs.readFile來讀取文件然后逐行來進行檢查

  JSLint的問題很明顯:所有的配置項都內置不可配置,本身推崇愛用不用的傳統,不像開發者開放配置或者修改他覺得對的規則,因此很多人也無法忍受他的規則

2、JSHint,它的初衷就是為了能讓開發者自定義規則 lint rules,因此提供了豐富的配置項,給開發者極大的自由

  JSHint相比於JSLint,最大的特點就是可配置,我們可以在項目中放入一個.jshintrc的配置文件,JSLint就會加載配置文件用於代碼分析

  由於JSHint是基於JSLint開發的,因此JSLint的一些問題也繼承下來了,比如不易擴展以及不容易直接根據報錯定位到具體的配置規則等

3、ESLint

  2013年 Zakas 大佬發現JSHint無法滿足自己定制化規則的需要,因此設想開發一個基於AST的Linter,可以動態執行額外的規則,同時可以很方面的擴展規則,於是在13年6月份開源推出了全新的ESLint。

  靈感來源於PHP Linter,將源碼解析成AST,然后檢測AST是否符合規則;ESLint最開始使用esprima解析器將源碼解析成AST,然后就可以使用任意規則來檢測AST是否符合預期,這也是ESLint高可擴展的原因。

  剛開始ESlint的推出並沒有撼動JSHint的霸主地位,由於ESlint需要將源碼轉為AST,而JSHint直接檢測源文件字符串,因此執行速度比JSHint慢很多;真正讓ESLint實現彎道超車的是ES6的出現

  2015年,ES6規范發布后,由於大部分瀏覽器支持程度不高,因此需要Babel將代碼轉換編譯成ES5或者更低版本;同時由於ES6變化很大,短期內JSHint無法完全支持,這時ESLint的高擴展性的優點顯現出來了,不僅可以擴展規則,連默認的解析器也能替換;Babel團隊就為ESLint開發了babel-eslint替換默認的解析器esprima,讓ESLint率先支持ES6。

三、ESLint 配置

  ESLint被設計成完全可配置的,我們可以用多種方式配置它的規則,或者配置要檢測文件的范圍。

1、初始化:如果想在現有的項目中引入eslint,我們可以在項目中進行初始化:

npm i eslint --save-dev npx eslint --init

  在經過一系列問答后,會在項目根目錄創建一個我們熟悉的.eslintrc.js配置文件;安裝后就可以通過命令行對項目中的文件需要檢測了:

# 檢測單個文件
npx eslint file1.js file2.js
# 檢測src和scripts目錄
npx eslint src scripts

  一般我們會把eslint命令行配置到packages.json中:

"scripts": { "lint": "npx eslint src scripts", "lint:fix": "npx eslint src scripts --fix", "lint:create": "npx eslint --init" }

  這里有一個--fix后綴,是ESLint提供自動修復基礎錯誤的功能,我們運行lint:fix后發現有一些報錯信息消失了,代碼也改變了;不過它只能修復一些基礎的不影響代碼邏輯的錯誤,比如代碼末尾加上分號、表達式的空格等等。

  ESLint默認只會檢測.js后綴的文件,如果我們想對更多類型的文件進行檢測,比如.vue、.jsx,可以使用--ext選項,參數用逗號分隔:

"scripts": { "lint": "npx eslint --ext .js,.jsx,.vue src", }

  對於一些公共的js,或者測試腳本,不需要進行檢測,我們可以通過在項目根目錄創建一個.eslintignore告訴ESLint去忽略特定的目錄或者文件:

public/ src/main.js

  除了.eslintignore中指定的文件或目錄,ESLint總是忽略/node_modules/* 和/bower_components/*中的文件;因此對於一些目前解決不了的規則報錯,但是我們需要打包上線,在不影響運行的情況下,我們就可以利用.eslintignore文件將其暫時忽略。

2、ESLint一共有兩種配置方式

  • 配置注釋:使用JavaScript注釋把配置信息直接嵌入到一個代碼源文件中
  • 配置文件:1. 使用 JavaScript、JSON 或者 YAML 文件為整個目錄(處理你的主目錄)和它的子目錄指定配置信息。可以配置一個獨立的 .eslintrc.* 文件,或者直接在 package.json 文件里的 eslintConfig 字段指定配置,ESLint 會查找和自動讀取它們,再者,你可以在命令行運行時指定一個任意的配置文件。

(1)第一種方式是直接把lint規則嵌入源代碼中;

/* eslint eqeqeq: "error" */
var num = 1 num == '1'

  eqeqeq代表eslint校驗規則,error代表校驗報錯級別,后面會詳細說明;這個eslint校驗規則只會對該文件生效

  我們還可以使用其他注釋,更精確地管理eslint對某個文件或某一行代碼的校驗:

/* eslint-disable */ alert('該注釋放在文件頂部,eslint不會檢查整個文件') /* eslint-enable */ alert('重新啟用eslint檢查') /* eslint-disable eqeqeq */ alert('只禁止某一個或多個規則') /* eslint-disable-next-line */ alert('下一行禁止eslint檢查') alert('當前行禁止eslint檢查') // eslint-disable-line

(2)第二種方式是直接把lint規則放到我們的配置文件中,

  上面init初始化生成的.eslintrc.js就是一個配置文件,官方還提供了其他幾種配置文件名稱(優先級從上到下),一般情況下我們使用.eslintrc.js就可以了。

.eslintrc.js
.eslintrc.yaml
.eslintrc.yml
.eslintrc.json
.eslintrc
package.json

四、配置詳解

// 我們詳細看下.eslintrc.js文件內部有哪些配置選項:
module.exports = { "globals": {}, "env": { "browser": true, "es2021": true }, "extends": "eslint:recommended", "parse": "babel-eslint", "parserOptions": { "ecmaVersion": 12, "sourceType": "module" }, "rules": {} };

1、globals 全局變量:腳本在執行期間訪問的額外的全局變量

當訪問當前源文件內未定義的變量時,no-undef 規則將發出警告。如果你想在一個源文件里使用全局變量,在Globals中定義這些全局變量,這樣ESLint就不會發出警告了

  首先是我們的 globals ,ESLint會檢測未聲明的變量,並發出報錯,比如node環境中的process,瀏覽器環境下的全局變量console,以及我們通過cdn引入的jQuery定義的$等;我們可以在 globals 中進行變量聲明:

{ "globals": { // true表示該變量可讀寫,false表示變量是只讀
        "$": true, "console": false } }

2、env 環境

  但是node或者瀏覽器中的全局變量很多,如果我們一個個進行聲明顯得繁瑣,因此就需要用到我們的 env,這是對環境定義的一組全局變量的預設:一個環境定義了一組預定義的全局變量

指定不同的環境可以給對應環境下提供預設的全局變量,比如說在 browser 環境下,可以使用 window 全局變量;在 node 環境下,可以使用 process 全局變量等。

這些環境並不是互斥的,所以可以同時定義多個。可以在源文件里、在配置文件中或使用 命令行 的 --env 選項來指定環境。

{ "env": { "browser": true, "node": true, "jquery": true } }

  更多的環境參數可以看ESLint聲明環境。

3、parser解析器及解析參數parserOptions

這里可以類比webpack,自身只能處理js、及json文件,css、html等文件需要通過自定義loader處理來理解

  解析器將源代碼轉換為稱為抽象語法樹AST的數據格式,然后,插件使用這種數據格式圍繞代碼的外觀或行為創建稱為lint規則的斷言。

  我們上面說到ESLint可以更換解析器,"parse": "babel-eslint"就是用來指定要使用的解析器,它有以下幾個選擇:

  • esprima:ESLint最開始使用的解析器
  • espree:默認,ESLint自己基於esprima v1.2.2開發的一個解析器
  • babel-eslint:一個對Babel解析器的包裝,使其能夠與ESLint兼容。
  • @typescript-eslint/parser:將TypeScript轉換成與estree兼容的形式,以便在ESLint中使用。

  那么這幾個解析器怎么選擇呢?如果你想使用一些先進的語法(ES6789),就使用babel-eslint(需要npm安裝);如果你想使用typescript,就使用@typescript-eslint/parser。

  選好了解析器,我們可以通過parserOptions給解析器傳入一些其他的配置參數:

{ "parser": "babel-eslint", "parserOptions": { // 代碼模塊類型,可選script(默認),module
    "sourceType": "module", // es版本號,默認為5,可以使用年份2015(同6)
    "ecamVersion": 6, // es 特性配置
    "ecmaFeatures": { "globalReturn": true, // 允許在全局作用域下使用 return 語句
        "impliedStrict": true, // 啟用全局 strict mode 
        "jsx": true // 啟用 JSX
 } }, }

4、規則 rules

  ESLint可以配置大量的規則,我們可以在配置文件的rules屬性自定義需要的規則:

  對於檢驗規則,有3個報錯等級:

  • "off" 或 0:關閉規則
  • "warn" 或 1:開啟規則,warn級別的錯誤 (不會導致程序退出)
  • "error" 或 2:開啟規則,error級別的錯誤(當被觸發的時候,程序會退出)

  有些規則沒有屬性,只需控制開啟還是關閉;有些規則可以傳入屬性,我們通過數組的方式傳入參數:

{ "rules":{ // 代碼縮進,使用tab縮進,switch語句的case縮進級別,1表示2個空格
        "indent": ["error", "tab", { "SwitchCase": 1 }], // 引號,雙引號
        "quotes": ["error", "double"], // 在語句末尾使用分號
        "semi": ["error", "always"] } }

  對於剛接觸ESLint的同學,看到這么多的規則肯定很懵逼,難道要一條一條來記么?肯定不是的;項目的ESLint配置文件並不是一次性完成的,而是在項目開發中慢慢完善起來的,因為並不是所有的規則都是我們項目所需要的。因此我們可以先進行編碼,在編碼的過程中使用npm run lint校驗代碼規范,如果報錯,可以通過報錯信息去詳細查看是那一條規范報錯:

  比如這里的報錯no-unused-vars我們可以看到它來自第六行,再去文檔查找,發現是我們在js中有一個定義了卻未使用的變量;在團隊協商后可以進一步來確定項目是否需要這條規范。

5、擴展 extends

  如果每條規則都需要團隊協商配置還是比較繁瑣的,在項目開始配置時,我們可以先使用一些業內已經成熟的、大家普遍遵循的編碼規范(最佳實踐);我們可以通過extends字段傳入一些規范,它接收String/Array:

{ "extends": [ "eslint:recommended", "plugin:vue/essential", "@vue/prettier", "eslint-config-standard" ] }

  extends可以使用以下幾種類型的擴展:

  • eslint:開頭的ESLint官方擴展,有兩個:eslint:recommended(推薦規范)和eslint:all(所有規范)。
  • plugin:開頭的擴展是插件類型擴展
  • eslint-config:開頭的來自npm包,使用時可以省略eslint-config-,比如上面的可以直接寫成standard
  • @:開頭的擴展和eslint-config一樣,是在npm包上面加了一層作用域scope

  需要注意的是:多個擴展中有相同的規則,以后面引入的擴展中規則為准。

  eslint:recommended推薦使用的規則在規則列表的右側用綠色√標記。

  插件類型的擴展一般先通過npm安裝插件,以上面的vue為例,我們先來安裝:npm install --save-dev eslint eslint-plugin-vue

  安裝后一個插件中會有很多同類型擴展可供選擇,比如vue就有以下幾種擴展:

  • plugin:vue/base:基礎
  • plugin:vue/essential:必不可少的
  • plugin:vue/recommended:推薦的
  • plugin:vue/strongly-recommended:強烈推薦

  針對擴展中的規則,我們也能夠通過rules來對它進行覆寫

{ "extends": [ "plugin:vue/recommended" ], "rules": { // 覆寫規則
    "vue/no-unused-vars": "error" } }

  除了上面的eslint-config-standard,還有以下幾個比較知名的編碼規范:

  不過需要注意的是,很多規范不僅需要安裝擴展本身,還需要配合插件,比如eslint-config-standard,我們還需要安裝下面幾個插件才能有效:

npm i eslint-config-standard -D npm i eslint-plugin-promise eslint-plugin-import eslint-plugin-node -D

6、插件 plugins

ESLint雖然可以定義很多的rules,以及通過extends來引入更多的規則,但是說到底只是檢查JS語法。如果需要檢查Vue中的template或者React中的jsx,就束手無策了。所以引入插件的目的就是為了增強ESLint的檢查能力和范圍。

在配置文件里配置插件時,可以使用 plugins 關鍵字來存放插件名字的列表。插件名稱可以省略 eslint-plugin- 前綴。

  在Webpack中,插件是用來擴展功能,讓其能夠處理更多的文件類型以及功能,ESLint中的插件也是同樣的作用;雖然ESLint提供了幾百種規則可供選擇,但是隨着JS框架和語法的發展,這么多規則還是顯得不夠,因為官方的規則只能檢查標准的JS語法;如果我們寫的是vue或者react的jsx,那么ESLint就不能檢測了。

  這時就需要安裝ESLint插件,用來定制一些特色的規則進行檢測;eslint插件以eslint-plugin-開頭,使用時可以省略;比如我們上面檢測.vue文件就用到eslint-plugin-vue插件;需要注意的是,我們在配置eslint-plugin-vue這個插件時,如果僅配置"plugins": ["vue"],vue文件中template內容還是會解析失敗。

  這是因為不管是默認的espree還是babel-eslint解析器都無法解析.vue中template的內容;eslint-plugin-vue插件依賴vue-eslint-parser解析器,而vue-eslint-parser解析器只會解析template內容,不會檢測script中的JS內容,因此我們還需要指定一下解析器:

{ "extends": ["eslint:recommended"], "plugins": ["vue"], "parser": "vue-eslint-parser", "parserOptions": { "parser": "babel-eslint", "ecmaVersion": 12, "sourceType": "module", }, }

  上面parserOptions.parser不少同學肯定看的有點迷糊,這是由於外層的解析器只能有一個,我們已經用了vue-eslint-parser就不能再寫其他的;因此vue-eslint-parser的做法是在解析器選項中再傳入一個解析器選項用來處理script中的JS內容。

  如果想讓ESLint檢測vue文件,確保將.vue后綴加入--ext選項中。

// 而react配置則較為簡單了,引入插件,選擇對應的擴展規則即可:
{ "extends": [ "eslint:recommended", "plugin:react/recommended" ], "parserOptions": { // 啟用jsx語法支持
        "ecmaFeatures": { "jsx": true }, "ecmaVersion": 12, "sourceType": "module" }, "plugins": [ "react" ], }

7、其他配置:配置當前目錄為 root

  ESLint檢測配置文件步驟:

  1. 在要檢測的文件同一目錄里尋找 .eslintrc.*package.json
  2. 緊接着在父級目錄里尋找,一直到文件系統的根目錄;
  3. 如果在前兩步發現有 root:true 的配置,停止在父級目錄中尋找 .eslintrc
  4. 如果以上步驟都沒有找到,則回退到用戶主目錄 ~/.eslintrc 中自定義的默認配置;
  通常我們都習慣把 ESLint 配置文件放到項目根目錄,因此可以為了避免 ESLint 校驗的時候往父級目錄查找配置文件,所以需要在配置文件中加上 root: true。
{ "root": true, }

五、ESLint 校驗文件

1、校驗.js類型文件
// 校驗 a.js 和 b.js 
npx eslint a.js b.js // 校驗 src 和 scripts 目錄 
npx eslint src scripts

2、校驗其他類型文件

  通常ESLint只能校驗JS文件。比如需要校驗.vue文件,光配置vue插件vue-eslint-parser解析器是不夠的,還需要讓ESLint在查找文件的時候找到.vue文件。ESLint提供了--ext來指定具體需要校驗的文件

npx eslint --ext .js,.vue src

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

  rules列表項 中標識了🔧規則表示該規則是可以自動修復的,ESLint提供了--fix

// package.json配置scripts
{ "scripts": { "lint": "npx eslint --ext .js,.vue src", "lint:fix": "npx eslint --fix --ext .js,.vue src", } }

4、過濾一些不需要校驗的文件:通過創建一個.eslintignore文件來配置,告訴 ESLint 校驗的時候忽略它們

學習鏈接:https://mp.weixin.qq.com/s/Gg37sEBsu3J5Ov6a8Frq5w


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM