Eslint 超簡單入門教程

兩個月之前在項目中就開始使用 Eslint ,當時直接 copy 別人的 .eslintrc.js 文件,感覺好復(fù)雜,一直沒吃透,中間去把 Eslint 官方文檔看了數(shù)遍,依然無果。今天剛好沒事,回過頭來想整理一下 Eslint 的使用,突然發(fā)現(xiàn)變得好簡單。總結(jié)下在這過程中走得彎路。

  • 先要知道 Lint 是什么,Eslint 又是什么;
  • 因為想要的太多(想把 Eslint 官方文檔里每個字都記住)就容易抓不住重點(目的是在項目中使用 Eslint,這僅僅是個工具,工具又怎么會搞的太難)。

目標

學(xué)習完本教程希望對下面這個 .eslintrc.js 文件能夠做到心里有數(shù)。

// .eslintrc.js 
module.exports = {
  "extends": "airbnb",
  "rules": {
    "semi": [2, "never"],
    "no-console": 0,
    "comma-dangle": [2, "always-multiline"],
    "max-len": 0,
    "react/jsx-first-prop-new-line": 0,
    "react/jsx-filename-extension": 0,
    "space-before-function-paren": [2, "always"],
    "no-unused-expressions": [0, {
      "allowShortCircuit": true,
      "allowTernary": true
    }],
    "arrow-body-style": [0, "never"],
    "func-names": 0,
    "prefer-const": 0,
    "no-extend-native": 0,
    "no-param-reassign": 0,
    "no-restricted-syntax": 0,
    "no-eval": 0,
    "no-continue": 0,
    "react/jsx-no-bind": 0,
    "no-unused-vars": [2, { "ignoreRestSiblings": true }],
    "no-underscore-dangle": 0,
    "global-require": 0,
    "import/no-unresolved": 0,
    "import/extensions": 0,
    "jsx-a11y/href-no-hash": 0,
    "react/no-array-index-key": 0,
    "react/require-default-props": 0,
    "react/forbid-prop-types": 0,
    "react/no-string-refs": 0,
    "react/no-find-dom-node": 0,
    "import/no-extraneous-dependencies": 0,
    "import/prefer-default-export": 0,
    "react/no-danger": 0,
    "jsx-a11y/no-static-element-interactions": 0,
  },
  "parser": "babel-eslint",
  "parserOptions": {
    "sourceType": "module",
    "ecmaVersion": 8,
    "ecmaFeatures": {
      "jsx": true,
      "experimentalObjectRestSpread": true
    }
  },
  "settings": {
    "import/resolver": "node"
    }
};

Eslint 是什么

編碼規(guī)范

每個程序員都有自己的編碼習慣,最常見的莫過于:

  • 有的人寫代碼一行代碼結(jié)尾必須加分號 ;,有的人覺得不加分號 ; 更好看;
  • 有的人寫代碼一行代碼不會超過 80 個字符,認為這樣看起來簡潔明了,有的人喜歡把所有邏輯都寫在一行代碼上,覺得別人看不懂的代碼很牛逼;
  • 有的人使用變量必然會先定義 var a = 10;,而粗心的人寫變量可能沒有定義過就直接使用 b = 10;

Lint 的含義

如果你寫自己的項目怎么折騰都沒關(guān)系,但是在公司中老板希望每個人寫出的代碼都要符合一個統(tǒng)一的規(guī)則,這樣別人看源碼就能夠看得懂,因為源碼是符合統(tǒng)一的編碼規(guī)范制定的。

那么問題來了,總不能每個人寫的代碼老板都要一行行代碼去檢查吧,這是一件很蠢的事情。凡是重復(fù)性的工作,都應(yīng)該被制作成工具來節(jié)約成本。這個工具應(yīng)該做兩件事情:

  • 提供編碼規(guī)范;
  • 提供自動檢驗代碼的程序,并打印檢驗結(jié)果:告訴你哪一個文件哪一行代碼不符合哪一條編碼規(guī)范,方便你去修改代碼。

Lint 因此而誕生。

Eslint 的含義

Lint 是檢驗代碼格式工具的一個統(tǒng)稱,具體的工具有 JslintEslint 等等 ...........

