1. 程式人生 > 程式設計 >JS程式碼檢查工具ESLint介紹與使用方法

JS程式碼檢查工具ESLint介紹與使用方法

ESLint不但提供一些預設的規則,也提供使用者自定義規則來約束所寫的JavaScript程式碼。

JS程式碼檢查工具ESLint介紹與使用方法

發展歷史

Douglas Crockford大神根據自己的理念用JavaScript寫了一個JavaScript程式碼規範檢查工具,這就是JSLint。後來非常流行,也的確幫助了廣大的JavaScript程式設計師。但是,大神對於自己的程式碼規範不做絲毫的妥協,對開源社群的反饋的迴應也不禮貌。於是,JSLint從一個幫助程式設計師規範程式碼,避免Bug的工具,變成了一個讓程式碼像Crockford的工具。在最不信神的IT界,這當然不能忍了

2011年,一個叫Anton Kovalyov的前端程式設計師藉助開源社群的力量弄出來了JSHint,該工具的思想基本上和JSLint是一致的,但具有以下幾點優勢:1、可配置規則。2、社群支援度高。3、可定製結果報表

起初幾年,JSHint 一直是前端程式碼檢測工具的首選。但在 2013 年,Zakas 大佬發現 JSHint 已經無法滿足自己定製化規則的需求,而且和 Anton 討論後達成共識這根本在不可能在 JSHint 上實現。同時 Zakas 還設想發明一個基於 AST 的 lint,可以動態執行額外的規則,同時可以很方便的擴充套件規則

2013 年的 6 月份,Zakas 釋出了全新的 lint 工具——ESLint。ESLint 的出現並沒有撼動 JSHint 的霸主地位。由於前者是利用 AST 處理規則,用 Esprima 解析程式碼,執行速度要比只需要一步搞定的 JSHint 慢很多;其次當時已經有許多編輯器對 JSHint 支援完善,生態足夠強大。真正讓 ESLint 逆襲的是 ECMAScript 6 的出現

2015 年 6 月,ES2015 規範正式釋出。但是釋出後,市面上瀏覽器對最新標準的支援情況極其有限。如果想要提前體驗最新標準的語法,就得靠 Babel 之類的工具將程式碼編譯成 ES5 甚至更低的版本,同時一些實驗性的特性也能靠 Babel 轉換。這時 JSHint 就略尷尬,ES2015 變化很大,短期內無法完全支援。ESLint 可擴充套件的優勢一下就體現出來了,不僅可以擴充套件規則,甚至連解析器也能替換。Babel 團隊就為 ESLint 開發了 babel-eslint 替換預設解析器,讓 ESLint 率先支援 ES2015 語法

也是在 2015 年,React 的應用越來越廣泛,誕生不久的 JSX 也愈加流行。ESLint 本身也不支援 JSX 語法。還是因為可擴充套件性,eslint-plugin-react 的出現讓 ESLint 也能支援當時 React 特有的規則

至此,ESLint 完美躺贏,替代 JSHint 成為前端主流工具

ESLint詳細配置

註釋配置

有兩種主要的方式來配置 ESLint,其中一種就是註釋配置,使用 JavaScript 註釋把配置資訊直接嵌入到一個程式碼原始檔中

可以在檔案中使用以下格式的塊註釋來臨時禁止規則出現警告

/* eslint-disable */
alert('foo');
/* eslint-enable */

也可以對指定的規則啟用或禁用警告:

/* eslint-disable no-alert,no-console */
alert('foo');
console.log('bar');
/* eslint-enable no-alert,no-console */

如果在整個檔案範圍內禁止規則出現警告,將 /* eslint-disable */ 塊註釋放在檔案頂部:

/* eslint-disable */
alert('foo');

檔案配置

另一種是檔案配置,使用 JavaScript、JSON 或者 YAML 檔案為整個目錄和它的子目錄指定配置資訊

ESLint 支援幾種格式的配置檔案

JavaScript - 使用 .eslintrc.js 然後輸出一個配置物件。

YAML - 使用 .eslintrc.yaml 或 .eslintrc.yml 去定義配置的結構。

