iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 27
0
Modern Web

寫React的那些事系列 第 27

React Day27 - ESLint(1)

Linting tool是可以幫忙把關程式品質的工具,雖然它不是寫javascript必備的工作,但是當程式碼越來越複雜,或是團隊多人一起開發的時候,維持code的品質與coding style一致性就是很重要的事情!

它會用一套標準分析靜態的javascript code,當沒有達到標準規範,就會跳出訊息指示。它除了可以幫助建立coding style,還可以避免發生一些不預期的錯誤,像是結尾沒寫分號、使用沒有宣告導致變成全域變數...等問題,linting tool都能夠有效避免我們撰寫這些可能產生問題的程式碼,讓code看起來也更專業。

Javascript有許多這類工具可以使用,像是JSLint、JSHint、ESLint...等,但是ESLint是網路上大家都最推薦的一個,因為它非常有彈性,官方沒有認定哪一種style rules是最好的,所以任何rules都是pluggable,可以靠config設定你想要的規則,而且非常容易透過它的錯誤訊息找到問題,同時也支援ES6和JSX。

ESLint


ESLint的特點在上面講的差不多XD,這邊只好再重述一下官網說的概念:

The pluggable linting utility for JavaScript and JSX

ESLint的幾項優點:

  • Flexible:任何規則都可以設定是否啟用,依照程度分成跳出錯誤、跳出警告、完全忽略,有些規則甚至提供額外調整的選項。
  • 錯誤訊息簡潔且很容易看懂,會提供規則的名稱,讓我們很容易可以知道錯誤的地方在哪。
  • 可以extend別人的config設定,最有名的應該就是airbnb的config。
  • 對ES6和JSX的支援度都很好。
  • 可以產生lint結果的report,並支援多種格式,像是html、json、tab...等。

Config方式


Configuration Comments

使用註解的方式,把config內容設定在單一檔案中,會面會講到這種方式,也可以叫inline comments。

Configuration Files

可以設定在 .eslintrc 檔案或是package.json裡面的 eslintConfig 區段,和babel設定的方式很像,ESLint也會自動查找這個設定檔。而且 .eslintrc 支援在裡面的json寫註解。

.eslintrc的檔案,檔名可以是 .eslintrc ,也可以是 .eslintrc.* ,後面*代表不同語言格式,例如:.eslintrc.json。

查找的方式,假設資料夾結構如下:

project
├── .eslintrc
├── lib
│ └── source.js
└─┬ tests
  ├── .eslintrc
  └── test.js

在lib資料夾裡面的檔案,會使用project/.eslintrc的設定,而tests資料夾裡面的檔案,會使用project/.eslintrc加上project/tests/.eslintrc的設定,並且project/tests/.eslintrc的設定優先。如果同一個資料夾下, .eslintrc 和package.json的eslintConfig 區段都有設定時,package.json內的不會被使用。

.eslintignore

和git一樣的使用方式,ESLint也提供ignore讓我們設定哪些檔案可以被忽略。

Config內容


Environments

設定環境,因為不同的環境中會有不同的global變數,例如:設定browser環境,這代表裡面會設定window..等,browser環境下特定的全域變數。可以到官網看有哪些環境可以設定,你也可以設定多個env,它們彼此之間是沒有衝突的。

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

如果想使用的環境是來自於別的plugins,可以先指定沒有前綴詞 eslint-plugin- 的plugin名稱(example),加上一個斜線,後面接該plugin設定的環境名稱(custom):

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

如果只想針對單一檔案做這個設定,也可以在該檔案最上方加上:

/* eslint-env node, mocha */

Globals

設定自己定義的global變數,因為ESlint分析的是靜態的javascript,有一條規則:Disallow Undeclared Variables (no-undef),當js檔案中有使用到沒有定義的變數時它會報錯,不允許我們隨便使用global變數。但是某些時候,我們會使用一些第三方的library,例如:ga、mocha,在runtime時沒有問題,但在ESLint分析靜態檔案時會違反沒有定義的規則,所以使用到非環境本身的global變數,為了讓ESLint知道沒問題,就可以設定在globals這邊。