我們可以形象地將 Lint 看成是電商行業(yè),而電商行業(yè)具體表現(xiàn)有淘寶(Eslint)、京東(Jslint)等。

使用 Eslint

確保你的電腦安裝了 node 和 npm 環(huán)境

創(chuàng)建項目

npm init 指令會在項目根目錄下生成 package.json 文件。

$ d:
$ cd d:
$ mkdir test-eslint
$ cd test-eslint
$ npm init

安裝依賴包

--save-dev 會把 eslint 安裝到 package.json 文件中的 devDependencies 屬性中,意思是只是開發(fā)階段用到這個包,上線時就不需要這個包了。

$ npm install eslint --save-dev

設(shè)置 package.json 文件

打開 package.json 文件,修改 script 屬性如下:

"scripts": {
    "test": "react-scripts test --env=jsdom",
    "lint": "eslint src",
    "lint:create": "eslint --init"
}
  • script 屬性的意思是腳本,使用方法是在 cmd 窗口中輸入 npm run 指令 的形式,如:npm run lint:create
  • "lint:create": "eslint --init" 這個腳本是為了生成 .eslintrc.js 文件,在介紹 Lint 的時候說到 Lint 應(yīng)該提供編碼規(guī)范,規(guī)范寫在哪里,就寫在這個文件,所以我們需要創(chuàng)建它;
  • "lint": "eslint src" 在介紹 Lint 的時候也說到 Lint 應(yīng)該提供自動校驗代碼的程序,這個腳本是讓 Lint 自動檢驗 src 目錄下所有的 .js 文件。

創(chuàng)建 .eslint.js 文件

$ npm run lint:create

> 20170811@0.1.0 lint:create D:\code\test\20170811
> eslint --init

? How would you like to configure ESLint? Answer questions about your style // 以問答的形式創(chuàng)建配置文件
? Are you using ECMAScript 6 features? Yes      // 是否校驗 Es6 語法
? Are you using ES6 modules? Yes                // 是否校驗 Es6 模塊語法
? Where will your code run? Browser             // 代碼運行環(huán)境,Browser 指瀏覽器
? Do you use CommonJS? Yes                      // 是否校驗 CommonJs 語法
? Do you use JSX? Yes                           // 是否校驗 JSX 語法
? Do you use React? Yes                         // 是否校驗 React 語法
? What style of indentation do you use? Tabs    // 首行空白選擇 Tab 鍵還是 Space
? What quotes do you use for strings? Double    // 字符串使用單引號 'string' 還是雙引號 "string"
? What line endings do you use? Windows         // 操作系統(tǒng)
? Do you require semicolons? Yes                // 每行代碼結(jié)尾是否校驗加分號 ;
? What format do you want your config file to be in? JavaScript     // 以 .js 格式生成配置文件
Installing eslint-plugin-react@latest   // 因為要校驗 Reac 語法,所以這里需要下載一個 React 語法規(guī)則的包

創(chuàng)建完成后根目錄下應(yīng)該會出現(xiàn) .eslintrc.js 文件

創(chuàng)建 index.js 文件

在根目錄下創(chuàng)建 src/index.js 文件,內(nèi)容如下,接下來就使用 Eslint 來檢驗這個 .js 文件是否符合編碼規(guī)范。

const lint = 'eslint'

此時的目錄結(jié)構(gòu)應(yīng)該為:

- test-eslint
    + .eslintrc.js
    + package.json
    - src
        + index.js

校驗代碼

$ npm run lint

    1:7   error  'lint' is assigned a value but never used  no-unused-vars
    1:14  error  Strings must use doublequote               quotes
    1:22  error  Missing semicolon                          semi

    3 problems (3 errors, 0 warnings)
    2 errors, 0 warnings potentially fixable with the `--fix` option.

這里報了三個錯誤,分別是:

  • index.js 第1行第7個字符,報錯編碼規(guī)則為 no-unused-vars:變量 lint 只定義了,但是未使用;
  • index.js 第1行第14個字符,報錯編碼規(guī)則為 quotes:編碼規(guī)范字符串只能使用雙引號,這里卻使用了單引號;
  • index.js 第1行第22個字符,報錯編碼規(guī)則為 semi:編碼規(guī)范每行代碼結(jié)尾必須加分號,這里沒有加分號。