JSON - 使用 .eslintrc.json 去定義配置的結構,ESLint 的 JSON 檔案允許 JavaScript 風格的註釋。

(棄用) - 使用 .eslintrc,可以使 JSON 也可以是 YAML。

package.json - 在 package.json 裡建立一個 eslintConfig屬性,在那裡定義配置。

如果同一個目錄下有多個配置檔案,ESLint 只會使用一個。優先順序順序如下

1 .eslintrc.js

2 .eslintrc.yaml

3 .eslintrc.yml

4 .eslintrc.json

5 .eslintrc

6  package.json

除了配置一個獨立的 .eslintrc.* 檔案,也可以直接在 package.json 檔案裡的 eslintConfig 欄位指定配置,ESLint 將自動在要檢測的檔案目錄裡尋找它們,緊接著是父級目錄,一直到檔案系統的根目錄

{
  "name": "mypackage","version": "0.0.1","eslintConfig": {
    "env": {
      "browser": true,"node": true
    }
  }
}

或者使用 -c 選項傳遞命令列將檔案保持到任意地方

eslint -c myconfig.json myfiletotest.js

配置語言

ESLint 允許指定想要支援的 JavaScript 語言選項。預設情況下,ESLint 支援 ECMAScript 5 語法。可以覆蓋該設定,以啟用對 ECMAScript 其它版本和 JSX 的支援

ecmaVersion - 預設設定為3,5(預設), 可以使用 6、7、8 或 9 來指定想要使用的 ECMAScript 版本。也可以用使用年份命名的版本號指定為 2015(同 6),2016(同 7),或 2017(同 8)或 2018(同 9)

sourceType - 設定為 "script" (預設) 或 "module"(如果程式碼是 ECMAScript 模組)

ecmaFeatures - 這是個物件,表示想使用的額外的語言特性:

globalReturn - 允許在全域性作用域下使用 return 語句

impliedStrict - 啟用全域性 strict mode (如果 ecmaVersion 是 5 或更高)

jsx - 啟用 JSX

experimentalObjectRestSpread - 啟用實驗性的 object rest/spread properties 支援

配置示例

  "parserOptions": {
    "ecmaVersion": 6,"sourceType": "module","ecmaFeatures": {
      "jsx": true
    }
  }

配置環境

一個環境定義了一組預定義的全域性變數。這些環境並不是互斥的,可以同時定義多個。可用的環境包括

browser - 瀏覽器環境中的全域性變數。

node - Node.js 全域性變數和 Node.js 作用域。

commonjs - CommonJS 全域性變數和 CommonJS 作用域 

shared-node-browser - Node.js 和 Browser 通用全域性變數。

es6 - 啟用除了 modules 以外的所有 ECMAScript 6 特性(該選項會自動設定 ecmaVersion 解析器選項為 6)

worker - Web Workers 全域性變數。

amd - 將 require() 和 define() 定義為像 amd 一樣的全域性變數。

mocha - 新增所有的 Mocha 測試全域性變數。

jasmine - 新增所有的 Jasmine 版本 1.3 和 2.0 的測試全域性變數。

jest - Jest 全域性變數。

phantomjs - PhantomJS 全域性變數。

protractor - Protractor 全域性變數。

qunit - QUnit 全域性變數。

jquery - jQuery 全域性變數。

prototypejs - Prototype.js 全域性變數。

shelljs - ShellJS 全域性變數。

meteor - Meteor 全域性變數。

mongo - MongoDB 全域性變數。

applescript - AppleScript 全域性變數。

nashorn - Java 8 Nashorn 全域性變數。

serviceworker - Service Worker 全域性變數。

atomtest - Atom 測試全域性變數。

embertest - Ember 測試全域性變數。

webextensions - WebExtensions 全域性變數。

greasemonkey - GreaseMonkey 全域性變數。

可以在JavaScript 檔案中使用註釋來指定環境

/* eslint-env node,mocha */

也可以在配置檔案裡指定環境,使用 env 關鍵字指定想啟用的環境,並設定它們為 true

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

