ESLint 使用指南

yuanhjty發表於2019-03-21

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.org/docs/user-g…

命令模式

# eslint [選項] [操作目標]
eslint [options] [file|dir|glob]*
複製程式碼

注意

  • 當使用 glob 語法指定操作目標時,glob 模式會被 shell 解析,解析結果可能因 shell 不同而不同。如果想要使用 nodeglob 語法,必須使用引號將 glob 模式串引起來(在 Windows 中必須使用雙引號)。示例:

    eslint "lib/**"
    複製程式碼

命令選項

使用 ESLint 命令時,可以通過 eslint -h 概覽命令選項,找到自己需要的選項,然後後去官方文件 命令列介面部分 檢視該選項的詳細描述。

有些選項可接收一組引數,這類選項支援兩種傳參方式(有一個選項例外:--ignore-pattern 不支援第二種方式):

  1. 多次指定同一選項,每次接收一個不同的引數
  2. 將引數列表用逗號分隔,一次傳給選項

示例:

# 1.
eslint --ext .jsx --ext .js lib/

# 2.
eslint --ext .jsx,.js lib/
複製程式碼

配置

相對路徑解析

配置檔案中包含的相對路徑和 glob 模式都是基於當前配置檔案的路徑進行解析的。

兩種主要的配置方式

  1. 配置註釋 - 在目標檔案中使用註釋語法嵌入配置資訊。這種配置只對當前檔案有效。
  2. 配置檔案 - 在 JavaScriptJSONYAML 檔案中定義配置資訊。對於這種配置方式,配置資訊可以寫在單獨的 .eslintrc.* 檔案中,或者寫在 package.json 檔案的 eslintConfig 欄位中。這種配置對配置檔案所在目錄及其子目錄樹中的所有檔案有效。

配置檔案格式

  • JavaScript - use .eslintrc.js 檔案匯出一個包含配置資訊的物件。
  • YAML - 使用 .eslintrc.yaml.eslintrc.yml 定義配置。
  • JSON - 使用 .eslintrc.json 定義配置資訊,JSON 檔案中支援 JavaScript 註釋。
  • package.json - 在 package.json 檔案中增加一個 eslintConfig 欄位,在該欄位中定義配置資訊。
  • .eslintrc - 已廢棄

如果在同一個目錄中有多個配置檔案,則它們中間只有一個是有效的,優先順序如下:

  1. .eslintrc.js
  2. .eslintrc.yaml
  3. .eslintrc.yml
  4. .eslintrc.json
  5. .eslintrc
  6. package.json

配置層疊

官方文件:eslint.org/docs/user-g…

專案級配置檔案

在同一個專案中,可以為不同目錄指定不同的配置檔案。

當 lint 一個檔案時,ESLint :

  1. 從檔案所在目錄開始,在目錄樹中依次向上搜尋配置檔案,直到系統根目錄,或者直到找到一個包含 root: true 配置引數的配置檔案,最終得到一個配置檔案列表。
  2. 合併上一步得到的配置檔案列表中的配置項,得到最終的配置檔案配置。合併配置項時,在目錄樹中距離 lint 目標越近的配置檔案具有越高的優先順序。
  3. 執行其餘步驟。

完整的配置層疊關係

ESLint 配置除了通過配置檔案指定,還可以通過註釋內嵌或命令列選項指定。Lint 一個檔案所使用的最終配置是各種配置合併的結果,合併時各種配置的優先順序如下:

  1. 註釋內嵌配置

    1. /*eslint-disable*/ and /*eslint-enable*/
    2. /*global*/
    3. /*eslint*/
    4. /*eslint-env*/
  2. 通過命令列選項指定的配置

    1. --global
    2. --rule
    3. --env
    4. -c, --config
  3. 專案級配置檔案

  4. 如果沒有找到專案級配置檔案,並且沒有或沒有找到通過 --config 指定配置檔案,則去使用者家目錄(~/)下搜尋配置檔案。

如果上述配置均不存在,則 ESLint 丟擲 noConfigError

配置引數

  • parser

    指定 ESLint 使用的語法分析器。ESLint 相容的語法分析器有:EsprimaBabel-ESLint@typescript-eslint/parser,ESLint 預設使用 Esprima

  • parserOptions

    指定語法分析器選項,預設使用的語法分析器支援如下幾個選項:ecmaVersionsourceTypeecmaFeatures。示例:

    {
      "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" 分別是 semiquotes 各自特有的附加選項。

    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-standardeslint-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 依賴的外掛

配置示例

// .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 外掛

使用:在 VSCode 設定中將 eslint.enable 設定為 true

程式碼修復

工具:VSCode Prettier 外掛

使用:在 VSCode 設定中將 prettier.eslintIntegration 設定為 true,prettier 外掛執行格式化時將使用 prettier-eslint 完成下述操作:

  1. 使用 prettier 格式化程式碼
  2. 對上一步格式化過的程式碼執行 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"]
    }
}
複製程式碼

其他整合

eslint.org/docs/user-g…

完整配置示例

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",
}
*/
複製程式碼