當我們熟悉了編碼規(guī)范之后,只需進行響應(yīng)的修改就可以使代碼形成統(tǒng)一的風格。剛開始如果對編碼規(guī)范具體某一條規(guī)則不了解的話,可以在 eslint規(guī)則表 查看用法。(不建議去背規(guī)則表,而是用到什么查什么,把它當成字典來用,不那么累)

設(shè)置 --fix 參數(shù)

打開 package.json 文件,修改 script 屬性如下:

"scripts": {
    "test": "react-scripts test --env=jsdom",
    "lint": "eslint src --fix",
    "lint:create": "eslint --init"
}

說明:這里給 "lint": "eslint src --fix", 加上 --fix 參數(shù),是 Eslint 提供的自動修復(fù)基礎(chǔ)錯誤的功能。

此時運行 npm run lint 會看到少了兩條報錯信息,并不是說編碼規(guī)范變了,而是 Eslint 自動修復(fù)了基礎(chǔ)錯誤,打開 index.js 文件,可看到字符串自動變成了雙引號,并且代碼末尾也加上了分號。可惜的是 --fix 只能修復(fù)基礎(chǔ)的不影響代碼邏輯的錯誤,像 no-unused-vars 這種錯誤只能手動修改。

配置文件講解

按照上述操作,會生成默認 .eslintrc.js 配置文件,內(nèi)容如下:

// .eslintrc.js 
module.exports = {
    "env": {
        "browser": true,
        "commonjs": true,
        "es6": true
    },
    "extends": "eslint:recommended",
    "parserOptions": {
        "ecmaFeatures": {
            "experimentalObjectRestSpread": true,
            "jsx": true
        },
        "sourceType": "module"
    },
    "plugins": [
        "react"
    ],
    "rules": {
        "indent": [
            "error",
            "tab"
        ],
        "linebreak-style": [
            "error",
            "windows"
        ],
        "quotes": [
            "error",
            "double"
        ],
        "semi": [
            "error",
            "always"
        ]
    }
}

該文件導(dǎo)出一個對象,對象包含屬性 envextendsparserOptionspluginsrules 五個屬性,作為剛學(xué)習 Eslint 的新手,我們總是想要竭盡所能的詳細了解每一個屬性是什么,干嘛用的,以獲取小小的安全感。

env、parserOptions、plugins

這三個放在一起將是因為你只需要知道它們是干嘛的:我的程序里要用到 ES6 、React 、JSX 語法,這幾個屬性就是讓 Eslint 能夠檢驗到這些語法的。其余的你不需要知道更多的哪怕一丟丟的東東了。

作者在學(xué)習之初在這塊浪費了很多時間,官方文檔看了很多遍,大多不能理解什么意思,后來想它既然提供這么一個自動生成配置文件的工具,并且是命令行交互的方式,我只需要告訴它我要用 ES6 、React 、JSX 語法,它會自動進行相關(guān)配置滿足我的要求即可。

extends

前面一直說檢驗代碼遵循編碼規(guī)范,那到底是什么規(guī)范呢。

值為 "eslint:recommended" 的 extends 屬性啟用一系列核心規(guī)則,這些規(guī)則是經(jīng)過前人驗證的最佳實踐(所謂最佳實踐,就是大家伙都覺得應(yīng)該遵循的編碼規(guī)范),想知道最佳實踐具體有哪些編碼規(guī)范,可以在 eslint規(guī)則表 中查看被標記為 √ 的規(guī)則項。

如果覺得官方提供的默認規(guī)則不好用,可以自定義規(guī)則配置文件,然后發(fā)布成 Npm 包,eslint-config-airbnb 就是別人自定義的編碼規(guī)范,使用 npm 安裝后,在我們自己的 .eslintrc.js 中進行配置 "extends": "airbnb",eslint-config 這個前綴可以省略不寫,這樣我們就使用了 eslint-config-airbnb 中的規(guī)則,而不是官方的規(guī)則 "extends":"eslint:recommended" 了。關(guān)于如何創(chuàng)建自定義規(guī)則配置并共享可以參考: 如何自定義規(guī)則配置