如果想在一個特定的外掛中使用一種環境,確保提前在 plugins 數組裡指定了外掛名,然後在 env 配置中不帶字首的外掛名後跟一個 / ,緊隨著環境名

{
  "plugins": ["example"],"env": {
    "example/custom": true
  }
}

配置外掛

ESLint 支援使用第三方外掛。在使用外掛之前,必須使用 npm 安裝它。

在配置檔案裡配置外掛時,可以使用 plugins 關鍵字來存放外掛名字的列表。外掛名稱可以省略 eslint-plugin- 字首

{
  "plugins": [
    "plugin1","eslint-plugin-plugin2"
  ]
}

注意:由於 Node.js 的 require 函式的行為,全域性安裝的 ESLint 例項只能使用全域性安裝的 ESLint 外掛,本地安裝的版本,只能用本地安裝的外掛。不支援混合本地和全域性外掛

配置規則

ESLint 附帶有大量的規則。可以使用註釋或配置檔案修改專案中要使用的規則。要改變一個規則設定,必須將規則 ID 設定為下列值之一:

"off" 或 0 - 關閉規則

"warn" 或 1 - 開啟規則,使用警告級別的錯誤:warn (不會導致程式退出)

"error" 或 2 - 開啟規則,使用錯誤級別的錯誤:error (當被觸發的時候,程式會退出)

為了在檔案註釋裡配置規則,使用以下格式的註釋:

/* eslint eqeqeq: "off",curly: "error" */

也可以在配置檔案中進行規則配置

{
  "rules": {
    "eqeqeq": "off","curly": "error","quotes": ["error","double"]
  }
}

配置定義在外掛中的一個規則的時候,必須使用 外掛名/規則ID 的形式

{
  "plugins": [
    "plugin1"
  ],"rules": {
    "eqeqeq": "off","double"],"plugin1/rule1": "error"
  }
}

也可以使用這種格式的註釋配置

/* eslint "plugin1/rule1": "error" */

配置繼承

一個配置檔案可以被基礎配置中的已啟用的規則繼承

值為 "eslint:recommended" 的 extends 屬性啟用一系列核心規則,這些規則報告一些常見問題。這個推薦的子集只能在 ESLint 主要版本進行更新

"extends": "eslint:recommended"

外掛是一個 npm 包,通常輸出規則。一些外掛也可以輸出一個或多個命名的 配置。要確保這個包安裝在 ESLint 能請求到的目錄下

{
  "plugins": [
    "react"
  ],"extends": [
    "eslint:recommended","plugin:react/recommended"
  ],"rules": {
    "no-set-state": "off"
  }
}

extends 屬性值可以是基本配置檔案的絕對路徑或相對路徑。 ESLint 解析基本配置檔案的相對路徑相對使用的配置檔案,除非那個檔案在主目錄或非 ESLint 安裝目錄的父級目錄。在這些情況下,ESLint 解析基本配合檔案的相對路徑相對於被檢測的專案目錄(尤其是當前工作目錄)

{
  "extends": [
    "./node_modules/coding-standard/eslintDefaults.js","./node_modules/coding-standard/.eslintrc-es6","./node_modules/coding-standard/.eslintrc-jsx"
  ],"rules": {
    "eqeqeq": "warn"
  }
}

配置忽略

可以通過在專案根目錄建立一個 .eslintignore 檔案告訴 ESLint 去忽略特定的檔案和目錄

.eslintignore 檔案是一個純文字檔案,其中的每一行都是一個 glob 模式表明哪些路徑應該忽略檢測

例如,以下將忽略所有的 JavaScript 檔案:

