在RN工程中,使用ESLint進行代碼規范掃描。
Why-- 為什么需要代碼規范
JavaScript的應用場景由最初的用在Web頁面中實現一些簡單交互,發展到處理復雜的網站功能交互等,甚至通過NodeJS來跑在服務端。應用的場景越來越多,越來越復雜,需要應對不同的運行的環境等,對代碼的穩定性和兼容性要求越來越高。
加上JavaScript語言本身存在一些設計缺陷,例如既是優點又是缺陷的弱類型特性、例如var變量的作用域問題等等,這些特性會帶來非常多的安全隱患。代碼不嚴謹可能就會觸發一些神奇的錯誤甚至一些低級錯誤,這些錯誤往往在編譯期間很難發現,通常只有在運行期間才會暴露出來,這樣很容易把問題帶到線上,導致面臨巨大的風險。以上問題,需要通過一套代碼規范機制來約束代碼風格、盡量避免低級錯誤的產生。
同時在企業的項目開發中,制定一套完善有效的編碼規范也是極為必要的。好的編碼習慣,規范的代碼風格對于降低團隊成員開發時的溝通成本、提升codeReview效率、提高代碼質量、提升系統穩定性等都是有巨大好處的。
在前端開發中有一些輔助工具來解決這個問題,例如JSLint、JSHint、ESLint等,其中現在比較流行且對JS新特性兼容比較好的是ESLint。這套機制同樣適用于React Native的開發.
What-- 規則、自動檢測工具(ESLint)
規則
工程目錄結構
以下目錄結構示例中只展示js與靜態資源,不包含原生代碼。
├── index.ios.js
├── index.android.js
└── js
├── component 可復用的組件(非完整頁面)
├── page 完整頁面
├── config 配置項(常量、接口地址、路由、多語言化等預置數據)
├── util 工具類(非UI組件)
├── style 全局樣式
└── image 圖片
在component和page目錄中,可能還有一些內聚度較高的模塊再建目錄
page/component
├── HomeView.component.js
├── HomeView.style.js
└── MovieView
├── MovieList.component.js
├── MovieList.style.js
├── MovieCell.component.js
├── MovieCell.style.js
├── MovieView.component.js
└── MovieView.style.js
代碼風格、規范
JavaScript基礎語法部分的代碼規范
ESLint內置的一套代碼規范(eslint:recommended):https://cn.eslint.org/docs/rules/
前端比較流行的一套代碼規范:Airbnb JavaScript Style Guide
React/JSX 相關的代碼規范
Airbnb React/JSX 風格指南:https://github.com/lin-123/javascript/tree/cn/react
自動檢測工具
JSLint、JSHint、ESLint對比
JSLint
2002 年,Douglas Crockford 開發了可能是第一款針對 JavaScript 的語法檢測工具 —— JSLint,并于 2010 年開源。
JSLint 面市后,確實幫助許多 JavaScript 開發者節省了不少排查代碼錯誤的時間。
但是 JSLint 的問題也很明顯:
- 幾乎不可配置,所有的代碼風格和規則都是內置好的;
- 再加上 JSLint 作者冷處理方式,不會向開發者妥協開放配置或者修改他覺得是對的規則。
JSHint
于是 Anton Kovalyov 吐槽:「JSLint 是讓你的代碼風格更像 Douglas Crockford 的而已」,并且在 2011 年 Fork 原項目開發了 JSHint。
JSHint 的特點就是:
- 可配置,
- 同時文檔也相對完善,
- 而且對開發者友好。
很快大家就從 JSLint 轉向了 JSHint。
ESLint
ESLint 的誕生
起初幾年,JSHint 一直是前端代碼檢測工具的首選,包括 Nicholas C. Zakas 也是 JSHint 的用戶。但在 2013 年,Zakas 大佬發現 JSHint 已經無法滿足自己定制化規則的需求,而且和 Anton 討論后達成共識這根本在不可能在 JSHint 上實現。同時 Zakas 還設想發明一個基于 AST 的 lint,可以動態執行額外的規則,同時可以很方便的擴展規則。
2013 年的 6 月份,Zakas 發布了全新的 lint 工具——ESLint。
ESLint的特點:
- 可擴展
- 每條規則獨立
- 可自定義規則
ESlint有一些內置的規則讓你更容易上手,同時你可以隨時加載自己的規則。
發展&契機
ESLint 的出現并沒有撼動 JSHint 的霸主地位。由于前者是利用 AST 處理規則,用 Esprima 解析代碼,執行速度要比只需要一步搞定的 JSHint 慢很多;其次當時已經有許多編輯器對 JSHint 支持完善,生態足夠強大。真正讓 ESLint 逆襲的是 ECMAScript 6 的出現。
ES2015
2015 年 6 月,ES2015 規范正式發布。但是發布后,市面上瀏覽器對最新標準的支持情況極其有限。如果想要提前體驗最新標準的語法,就得靠 Babel 之類的工具將代碼編譯成 ES5 甚至更低的版本,同時一些實驗性的特性也能靠 Babel 轉換。這時 JSHint 就略尷尬,ES2015 變化很大,短期內無法完全支持。ESLint 可擴展的優勢一下就體現出來了,不僅可以擴展規則,甚至連解析器也能替換。Babel 團隊就為 ESLint 開發了 babel-eslint 替換默認解析器,讓 ESLint 率先支持 ES2015 語法。
React&JSX
也是在 2015 年,React 的應用越來越廣泛,誕生不久的 JSX 也愈加流行。ESLint 本身也不支持 JSX 語法。還是因為可擴展性,eslint-plugin-react[10] 的出現讓 ESLint 也能支持當時 React 特有的規則。
至此,ESLint 完美躺贏,替代 JSHint 成為前端主流工具
How--在RN項目中如何利用ESLint實現高效的代碼規范校驗
ESLint的安裝
你可以使用 npm 安裝 ESLint,在JS工程的根目錄下執行:
$ npm install eslint --save-dev
緊接著你應該設置一個配置文件(初始化):
$ ./node_modules/.bin/eslint --init
之后,你可以在任何文件或目錄上運行ESLint如下:
$ ./node_modules/.bin/eslint yourfile.js
也可以在全局而不是本地安裝 ESLint (使用 npm install eslint --global)。但是,你使用的任何插件或可共享配置都必須安裝在本地。
ESLint的配置
運行 eslint --init 之后,.eslintrc 文件會在你的文件夾中自動創建(文件格式可以是“.js”、“.json”等)。例如一個.eslintrc.json文件內容如下:
{
"env": {
"browser": true,
"es6": true,
"react-native/react-native": true
},
"parser": "babel-eslint",
"extends": [
"eslint:recommended",
"airbnb",
"plugin:react-native/all",
"plugin:flowtype/recommended"
],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 6,
"sourceType": "module"
},
"plugins": [
"react",
"react-native",
"flowtype"
],
"rules": {
"react/jsx-filename-extension": "off",
"no-use-before-define": "off",
"react-native/sort-styles": "off",
"arrow-body-style": "off",
"indent": "off",
"react/jsx-indent": "off"
}
}
parser:解析器
如前述,ESLint支持替換默認解析器。當代碼中用到了一些比較新的語法特性(例如需要Babel轉換的一些新特性或實驗特性)時,就需要使用一些其他的解析器,例如babel-eslint。
當然使用的前提是先在本地安裝對應的解析器,例如:
npm install eslint babel-eslint --save-dev
安裝后在配置文件中,設置對應的parser字段為自定義的解析器。(這里設置的為babel-eslint)
"parser": "babel-eslint",
extends:繼承
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"airbnb",
"plugin:react-native/all",
"plugin:flowtype/recommended"
],
可以繼承一些現有的規則配置(規則集合),例如ESLint內置的推薦規則集(eslint:recommended),還有一些流行的第三方配置(例如:airbnb)或者第三方插件中的配置(例如:plugin:react/recommended)等。
- 可以指定繼承多個配置
- 繼承的配置可以是內置配置,例如:"eslint:recommended"
- 可以是第三方配置包中的配置(例如eslint-config-airbnb),可以省略包名的前綴 eslint-config-,例如:"airbnb"
- 也可以是第三方插件中的配置, extends 屬性值可以由以下組成:(例如"plugin:react/recommended")
- plugin:
- 包名 (省略了前綴,比如,react)
- /
- 配置名稱 (比如 recommended)
- 繼承按順序依次繼承,如果有相同規則的設置,后面的會覆蓋前面的
plugins:插件
ESLint 支持使用第三方插件。在使用插件之前,你必須使用 npm 安裝它。
在配置文件里配置插件時,可以使用 plugins 關鍵字來存放插件名字的列表。插件名稱可以省略 eslint-plugin- 前綴。
注意:插件是相對于 ESLint 進程的當前工作目錄解析的。換句話說,ESLint 將加載與用戶通過從項目 Node 交互解釋器運行 ('eslint-plugin-pluginname') 獲得的相同的插件。
當你需要自定義一些ESLint沒有提供規則的時候就需要用的插件,可以通過自定義或者使用別人開發好的插件來加入一些新的代碼規則。
配置包(eslint-config-) VS 插件(eslint-plugin-)
相同點
- 都是 npm 包
- 都可以共享,通過npm可以安裝別人分享的包
- 都可以對ESLint默認的規則進行設置
- 都可以提供規則集(配置)
不同點
- 配置包(eslint-config-),只是對已有規則的修改、聚合等
- 插件(eslint-plugin-),也可以提供配置,同時可以新增自定義規則
rules:規則
可以在rules中添加一些額外的規則(除extends繼承的配置中啟用的),或者對extends引入的規則進行二次定制。
-
規則啟用狀態設置:要改變一個規則設置,你必須將規則 ID 設置為下列值之一:
- "off" 或 0 - 關閉規則
- "warn" 或 1 - 開啟規則,使用警告級別的錯誤:warn (不會導致程序退出)
- "error" 或 2 - 開啟規則,使用錯誤級別的錯誤:error (當被觸發的時候,程序會退出)
-
額外選項設置:如果一個規則有額外的選項,你可以使用數組字面量指定它們,比如:
{ "rules": { "quotes": ["error", "double"] } }
"quotes": ["error", "double"]
為規則 quotes 指定了 “double”選項(雙引號)。數組的第一項總是規則的嚴重程度(數字或字符串)。
-
配置定義在插件中的一個規則的時候,你必須使用 插件名/規則ID 的形式。比如:
"rules": { "react/jsx-filename-extension": "off", "react/jsx-indent": "off" }
注意:當指定來自插件的規則時,確保刪除 eslint-plugin- 前綴。ESLint 在內部只使用沒有前綴的名稱去定位規則。
ESLint與開發環境(工具)集成
WebStorm
- 進入ESLint設置:
Preferences
->Languages & Frameworks
->JavaScript
->Code Quality Tools
->ESLint
- 選擇
Menual ESlint configuration
-
ESlint package
設置為全局路徑(如果是本地安裝,選擇本地路徑):/usr/local/lib/node_modules/eslint
- 將
Configuration file
路徑手動設置為項目 eslint 配置文件的路徑,例如:/Users/xxx/Documents/work_6/JD_Recharge/RN_Recharge/jdreact-jsbundle-jdreactrechargemodule/.eslintrc.json
設置好以后,WebStorm就會自動檢測工程中的代碼,并會在發現的錯誤(或不符合規范)處進行波浪線標注,例如:
Tips
1.sourceType 是什么意思?
sourceType 有兩個值,script 和 module。 對于 ES6+ 的語法和用 import / export 的語法必須用 module.
2. eslint --init
只有在選擇 "To check syntax, find problems, and enforce code style" 才可以選擇 airbnb, standard, recommended 標準。
3. 環境
有時候在前端項目中存在前端和 node 的代碼共存的情況,只要在 env 中配置好 browser: true, node: true 就可以把兼容不同環境的全局變量兼容進來,例如 nodejs 中的 global, process 等等。
4. 常見規則強度
規則強度是 airbnb > standard > recommended. 看下圖,
recommended 和 standard 大概有 88 出不同,主要是 recommended 很多都是 off, standard 是 error, 同時 standard 還有很多特有的規則。
5. 關于自動修復
現在代碼都比較嚴格,可能包含縮進是 2 個空格,是否在語句最后加逗號的情況。不可能自己手動去一個個修正。
eslint ./src --fix
加上 --fix 可以自動修正一些明顯的問題。
參考:
前端工具考 - ESLint 篇:ESLint的誕生和發展