關(guān)于 "airbnb" 編碼規(guī)范說兩句,在接觸到大多數(shù)開源項目中,大多數(shù)的作者都會使用 "airbnb" 編碼規(guī)范而不是 官方的 "extends": "eslint:recommended" 編碼規(guī)范。

如果我們覺得 eslint-config-airbnb 規(guī)則配置中個別規(guī)則并不符合當前項目的要求,可以直接在 .eslintrc.js 配置 rules 屬性,優(yōu)先級高于共享規(guī)則 airbnb。

rules

配置文件也生成了,我們怎么知道我們的系統(tǒng)會遵循什么規(guī)則呢??

在前面的列子中,使用 npm run lint 校驗出了三處錯誤,假如我們的項目中字符串就是要使用單引號而不是雙引號,代碼結(jié)尾就是要不加分號才好看,變量就是定義了可能不會使用,我們可以通過設(shè)置 rules 來定義我們自己的編碼規(guī)范,即規(guī)則。

ESLint 附帶有大量的規(guī)則,修改規(guī)則應(yīng)遵循如下要求:

  • "off" 或 0 - 關(guān)閉規(guī)則
  • "warn" 或 1 - 開啟規(guī)則,使用警告級別的錯誤:warn (不會導(dǎo)致程序退出)
  • "error" 或 2 - 開啟規(guī)則,使用錯誤級別的錯誤:error (當被觸發(fā)的時候,程序會退出)

有的規(guī)則沒有屬性,只需控制是開啟還是關(guān)閉,像這樣:"eqeqeq": "off",有的規(guī)則有自己的屬性,使用起來像這樣:"quotes": ["error", "double"],具體有沒有自帶屬性,可查看 eslint規(guī)則表

修改 .eslintrc.js 文件中的 rules 屬性:

"rules": {
    "indent": [
        "error",
        "tab"
    ],
    "linebreak-style": [
        "error",
        "windows"
    ],
    "quotes": [
        "error",
        "single"        // 改成字符串必須由單引號括起來而不是雙引號,'string'不報錯,"string"報錯
    ],
    "semi": [
        "error",
        "never"         // 改成代碼結(jié)尾不再加分號,加了分號報錯,不加分號不報錯
    ],
    "no-unused-vars": 0 // 0 相當于 off,表示關(guān)閉規(guī)則,相當于不再校驗這條規(guī)則:變量定義了必須使用
}

此時再使用 npm run lint 進行代碼校驗,沒有報錯就說明校驗通過,代碼符合統(tǒng)一編碼規(guī)范。

D:\code\test\20170811>npm run lint

> 20170811@0.1.0 lint D:\code\test\20170811
> eslint src


D:\code\test\20170811>

可能存在的疑問

剛接觸 ESlint ,并不清楚有哪些規(guī)則怎么辦,要去 eslint規(guī)則表 一條條記憶嗎?答案是 no。

個人認為 ESlint 的配置文件并不是一次性完成的,而是在項目過程中慢慢完善的。你可以放心大膽的先進行編碼,然后使用 npm run lint 校驗代碼的編碼規(guī)范,如果這時候報錯,可以在報錯信息中知道是哪一條編碼規(guī)范報錯了,你可能并不認識它們,此時去 eslint規(guī)則表 查詢相應(yīng)規(guī)則的使用方法,如:no-unused-vars,從而進一步確定項目中是否需要這條編碼規(guī)范,如果需要,進行局部調(diào)整即可。

$ npm run lint

    1:7   error  'lint' is assigned a value but never used  no-unused-vars
    1:14  error  Strings must use doublequote               quotes
    1:22  error  Missing semicolon                          semi

    3 problems (3 errors, 0 warnings)
    2 errors, 0 warnings potentially fixable with the `--fix` option.

更新部分

全局變量配置。

如使用 window 對象,默認情況下會報 no-undef 的錯誤,需要在 .eslintrc 中進行相應(yīng)配置。

{
    "rules": {
        // ...
    },
    "globals": {
        "window": true
    }
}

單行跳過 lint 校驗