**/*.js

如果沒有發現 .eslintignore 檔案,也沒有指定替代檔案,ESLint 將在 package.json 檔案中查詢 eslintIgnore 鍵,來檢查要忽略的檔案

{
 "name": "mypackage","eslintConfig": {
   "env": {
     "browser": true,"node": true
   }
 },"eslintIgnore": ["hello.js","world.js"]
}

NodeJS配置eslint規則

下面來介紹NodeJS環境下如何配置airbnb-base的eslint規則

1、本地安裝eslint、eslint-config-airbnb-base、eslint-plugin-import

npm install --save-dev eslint
npm install --save-dev eslint-config-airbnb-base
npm install --save-dev eslint-plugin-import

注意: 最好使用npm,而不是cnpm安裝。因為在使用本地安裝的eslint時,會使用其安裝路徑。而npm和cnpm的安裝路徑不一致

2、安裝成功後,package.json檔案中增加如下欄位

 "devDependencies": {
  "eslint": "^4.19.1","eslint-config-airbnb-base": "^12.1.0","eslint-plugin-import": "^2.12.0"
 }

3、在根目錄下設定.eslintrc.js配置檔案

module.exports = {
 "extends": ["airbnb-base"],"env": {
  "es6": true,"node": true
 },"rules": {
  "comma-dangle": ["error","never"],// 要求或禁止末尾逗號:不允許逗號
  "indent": ["error",2],// JavaScript程式碼強制使用一致的縮排:2格縮排
  "semi": ["error",// 不使用分號
  "arrow-parens": ["error","as-needed"],// 箭頭函式的引數可以不使用圓括號
  "linebreak-style": "off",// 取消換行符\n或\r\n的驗證
  "object-curly-newline": ["error",{ "consistent": true }],// 花括號內的換行符不一定要格式一致
  "function-paren-newline": "off",// 不驗證函式括號內的換行
  "import/extensions": "off",// 取消對副檔名的驗證
  "no-param-reassign": "off",// 允許對函式引數進行再賦值
  "no-underscore-dangle": "off",// 允許在識別符號中使用下劃線
  "no-use-before-define": "off",// 允許變數和函式在定義前使用
  "no-unused-expressions": "off",// 允許使用未使用過的表示式,以此來支援a && a()的程式碼形式
  "no-console": "off",// 啟用console控制檯
  "consistent-return": "off",// 關閉函式中return的檢測
  "no-shadow": "off",// 可以使用同名變數,"newline-per-chained-call": "off",//取消方法鏈呼叫中的換行符的檢測
  "import/newline-after-import": "off"
 }
}

4、在命令列工具中使用命令,對檔案進行lint校驗

PS D:\blog\api\node_modules\.bin> ./eslint ../../index.js

D:\blog\api\index.js
 16:1 error 'a' is not defined no-undef

✖ 1 problem (1 error,0 warnings)

React使用eslint

1、安裝eslint-config-airbnb配置合集

npm install --save-dev eslint-config-airbnb

Airbnb包括了以下三個外掛

eslint-plugin-import

eslint-plugin-react 

eslint-plugin-jsx-a11y

2、在根目錄下建立.eslintrc.js配置檔案

module.exports = {
 // 指定校驗的ECMAScript的版本及特性
 "parserOptions": {
  "ecmaVersion": 7,// ECMAScript版本,7為ES7
  "sourceType": "module",//預設script,如果程式碼是ECMAScript模組,設定為module
  "ecmaFeatures": { // 使用額外的語言特性
    "jsx": true // 啟用JSX
  }
 },// 當訪問未定義的變數時,no-undef 規則將發出警告
 // 指定指令碼的執行環境。每種環境都有一組特定的預定義全域性變數
 "env": {
  "es6": true,"node": true,"browser": true,},// 當訪問未定義的變數時,no-undef 規則將發出警告
 // 指令碼在執行期間訪問的額外的全域性變數
 "globals": {
  "document": true,"navigator": true,"window":true,"node":true
 },// 使用第三方airbnb開發配置合集
 "extends": "airbnb",// eslint-config-airbnb包括了以下3個外掛
 "plugins": [
  "react","jsx-a11y","import"
 ],// 定義自己的規則
 "rules": {
  "comma-dangle": ["error",// 箭頭函式的引數可以不使用圓括號
  "react/jsx-filename-extension": [1,{ "extensions": [".js",".jsx"] }],//reajs檔案的字尾名為.js或.jsx均可
  "linebreak-style": "off",// 取消對副檔名的驗證
  "import/no-unresolved": "off",// 取消自動解析路徑,以此開啟alias的別名路徑設定
  "no-shadow": "off",// 取消變數宣告覆蓋的驗證,保證mapDispatchToProps的正確使用
  "no-param-reassign": "off",// 允許使用未使用過的表示式,以此來支援a && a()的程式碼形式
  "jsx-a11y/anchor-is-valid": [ "error",{ "components": [ "Link" ],"specialLink": [ "to" ]}],// 允許正常地使用Link
  "import/no-extraneous-dependencies": "off",//使用history/createBrowserHistory引入包時,不會報錯
  "no-console": "off" // 啟用console控制檯
 }
};

Vue使用eslint

使用vue-cli建立專案時,如果使用eslint,會有如下圖所示的選項,選擇使用standard還是airbnb規範

JS程式碼檢查工具ESLint介紹與使用方法

以standard規範建立成功後,package.json檔案,會出現如下欄位

"eslint": "^4.15.0","eslint-config-standard": "^10.2.1","eslint-friendly-formatter": "^3.0.0","eslint-loader": "^1.7.1","eslint-plugin-import": "^2.7.0","eslint-plugin-node": "^5.2.0","eslint-plugin-promise": "^3.4.0","eslint-plugin-standard": "^3.0.1","eslint-plugin-vue": "^4.0.0",

與此同時,在根目錄下自動生成.eslintrc.js配置檔案

// https://eslint.org/docs/user-guide/configuring

module.exports = {
 root: true,parserOptions: {
  parser: 'babel-eslint'
 },env: {
  browser: true
 },extends: [
  // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
  // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
  'plugin:vue/base',// https://github.com/standard/standard/blob/master/docs/RULES-en.md
  'standard'
 ],// required to lint *.vue files
 plugins: ['vue'],// add your custom rules here
 rules: {
  // allow async-await
  'generator-star-spacing': 'off',// allow debugger during development
  'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',}
}

如果需要更改為更嚴格的驗證,可以下載並使用airbnb規範

npm install --save-dev eslint-config-airbnb-base

在extends欄位中,將standard更改為airbnb-base,將plugin:vue/base更改為plugin: vue/recommended

 extends: [
  'plugin:vue/recommended','airbnb-base'
 ],

新增一些自定義的規則,最終的配置檔案如下所示

// https://eslint.org/docs/user-guide/configuring

module.exports = {
 root: true,extends: [
  // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
  // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
  'plugin:vue/recommended',// https://github.com/standard/standard/blob/master/docs/RULES-en.md
  'airbnb-base'
 ],"linebreak-style": "off",// 取消換行符\n或\r\n的驗證
  "semi": ["error",// 箭頭函式的引數可以不使用圓括號
  "comma-dangle": ["error",// 不允許末尾逗號
  "consistent-return": "off",// 關閉函式中return的檢測
  "object-curly-newline": ["error",// 花括號內的換行符不一定要格式一致
  "global-require": "off",// 取消對require的驗證,使得可以使用require來載入圖片的相對路徑
  "function-paren-newline": "off",// 不驗證函式括號內的換行
  "import/no-unresolved": "off",// 取消自動解析路徑,以此開啟alias的別名路徑設定
  "no-param-reassign": "off",// 允許對函式引數進行再賦值
  "import/extensions": "off",// 取消對副檔名的驗證
  "max-len": "off",// 取消行的最大長度的驗證,使SVG不用重新調整格式
  "no-underscore-dangle": "off",//允許識別符號中有下劃線,從而支援vue中外掛的使用
  "no-console": "off",// 啟用console控制檯
  "no-unused-expressions": "off",// 允許使用未使用過的表示式,以此來支援a && a()的程式碼形式
  "no-shadow": "off",// 取消變數宣告覆蓋的驗證
  'vue/attribute-hyphenation': 0,// 取消對元素特性只能使用中劃線或小駝峰形式的驗證
  'vue/max-attributes-per-line': 0 // 取消元素有多個特性時,每個特性獨佔一行的驗證
 }
}

更多關於JS程式碼檢查工具ESLint的文章大家可以看看下面的相關連結