About
ESLint 是一款開源的 JavaScript lint 工具,由 Nicholas C. Zakas 於2013 年建立。
ESLint 官方文件 About 頁面 分 About 和 Philosophy 兩個部分對 ESLint 做了介紹,簡潔明瞭,值得一讀。
藉助 ESLint,可將 靜態程式碼分析 和 問題程式碼協助修復 整合到 編碼、提交 和 打包 過程中,及早發現並協助修復程式碼中:
- 有語法錯誤的部分
- 不符合約定的樣式準則的部分
- 不符合約定的最佳實踐的部分
在專案開發中獲得如下收益:
- 在執行程式碼之前發現並修復語法錯誤,減少除錯耗時和潛在 bug
- 保證專案的編碼風格統一,提高可維護性
- 督促團隊成員在編碼時遵守約定的最佳實踐,提高程式碼質量
安裝
# Local Installation
yarn add -D eslint
# Global Installation
yarn add -g eslint
複製程式碼
注意
- ESLint 藉助 nodejs 的模組化機制引用外掛。所以,全域性安裝的 ESLint 只能使用全域性安裝的 ESLint 外掛,區域性安裝的 ESLint 只能使用區域性安裝的 ESLint 外掛。
命令列介面
命令模式
# eslint [選項] [操作目標]
eslint [options] [file|dir|glob]*
複製程式碼
注意
-
當使用
glob
語法指定操作目標時,glob
模式會被shell
解析,解析結果可能因shell
不同而不同。如果想要使用node
的glob
語法,必須使用引號將glob
模式串引起來(在 Windows 中必須使用雙引號)。示例:eslint "lib/**" 複製程式碼
命令選項
使用 ESLint 命令時,可以通過 eslint -h
概覽命令選項,找到自己需要的選項,然後後去官方文件 命令列介面部分 檢視該選項的詳細描述。
有些選項可接收一組引數,這類選項支援兩種傳參方式(有一個選項例外:--ignore-pattern
不支援第二種方式):
- 多次指定同一選項,每次接收一個不同的引數
- 將引數列表用逗號分隔,一次傳給選項
示例:
# 1.
eslint --ext .jsx --ext .js lib/
# 2.
eslint --ext .jsx,.js lib/
複製程式碼
配置
相對路徑解析
配置檔案中包含的相對路徑和 glob 模式都是基於當前配置檔案的路徑進行解析的。
兩種主要的配置方式
- 配置註釋 - 在目標檔案中使用註釋語法嵌入配置資訊。這種配置只對當前檔案有效。
- 配置檔案 - 在
JavaScript
、JSON
或YAML
檔案中定義配置資訊。對於這種配置方式,配置資訊可以寫在單獨的.eslintrc.*
檔案中,或者寫在package.json
檔案的eslintConfig
欄位中。這種配置對配置檔案所在目錄及其子目錄樹中的所有檔案有效。
配置檔案格式
JavaScript
- use.eslintrc.js
檔案匯出一個包含配置資訊的物件。YAML
- 使用.eslintrc.yaml
或.eslintrc.yml
定義配置。JSON
- 使用.eslintrc.json
定義配置資訊,JSON 檔案中支援 JavaScript 註釋。package.json
- 在package.json
檔案中增加一個eslintConfig
欄位,在該欄位中定義配置資訊。.eslintrc
- 已廢棄
如果在同一個目錄中有多個配置檔案,則它們中間只有一個是有效的,優先順序如下:
.eslintrc.js
.eslintrc.yaml
.eslintrc.yml
.eslintrc.json
.eslintrc
package.json
配置層疊
專案級配置檔案
在同一個專案中,可以為不同目錄指定不同的配置檔案。
當 lint 一個檔案時,ESLint :
- 從檔案所在目錄開始,在目錄樹中依次向上搜尋配置檔案,直到系統根目錄,或者直到找到一個包含
root: true
配置引數的配置檔案,最終得到一個配置檔案列表。 - 合併上一步得到的配置檔案列表中的配置項,得到最終的配置檔案配置。合併配置項時,在目錄樹中距離 lint 目標越近的配置檔案具有越高的優先順序。
- 執行其餘步驟。
完整的配置層疊關係
ESLint 配置除了通過配置檔案指定,還可以通過註釋內嵌或命令列選項指定。Lint 一個檔案所使用的最終配置是各種配置合併的結果,合併時各種配置的優先順序如下:
-
註釋內嵌配置
/*eslint-disable*/
and/*eslint-enable*/
/*global*/
/*eslint*/
/*eslint-env*/
-
通過命令列選項指定的配置
--global
--rule
--env
-c
,--config
-
專案級配置檔案
-
如果沒有找到專案級配置檔案,並且沒有或沒有找到通過
--config
指定配置檔案,則去使用者家目錄(~/
)下搜尋配置檔案。
如果上述配置均不存在,則 ESLint 丟擲 noConfigError
。
配置引數
-
parser
指定 ESLint 使用的語法分析器。ESLint 相容的語法分析器有:Esprima、Babel-ESLint、@typescript-eslint/parser,ESLint 預設使用 Esprima。
-
parserOptions
指定語法分析器選項,預設使用的語法分析器支援如下幾個選項:
ecmaVersion
、sourceType
、ecmaFeatures
。示例:{ "parserOptions": { "ecmaVersion": 6, "sourceType": "module", "ecmaFeatures": { "jsx": true } } } 複製程式碼
不同的語法分析器可能具有不同的選項。
-
env
指定執行環境,一個執行環境會預定義一組全域性變數。示例:
使用註釋配置
/* eslint-env node, mocha */ 複製程式碼
使用配置檔案:
{ "env": { "browser": true, "node": true } } 複製程式碼
-
globals
使用未在當前檔案中定義的全域性變數時,會命中
no-undef
規則,通過globals
配置指定的全域性變數無視no-undef
規則。示例:使用註釋配置
/* global var1, var2 */ /* global var1:writable, var2:writable */ 複製程式碼
在配置檔案中指定:
{ "globals": { "var1": "writable", "var2": "readonly" } } 複製程式碼
-
plugins
外掛是第三方定製的規則集合,
plugins
引數用於指定第三方外掛,外掛名中的eslint-plugin-
字首可以省略。示例:{ "plugins": [ "plugin1", "eslint-plugin-plugin2" ] } 複製程式碼
使用外掛時必須安裝其 npm 包。
注意
- 受限於 Node 的模組化機制,全域性安裝的 ESLint 只能使用全域性安裝的外掛,區域性安裝的 ESLint 只能使用區域性安裝的外掛,不支援全域性外掛和區域性外掛的混合使用。
-
rules
指定 ESLint 校驗規則。
所有規則獨立於其他規則,可單獨配置。
ESLint 內建規則:eslint.org/docs/rules/
規則組成:規則名、錯誤級別、附加選項
規則配置模式:
規則名: [錯誤級別, 附加選項] 規則名: 錯誤級別 複製程式碼
示例:
"rules": { "semi": ["error", "always"], "quotes": ["error", "double"] } 複製程式碼
在上述示例中,
"semi"
和"quotes"
是規則名,"error"
是規則錯誤級別,"always"
和"quotes"
分別是semi
和quotes
各自特有的附加選項。ESLint 定義了三種錯誤級別:
"off"
或0
- 關閉,不校驗該規則"warn"
或1
- 警告,不影響 exit code"error"
或2
- 錯誤,觸發該規則時 exit code 為1
關於規則的錯誤級別,在 ESLint 特性概覽 部分已有介紹。
使用註釋配置
/* eslint eqeqeq: "off", curly: "error" */ // 如果規則有額外選項,可以用陣列字面量語法 /* eslint quotes: ["error", "double"], curly: 2 */ 複製程式碼
使用配置檔案
{ "rules": { "eqeqeq": "off", "curly": "error", "quotes": ["error", "double"] } } 複製程式碼
可在檔案中使用註釋配置禁用全部規則或指定規則:
-
塊級禁用
/* 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 */ alert('foo'); /* eslint-disable no-alert */ alert('foo'); 複製程式碼
-
在指定行中禁用
alert('foo'); // eslint-disable-line alert('foo'); // eslint-disable-line no-alert alert('foo'); // eslint-disable-line no-alert, quotes, semi alert('foo'); /* eslint-disable-line */ alert('foo'); /* eslint-disable-line no-alert */ alert('foo'); /* eslint-disable-line no-alert, quotes, semi */ // eslint-disable-next-line // eslint-disable-next-line no-alert // eslint-disable-next-line no-alert, quotes, semi /* eslint-disable-next-line */ /* eslint-disable-next-line no-alert */ /* eslint-disable-next-line no-alert, quotes, semi */ alert('foo'); 複製程式碼
-
overrides
示例:
{ "rules": {...}, "overrides": [ { "files": ["*-test.js","*.spec.js"], "excludedFiles": "*.test.js", "rules": { "no-unused-expressions": "off" } } ] } 複製程式碼
對於匹配
overrides.files
且不匹配overrides.excludedFiles
的 檔案,overrides.rules
中的規則會覆蓋rules
中的同名規則。 -
settings
指定一個物件,這個物件會被提供給每一個將要執行的規則。
-
root
ESLint 在目錄樹種搜尋配置檔案時,若遇到
root
引數為true
的配置檔案,就會停止搜尋,否則沿著目錄樹一直向父級目錄的方向搜尋到系統根目錄為止。 -
extends
配置檔案可以在已有配置的基礎上進行擴充套件,
extends
用於指定基礎配置。該引數的值為以下之一:- 一個指定基礎配置來源的字串
- 一個指定基礎配置來源的字串的陣列:陣列中每個配置擴充套件它前面的配置
ESLint 支援遞迴擴充套件配置,所以基礎配置中也可包含
extends
引數。當指定基礎配置時,
rules
引數指定的規則可按如下幾種方式進行擴充套件:- 啟用基礎配置中沒有規則
- 繼承基礎配置中的規則,改變其錯誤級別,但不改變其附加選項:
- 基礎配置:
"eqeqeq": ["error", "allow-null"]
- 擴充套件配置:
"eqeqeq": "warn"
- 最終有效配置:
"eqeqeq": ["warn", "allow-null"]
- 基礎配置:
- 覆蓋基礎配置中的規則:
- 基礎配置:
"quotes": ["error", "single", "avoid-escape"]
- 擴充套件配置:
"quotes": ["error", "single"]
- 最終有效配置:
"quotes": ["error", "single"]
- 基礎配置:
使用
extends
指定的基礎配置來源可以是:-
eslint:recommended
,啟用 ESLint 內建規則集 的一個子集。 -
共享配置包,一類匯出 ESLint 配置物件的 npm 包,比如
eslint-config-standard
、eslint-config-airbnb
等。共享配置包需要安裝才能使用,配置時可省略報名中的eslint-config-
字首。示例:
{ "extends": ["airbnb"] "rules": { "no-set-state": "off" } } 複製程式碼
-
外掛匯出的命名配置,其配置值由以下幾部分組成:
plugin:
- 外掛包名(可省略字首,例如:
react
) /
- 配置名(例如:
recommended
)
示例:
{ "plugins": [ "react" ], "extends": [ "eslint:recommended", "plugin:react/recommended" ], "rules": { "no-set-state": "off" } } 複製程式碼
-
配置檔案,通過配置檔案的絕對路徑或相對路徑指定。
示例:
{ "extends": [ "./node_modules/coding-standard/eslintDefaults.js", "./node_modules/coding-standard/.eslintrc-es6", "./node_modules/coding-standard/.eslintrc-jsx", "./my-eslint-config.js" ], "rules": { "eqeqeq": "warn" } } 複製程式碼
-
eslint:all
,啟動所有 ESLint 內建規則,不推薦。
-
忽略檔案和目錄
使用
.eslintignore
檔案指定要忽略的檔案和目錄,忽略模式的指定使用.gitignore
的 規範。ESLint 預設忽略
/node_modules/*
和/bower_components/*
。示例:
# /node_modules/* and /bower_components/* in the project root are ignored by default # Ignore built files except build/index.js build/* !build/index.js 複製程式碼
基於 eslint-config-airbnb 擴充套件配置
eslint-config-airbnb 是一個 ESLint 共享配置包,支援 ECMAScript 6+ 和 React。
安裝 eslint-config-airbnb
# 安裝 eslint-config-airbnb
yarn add -D eslint-config-airbnb@latest
# 獲取 peerDependencies
npm info "eslint-config-airbnb@latest" peerDependencies
# 安裝 peerDependencies
yarn add -D <dependency_1>@<version> <dependency_2>@<version> ...
複製程式碼
eslint-config-airbnb 依賴的外掛
- eslint-plugin-import - 支援 ES6+
import
/export
語法以及模組路徑有效性的校驗。 - eslint-plugin-react - 支援 React 編碼規範的校驗。
- eslint-plugin-jsx-a11y - 支援 HTML 元素可訪問性的校驗。
配置示例
// .eslintrc.js
module.exports = {
root: true,
extends: ['airbnb'],
parserOptions: {
// eslint-config-airbnb: { ecmaVersion: 6, sourceType: 'module' }
ecmaFeatures: {
// eslint-config-airbnb: { jsx: true, es6: true }
generators: true,
},
},
env: {
// eslint-config-airbnb: { node: true, es6: true }
browser: true,
},
rules: {
indent: ['error', 4],
},
}
複製程式碼
使用 eslint-import-resolver-webpack
如果開啟了 eslint-plugin-import no-unresolved
規則,可以藉助該外掛使用 webpack 的 resolve
配置解析模組路徑。
安裝
yarn add -D eslint-import-resolver-webpack
複製程式碼
配置方式:
{
"settings": {
"import/resolver": "webpack", // 使用 webpack 預設配置
}
}
複製程式碼
{
"settings": {
"import/resolver": {
"webpack": {
"config": "webpack.dev.config.js" // 指定要使用的 webpack 配置檔案
}
}
}
}
複製程式碼
{
"settings": {
"import/resolver": {
"webpack": {
"config": { // 定義 webpack 配置物件
"resolve": {
"extensions": [".js", ".jsx"]
}
}
}
}
}
}
複製程式碼
使用 babel-eslint
babel-eslint 是一款用於 ESLint 的語法分析器,它支援使用 ESLint 分析所有 babel 相容的程式碼。
使用 babel-eslint 需要安裝 babel 並提供 babel 配置檔案。
ESLint 核心規則不支援實驗階段的語法,如果要使用這部分語法,需要配合 eslint-plugin-babel 使用。
安裝
# 安裝 babel-eslint
yarn add -D babel-eslint
# 安裝 eslint-plugin-babel
yarn add -D eslint-plugin-babel
複製程式碼
配置
{
"parser": "babel-eslint",
"plugins": ["babel"]
}
複製程式碼
整合
VSCode 整合
程式碼提示
使用:在 VSCode 設定中將 eslint.enable
設定為 true
程式碼修復
使用:在 VSCode 設定中將 prettier.eslintIntegration
設定為 true
,prettier 外掛執行格式化時將使用 prettier-eslint 完成下述操作:
- 使用 prettier 格式化程式碼
- 對上一步格式化過的程式碼執行
eslint --fix
相比於直接使用 eslint --fix
命令,prettier 外掛:
- 支援快捷鍵
- 支援更多的程式碼格式化選項
- 支援其他型別檔案的格式化
git commit 整合
在提交程式碼時,lint git 暫存區的程式碼,若 lint 不通過則中斷提交,保證問題程式碼不進入程式碼倉庫。
工具:
- husky - 提供 git hooks 支援
- lint-staged - 對暫存檔案(staged files)中匹配指定 glob 模式的檔案執行指定的 shell 命令。
配置示例:
package.json
{
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"linters": {
"**/*.js": ["eslint --fix", "git add"]
},
"ignore": ["**/{dist,build}/**/*.js", "**/*.min.js"]
}
}
複製程式碼
其他整合
完整配置示例
module.exports = {
root: true,
extends: ['airbnb'],
plugins: ['babel'],
parser: 'babel-eslint',
parserOptions: {
ecmaFeatures: {
generators: true,
},
},
env: {
browser: true,
},
rules: {
indent: ['error', 4],
},
settings: {
'import/resolver': {
// 識別 webpack 配置的路徑別名
webpack: {
config: 'webpack.config.js',
}
},
},
}
/**
peerDependencies: {
"babel-eslint": "^10.0.1",
"eslint": "^5.15.0",
"eslint-config-airbnb": "^17.1.0",
"eslint-import-resolver-webpack": "^0.11.0",
"eslint-plugin-babel": "^5.3.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-jsx-a11y": "^6.1.1",
"eslint-plugin-react": "^7.11.0",
}
*/
複製程式碼