在實際編碼時,可能會出現(xiàn)以下的代碼。

const apple = "apple";
const balana = "balana";

module.exports = {
    fruit: balana ;
}

在最上面定義了兩個變量,在底部的配置文件中只可能用到其中一個變量,另一個用不到的在 eslint 校驗時就會報錯 no-unused-vars 的錯誤,意思是變量定義了但是沒有被用到。

其中一種解決方案是在 .eslintrc 文件中配置 rules no-unused-vars: 0,意思是項目中不檢驗變量定義未使用這條規(guī)則。強烈不建議這樣做,這個規(guī)則十分有用,可以規(guī)避編寫代碼時遺漏的變量。

另一種解決方案就是使用行內(nèi)注釋跳過對 apple 和 balana 兩個變量跳過 eslint 校驗,只影響這兩個變量,不影響外部。

const apple = "apple";  // eslint-disable-line
const balana = "balana";  // eslint-disable-line
  
module.exports = {
    fruit: balana ;
}

此時使用 eslint 校驗時就不會再報錯了。

常見規(guī)則含義解釋

var foo = {x: x};    // 會報錯
var bar = {a: function () {}};  // 會報錯
var foo = {x};    // 不會報錯
var bar = {a () {}};    // 不會報錯
  • prefer-arrow-callback 要求回調(diào)函數(shù)使用箭頭函數(shù)
// 回調(diào)函數(shù),函數(shù)的參數(shù)是個函數(shù),這個參數(shù)函數(shù)就是回調(diào)函數(shù)
funciton bar () {}      // 不是回調(diào)函數(shù),不會報錯
// setTimeout 的第一個參數(shù)就是回調(diào)函數(shù),不用箭頭函數(shù)會報錯
setTimeout(() => {
    // .......
}, 1000)
  • no-param-reassign 禁止對函數(shù)的參數(shù)重新賦值
function bar ({ data = {} }) {
    data.num = 12;      // 會報錯
}
/* 
雖然報錯,又不想要將該校驗關(guān)閉,如果代碼中只有 data 這個屬性有這種情形,
可以在 .eslintrc.js 中的 rules 屬性中添加配置(可忽略 data 屬性做此校驗):
'no-param-reassign': ['error', { 'props': true, 'ignorePropertyModificationsFor': ['data'] }],
'no-param-reassign': 0,  // 關(guān)閉該屬性校驗
*/
  • no-trailing-spaces 禁止行尾空格

  • no-shadow 禁止變量聲明與外層作用域的變量同名

function sum (num) {
  let num = 2;    // 報錯,因為 num 變量作為參數(shù)已經(jīng)申明過了
}

常用的幾個規(guī)則

"quotes": [1, "single"],            # 單引號
"quote-props":[2, "as-needed"],     # 雙引號自動變單引號
"semi": [2, "never"],               # 一行結(jié)尾不要寫分號
"comma-dangle": [1,"always-multiline"]  # 對象或數(shù)組多行寫法時,最后一個值加逗號
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,382評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,038評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,853評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,616評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,112評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,355評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,869評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,727評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,928評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,165評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,570評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,813評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,585評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,892評論 2 372

推薦閱讀更多精彩內(nèi)容

  • EsLint入門學(xué)習整理 這兩天因為公司要求,就對ESLint進行了初步的了解,網(wǎng)上的內(nèi)容基本上都差不多,但是內(nèi)容...
    點柈閱讀 26,043評論 3 42
  • ESLint 配置 ESlint 被設(shè)計為完全可配置的,這意味著你可以關(guān)閉每一個規(guī)則而只運行基本語法驗證,或混合和...
    靜默虛空閱讀 41,414評論 3 14
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,618評論 25 708
  • 寫在開頭 先說說為什么要寫這篇文章, 最初的原因是組里的小朋友們看了webpack文檔后, 表情都是這樣的: (摘...
    Lefter閱讀 5,310評論 4 31
  • 前些天,和小朋友一起去她住的地方,給她搬東西。立在街角的老梧桐樹下,面對著十字路口等車,我拿出手機代替眼睛,隨處亂...
    暖清陽閱讀 292評論 0 1