Eslint 入門詳解教程
目錄
目標
學習完本教程希望對下面這個 .eslintrc.js
檔案能夠做到心裡有數。
// .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 是什麼
編碼規範
每個程式設計師都有自己的編碼習慣,最常見的莫過於:
- 有的人寫程式碼一行程式碼結尾必須加分號
;
,有的人覺得不加分號;
更好看; - 有的人寫程式碼一行程式碼不會超過 80 個字元,認為這樣看起來簡潔明瞭,有的人喜歡把所有邏輯都寫在一行程式碼上,覺得別人看不懂的程式碼很牛逼;
- 有的人使用變數必然會先定義
var a = 10;
,而粗心的人寫變數可能沒有定義過就直接使用b = 10;
;
Lint 的含義
如果你寫自己的專案怎麼折騰都沒關係,但是在公司中老闆希望每個人寫出的程式碼都要符合一個統一的規則,這樣別人看原始碼就能夠看得懂,因為原始碼是符合統一的編碼規範制定的。
那麼問題來了,總不能每個人寫的程式碼老闆都要一行行程式碼去檢查吧,這是一件很蠢的事情。凡是重複性的工作,都應該被製作成工具來節約成本。這個工具應該做兩件事情:
- 提供編碼規範;
- 提供自動檢驗程式碼的程式,並列印檢驗結果:告訴你哪一個檔案哪一行程式碼不符合哪一條編碼規範,方便你去修改程式碼。
Lint 因此而誕生。
Eslint 的含義
Lint 是檢驗程式碼格式工具的一個統稱,具體的工具有 Jslint
、 Eslint
等等 ...........
我們可以形象地將 Lint 看成是電商行業,而電商行業具體表現有淘寶(Eslint)、京東(Jslint)等。
使用 Eslint
確保你的電腦安裝了 node 和 npm 環境
建立專案
npm init
指令會在專案根目錄下生成 package.json
檔案。
$ d:
$ cd d:
$ mkdir test-eslint
$ cd test-eslint
$ npm init
安裝依賴包
--save-dev
會把 eslint 安裝到 package.json 檔案中的 devDependencies 屬性中,意思是隻是開發階段用到這個包,上線時就不需要這個包了。
$ npm install eslint --save-dev
設定 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 應該提供編碼規範,規範寫在哪裡,就寫在這個檔案,所以我們需要建立它;"lint": "eslint src"
在介紹 Lint 的時候也說到 Lint 應該提供自動校驗程式碼的程式,這個指令碼是讓 Lint 自動檢驗 src 目錄下所有的 .js 檔案。
建立 .eslint.js 檔案
$ npm run lint:create
> [email protected] lint:create D:\code\test\20170811
> eslint --init
? How would you like to configure ESLint? Answer questions about your style // 以問答的形式建立配置檔案
? Are you using ECMAScript 6 features? Yes // 是否校驗 Es6 語法
? Are you using ES6 modules? Yes // 是否校驗 Es6 模組語法
? Where will your code run? Browser // 程式碼執行環境,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 // 作業系統
? Do you require semicolons? Yes // 每行程式碼結尾是否校驗加分號 ;
? What format do you want your config file to be in? JavaScript // 以 .js 格式生成配置檔案
Installing eslint-plugin-react@latest // 因為要校驗 Reac 語法,所以這裡需要下載一個 React 語法規則的包
建立完成後根目錄下應該會出現 .eslintrc.js
檔案
建立 index.js 檔案
在根目錄下建立 src/index.js 檔案,內容如下,接下來就使用 Eslint 來檢驗這個 .js 檔案是否符合編碼規範。
const lint = 'eslint'
此時的目錄結構應該為:
- 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個字元,報錯編碼規則為
no-unused-vars
:變數 lint 只定義了,但是未使用; - index.js 第1行第14個字元,報錯編碼規則為
quotes
:編碼規範字符串只能使用雙引號,這裡卻使用了單引號; - index.js 第1行第22個字元,報錯編碼規則為
semi
:編碼規範每行程式碼結尾必須加分號,這裡沒有加分號。
當我們熟悉了編碼規範之後,只需進行響應的修改就可以使程式碼形成統一的風格。剛開始如果對編碼規範具體某一條規則不瞭解的話,可以在 eslint規則表 檢視用法。(不建議去背規則表,而是用到什麼查什麼,把它當成字典來用,不那麼累)
設定 --fix 引數
開啟 package.json 檔案,修改 script 屬性如下:
"scripts": {
"test": "react-scripts test --env=jsdom",
"lint": "eslint src --fix",
"lint:create": "eslint --init"
}
說明:這裡給 "lint": "eslint src --fix",
加上 --fix
引數,是 Eslint 提供的自動修復基礎錯誤的功能。
此時執行 npm run lint
會看到少了兩條報錯資訊,並不是說編碼規範變了,而是 Eslint 自動修復了基礎錯誤,開啟 index.js 檔案,可看到字串自動變成了雙引號,並且程式碼末尾也加上了分號。可惜的是 --fix 只能修復基礎的不影響程式碼邏輯的錯誤,像 no-unused-vars 這種錯誤只能手動修改。
配置檔案講解
按照上述操作,會生成預設 .eslintrc.js
配置檔案,內容如下:
// .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"
]
}
}
該檔案匯出一個物件,物件包含屬性 env
、extends
、parserOptions
、plugins
、rules
五個屬性,作為剛學習 Eslint 的新手,我們總是想要竭盡所能的詳細瞭解每一個屬性是什麼,幹嘛用的,以獲取小小的安全感。
env、parserOptions、plugins
這三個放在一起將是因為你只需要知道它們是幹嘛的:我的程式裡要用到 ES6 、React 、JSX 語法,這幾個屬性就是讓 Eslint 能夠檢驗到這些語法的。其餘的你不需要知道更多的哪怕一丟丟的東東了。
作者在學習之初在這塊浪費了很多時間,官方文件看了很多遍,大多不能理解什麼意思,後來想它既然提供這麼一個自動生成配置檔案的工具,並且是命令列互動的方式,我只需要告訴它我要用 ES6 、React 、JSX 語法,它會自動進行相關配置滿足我的要求即可。
extends
前面一直說檢驗程式碼遵循編碼規範,那到底是什麼規範呢。
值為 "eslint:recommended" 的 extends 屬性啟用一系列核心規則,這些規則是經過前人驗證的最佳實踐(所謂最佳實踐,就是大傢伙都覺得應該遵循的編碼規範),想知道最佳實踐具體有哪些編碼規範,可以在 eslint規則表 中檢視被標記為 √ 的規則項。
如果覺得官方提供的預設規則不好用,可以自定義規則配置檔案,然後釋出成 Npm 包,eslint-config-airbnb 就是別人自定義的編碼規範,使用 npm 安裝後,在我們自己的 .eslintrc.js 中進行配置 "extends": "airbnb",eslint-config 這個字首可以省略不寫,這樣我們就使用了 eslint-config-airbnb 中的規則,而不是官方的規則 "extends":"eslint:recommended" 了。關於如何建立自定義規則配置並共享可以參考: 如何自定義規則配置
關於 "airbnb" 編碼規範說兩句,在接觸到大多數開源專案中,大多數的作者都會使用 "airbnb" 編碼規範而不是 官方的 "extends": "eslint:recommended" 編碼規範。
如果我們覺得 eslint-config-airbnb 規則配置中個別規則並不符合當前專案的要求,可以直接在 .eslintrc.js 配置 rules 屬性,優先順序高於共享規則 airbnb。
rules
配置檔案也生成了,我們怎麼知道我們的系統會遵循什麼規則呢??
在前面的列子中,使用 npm run lint
校驗出了三處錯誤,假如我們的專案中字串就是要使用單引號而不是雙引號,程式碼結尾就是要不加分號才好看,變數就是定義了可能不會使用,我們可以通過設定 rules 來定義我們自己的編碼規範,即規則。
ESLint 附帶有大量的規則,修改規則應遵循如下要求:
- "off" 或 0 - 關閉規則
- "warn" 或 1 - 開啟規則,使用警告級別的錯誤:warn (不會導致程式退出)
- "error" 或 2 - 開啟規則,使用錯誤級別的錯誤:error (當被觸發的時候,程式會退出)
有的規則沒有屬性,只需控制是開啟還是關閉,像這樣:"eqeqeq": "off",有的規則有自己的屬性,使用起來像這樣:"quotes": ["error", "double"],具體有沒有自帶屬性,可檢視 eslint規則表。
修改 .eslintrc.js 檔案中的 rules 屬性:
"rules": {
"indent": [
"error",
"tab"
],
"linebreak-style": [
"error",
"windows"
],
"quotes": [
"error",
"single" // 改成字串必須由單引號括起來而不是雙引號,'string'不報錯,"string"報錯
],
"semi": [
"error",
"never" // 改成程式碼結尾不再加分號,加了分號報錯,不加分號不報錯
],
"no-unused-vars": 0 // 0 相當於 off,表示關閉規則,相當於不再校驗這條規則:變數定義了必須使用
}
此時再使用 npm run lint
進行程式碼校驗,沒有報錯就說明校驗通過,程式碼符合統一編碼規範。
D:\code\test\20170811>npm run lint
> [email protected] lint D:\code\test\20170811
> eslint src
D:\code\test\20170811>
可能存在的疑問
剛接觸 ESlint ,並不清楚有哪些規則怎麼辦,要去 eslint規則表 一條條記憶嗎?答案是 no。
個人認為 ESlint 的配置檔案並不是一次性完成的,而是在專案過程中慢慢完善的。你可以放心大膽的先進行編碼,然後使用 npm run lint
校驗程式碼的編碼規範,如果這時候報錯,可以在報錯資訊中知道是哪一條編碼規範報錯了,你可能並不認識它們,此時去 eslint規則表 查詢相應規則的使用方法,如:no-unused-vars
,從而進一步確定專案中是否需要這條編碼規範,如果需要,進行區域性調整即可。
$ 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 中進行相應配置。
{
"rules": {
// ...
},
"globals": {
"window": true
}
}
單行跳過 lint 校驗
在實際編碼時,可能會出現以下的程式碼。
const apple = "apple";
const balana = "balana";
module.exports = {
fruit: balana ;
}
在最上面定義了兩個變數,在底部的配置檔案中只可能用到其中一個變數,另一個用不到的在 eslint 校驗時就會報錯 no-unused-vars
的錯誤,意思是變數定義了但是沒有被用到。
其中一種解決方案是在 .eslintrc 檔案中配置 rules no-unused-vars: 0
,意思是專案中不檢驗變數定義未使用這條規則。強烈不建議這樣做,這個規則十分有用,可以規避編寫程式碼時遺漏的變數。
另一種解決方案就是使用行內註釋跳過對 apple 和 balana 兩個變數跳過 eslint 校驗,隻影響這兩個變數,不影響外部。
const apple = "apple"; // eslint-disable-line
const balana = "balana"; // eslint-disable-line
module.exports = {
fruit: balana ;
}
此時使用 eslint 校驗時就不會再報錯了。
常見規則含義解釋
object-shorthand
設定該規則,表示物件屬性要簡寫。
var foo = {x: x}; // 會報錯
var bar = {a: function () {}}; // 會報錯
var foo = {x}; // 不會報錯
var bar = {a () {}}; // 不會報錯
prefer-arrow-callback
要求回撥函式使用箭頭函式
// 回撥函式,函式的引數是個函式,這個引數函式就是回撥函式
funciton bar () {} // 不是回撥函式,不會報錯
// setTimeout 的第一個引數就是回撥函式,不用箭頭函式會報錯
setTimeout(() => {
// .......
}, 1000)
no-param-reassign
禁止對函式的引數重新賦值
function bar ({ data = {} }) {
data.num = 12; // 會報錯
}
/*
雖然報錯,又不想要將該校驗關閉,如果程式碼中只有 data 這個屬性有這種情形,
可以在 .eslintrc.js 中的 rules 屬性中新增配置(可忽略 data 屬性做此校驗):
'no-param-reassign': ['error', { 'props': true, 'ignorePropertyModificationsFor': ['data'] }],
'no-param-reassign': 0, // 關閉該屬性校驗
*/
no-trailing-spaces
禁止行尾空格no-shadow
禁止變數宣告與外層作用域的變數同名
function sum (num) {
let num = 2; // 報錯,因為 num 變數作為引數已經申明過了
}
常用的幾個規則
"quotes": [1, "single"], # 單引號
"quote-props":[2, "as-needed"], # 雙引號自動變單引號
"semi": [2, "never"], # 一行結尾不要寫分號
"comma-dangle": [1,"always-multiline"] # 物件或陣列多行寫法時,最後一個值加逗號
引用參考原文
連結:https://www.jianshu.com/p/ad1e46faaea2