另外,也有一條規則是禁止改變全域變數:Disallow assignment to native objects or read-only global variables (no-global-assign),所以globals有額外的設定,讓這個變數是否可以重新指定、被更改。

這邊設定兩個global變數,var1設為true,表示可以重新指定,var2設為false,表示不允許重新指定(readonly):

{
  "globals": {
    "var1": true,
    "var2": false
  }
}

如果只想針對單一檔案做這個設定,也可以在該檔案最上方加上:

  • 當沒有指定是否可以被覆寫,預設是true,表示可以。
/* global var1, var2 */
// 或是
/* global var1:false, var2:false */

Plugins

前面其實有稍微提到,如果要使用第三方定義好的plugins就可以透過這邊設定,第三方plugins名稱通常長這樣 eslint-plugin-* ,當然也要先npm install要使用的packages,然後設定plugins時,這些packages的前綴詞 eslint-plugin- 可以保留或去掉只留後面名稱。

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

Rules

這邊是真正制定規則的地方,可以設定每一條規則是否啟用,或是有額外調整的選項。ESLint提供了非常多,真的非常多的rules可以設定,除了可以用 .eslintrc 設定,也可以像前面提到的在單一檔案做設定。

規則的錯誤級別,有三個值可以設定:

  • "off" or 0:把這個rule關閉,設定為不顯示、不報錯。
  • "warn" or 1:若違反這個rule,只跳出warning提示。
  • "error" or 2:若違反這個rule,顯示error。

以下rules設定的範例:

  • rules裡面設定的key,都是ESLint事先設定好的規則名稱,也都找得到rules說明
  • quotes這條規則,還可以設定希望字串是用單引號(single)還是雙引號(double),可以看個人或團隊習慣,非常有彈性!
{
  "rules": {
    "eqeqeq": "off",
    "curly": "error",
    "quotes": ["error", "double"]
  }
}

如果只想針對單一檔案做這個設定,也可以在該檔案最上方加上:

/* eslint curly: 2, quotes: ["error", "double"] */
// 或是
/* eslint eqeqeq: "off", curly: "error" */

如果使用第三方plugins,又希望改變其中一條rule,就可以用"plugin名稱/規則名稱"當key。像我們寫React通常會使用到的是eslint-plugin-react這個plugins,這邊用它來當範例,可以參考下面 react/jsx-indent 設定方式:

{
  "plugins": [
    "react"
  ],
  "rules": {
    "eqeqeq": "off",
    "curly": "error",
    "quotes": ["error", "double"],
    "react/jsx-indent": ["error", 4]
  }
}

Extends

繼承第三方config的設定,我們可以設定多組extends,也可以使用rule覆蓋它原本的規則,或是加上新的rule。Extends單一的config,在設定extends時,前綴詞 eslint-config- 也可以保留或去掉只留後面名稱。

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

Inline Comments


有時候希望可以在只有單一檔案或是局部程式碼設定不同rule,可以透過inline註解的方式設定。

整個檔案都關閉no-alert設定:

/* eslint-disable no-alert */

alert('foo');

在這段區域關閉全部eslint設定:

/* eslint-disable */

alert('foo');

/* eslint-enable */

在這段區域關閉no-alert和no-console的設定:

/* eslint-disable no-alert, no-console */

alert('foo');
console.log('bar');

/* eslint-enable no-alert, no-console */

在這行程式碼關閉eslint設定:

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

// eslint-disable-next-line
alert('foo');

在這行程式碼關閉no-alert設定:

alert('foo'); // eslint-disable-line no-alert

// eslint-disable-next-line no-alert
alert('foo');

現在,我們對ESLint config設定應該很有概念了!下一篇會來介紹extends的方式,並且實際修正我們todos的範例。

參考


A Comparison of JavaScript Linting Tools
ESLint User Guide


上一篇
React Day26 - Immutablejs
下一篇
React Day28 - ESLint(2)
系列文
寫React的那些事31

尚未有邦友留言

立即登入留言