React-Native (JavaScript)代碼規(guī)范及檢測(cè)工具概述

在RN工程中,使用ESLint進(jìn)行代碼規(guī)范掃描。

Why-- 為什么需要代碼規(guī)范

JavaScript的應(yīng)用場(chǎng)景由最初的用在Web頁(yè)面中實(shí)現(xiàn)一些簡(jiǎn)單交互,發(fā)展到處理復(fù)雜的網(wǎng)站功能交互等,甚至通過(guò)NodeJS來(lái)跑在服務(wù)端。應(yīng)用的場(chǎng)景越來(lái)越多,越來(lái)越復(fù)雜,需要應(yīng)對(duì)不同的運(yùn)行的環(huán)境等,對(duì)代碼的穩(wěn)定性和兼容性要求越來(lái)越高。

加上JavaScript語(yǔ)言本身存在一些設(shè)計(jì)缺陷,例如既是優(yōu)點(diǎn)又是缺陷的弱類型特性、例如var變量的作用域問(wèn)題等等,這些特性會(huì)帶來(lái)非常多的安全隱患。代碼不嚴(yán)謹(jǐn)可能就會(huì)觸發(fā)一些神奇的錯(cuò)誤甚至一些低級(jí)錯(cuò)誤,這些錯(cuò)誤往往在編譯期間很難發(fā)現(xiàn),通常只有在運(yùn)行期間才會(huì)暴露出來(lái),這樣很容易把問(wèn)題帶到線上,導(dǎo)致面臨巨大的風(fēng)險(xiǎn)。以上問(wèn)題,需要通過(guò)一套代碼規(guī)范機(jī)制來(lái)約束代碼風(fēng)格、盡量避免低級(jí)錯(cuò)誤的產(chǎn)生。

同時(shí)在企業(yè)的項(xiàng)目開發(fā)中,制定一套完善有效的編碼規(guī)范也是極為必要的。好的編碼習(xí)慣,規(guī)范的代碼風(fēng)格對(duì)于降低團(tuán)隊(duì)成員開發(fā)時(shí)的溝通成本、提升codeReview效率、提高代碼質(zhì)量、提升系統(tǒng)穩(wěn)定性等都是有巨大好處的。

在前端開發(fā)中有一些輔助工具來(lái)解決這個(gè)問(wèn)題,例如JSLint、JSHint、ESLint等,其中現(xiàn)在比較流行且對(duì)JS新特性兼容比較好的是ESLint。這套機(jī)制同樣適用于React Native的開發(fā).

What-- 規(guī)則、自動(dòng)檢測(cè)工具(ESLint)

規(guī)則

工程目錄結(jié)構(gòu)

以下目錄結(jié)構(gòu)示例中只展示js與靜態(tài)資源,不包含原生代碼。

├── index.ios.js
├── index.android.js
└── js
    ├── component           可復(fù)用的組件(非完整頁(yè)面)
    ├── page                完整頁(yè)面
    ├── config              配置項(xiàng)(常量、接口地址、路由、多語(yǔ)言化等預(yù)置數(shù)據(jù))
    ├── util                工具類(非UI組件)
    ├── style               全局樣式
    └── image               圖片

在component和page目錄中,可能還有一些內(nèi)聚度較高的模塊再建目錄

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              

代碼風(fēng)格、規(guī)范

JavaScript基礎(chǔ)語(yǔ)法部分的代碼規(guī)范

ESLint內(nèi)置的一套代碼規(guī)范(eslint:recommended):https://cn.eslint.org/docs/rules/

前端比較流行的一套代碼規(guī)范:Airbnb JavaScript Style Guide

React/JSX 相關(guān)的代碼規(guī)范

Airbnb React/JSX 風(fēng)格指南:https://github.com/lin-123/javascript/tree/cn/react

自動(dòng)檢測(cè)工具

JSLint、JSHint、ESLint對(duì)比

JSLint

2002 年,Douglas Crockford 開發(fā)了可能是第一款針對(duì) JavaScript 的語(yǔ)法檢測(cè)工具 —— JSLint,并于 2010 年開源。

JSLint 面市后,確實(shí)幫助許多 JavaScript 開發(fā)者節(jié)省了不少排查代碼錯(cuò)誤的時(shí)間。
但是 JSLint 的問(wèn)題也很明顯:

  • 幾乎不可配置,所有的代碼風(fēng)格和規(guī)則都是內(nèi)置好的;
  • 再加上 JSLint 作者冷處理方式,不會(huì)向開發(fā)者妥協(xié)開放配置或者修改他覺(jué)得是對(duì)的規(guī)則。
JSHint

于是 Anton Kovalyov 吐槽:「JSLint 是讓你的代碼風(fēng)格更像 Douglas Crockford 的而已」,并且在 2011 年 Fork 原項(xiàng)目開發(fā)了 JSHint。

JSHint 的特點(diǎn)就是:

  • 可配置,
  • 同時(shí)文檔也相對(duì)完善,
  • 而且對(duì)開發(fā)者友好。

很快大家就從 JSLint 轉(zhuǎn)向了 JSHint。

ESLint
ESLint 的誕生

起初幾年,JSHint 一直是前端代碼檢測(cè)工具的首選,包括 Nicholas C. Zakas 也是 JSHint 的用戶。但在 2013 年,Zakas 大佬發(fā)現(xiàn) JSHint 已經(jīng)無(wú)法滿足自己定制化規(guī)則的需求,而且和 Anton 討論后達(dá)成共識(shí)這根本在不可能在 JSHint 上實(shí)現(xiàn)。同時(shí) Zakas 還設(shè)想發(fā)明一個(gè)基于 AST 的 lint,可以動(dòng)態(tài)執(zhí)行額外的規(guī)則,同時(shí)可以很方便的擴(kuò)展規(guī)則。

2013 年的 6 月份,Zakas 發(fā)布了全新的 lint 工具——ESLint。

ESLint的特點(diǎn):

  • 可擴(kuò)展
  • 每條規(guī)則獨(dú)立
  • 可自定義規(guī)則

ESlint有一些內(nèi)置的規(guī)則讓你更容易上手,同時(shí)你可以隨時(shí)加載自己的規(guī)則。

發(fā)展&契機(jī)

ESLint 的出現(xiàn)并沒(méi)有撼動(dòng) JSHint 的霸主地位。由于前者是利用 AST 處理規(guī)則,用 Esprima 解析代碼,執(zhí)行速度要比只需要一步搞定的 JSHint 慢很多;其次當(dāng)時(shí)已經(jīng)有許多編輯器對(duì) JSHint 支持完善,生態(tài)足夠強(qiáng)大。真正讓 ESLint 逆襲的是 ECMAScript 6 的出現(xiàn)。

ES2015

2015 年 6 月,ES2015 規(guī)范正式發(fā)布。但是發(fā)布后,市面上瀏覽器對(duì)最新標(biāo)準(zhǔn)的支持情況極其有限。如果想要提前體驗(yàn)最新標(biāo)準(zhǔn)的語(yǔ)法,就得靠 Babel 之類的工具將代碼編譯成 ES5 甚至更低的版本,同時(shí)一些實(shí)驗(yàn)性的特性也能靠 Babel 轉(zhuǎn)換。這時(shí) JSHint 就略尷尬,ES2015 變化很大,短期內(nèi)無(wú)法完全支持。ESLint 可擴(kuò)展的優(yōu)勢(shì)一下就體現(xiàn)出來(lái)了,不僅可以擴(kuò)展規(guī)則,甚至連解析器也能替換。Babel 團(tuán)隊(duì)就為 ESLint 開發(fā)了 babel-eslint 替換默認(rèn)解析器,讓 ESLint 率先支持 ES2015 語(yǔ)法。

React&JSX

也是在 2015 年,React 的應(yīng)用越來(lái)越廣泛,誕生不久的 JSX 也愈加流行。ESLint 本身也不支持 JSX 語(yǔ)法。還是因?yàn)榭蓴U(kuò)展性,eslint-plugin-react[10] 的出現(xiàn)讓 ESLint 也能支持當(dāng)時(shí) React 特有的規(guī)則。

至此,ESLint 完美躺贏,替代 JSHint 成為前端主流工具

How--在RN項(xiàng)目中如何利用ESLint實(shí)現(xiàn)高效的代碼規(guī)范校驗(yàn)

ESLint的安裝

你可以使用 npm 安裝 ESLint,在JS工程的根目錄下執(zhí)行:

$ npm install eslint --save-dev

緊接著你應(yīng)該設(shè)置一個(gè)配置文件(初始化):

$ ./node_modules/.bin/eslint --init

之后,你可以在任何文件或目錄上運(yùn)行ESLint如下:

$ ./node_modules/.bin/eslint yourfile.js

也可以在全局而不是本地安裝 ESLint (使用 npm install eslint --global)。但是,你使用的任何插件或可共享配置都必須安裝在本地。

ESLint的配置

運(yùn)行 eslint --init 之后,.eslintrc 文件會(huì)在你的文件夾中自動(dòng)創(chuàng)建(文件格式可以是“.js”、“.json”等)。例如一個(gè).eslintrc.json文件內(nèi)容如下:

{
    "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支持替換默認(rèn)解析器。當(dāng)代碼中用到了一些比較新的語(yǔ)法特性(例如需要Babel轉(zhuǎn)換的一些新特性或?qū)嶒?yàn)特性)時(shí),就需要使用一些其他的解析器,例如babel-eslint。

當(dāng)然使用的前提是先在本地安裝對(duì)應(yīng)的解析器,例如:

npm install eslint babel-eslint --save-dev

安裝后在配置文件中,設(shè)置對(duì)應(yīng)的parser字段為自定義的解析器。(這里設(shè)置的為babel-eslint)

"parser": "babel-eslint",

extends:繼承

    "extends": [
        "eslint:recommended",
        "plugin:react/recommended",
        "airbnb",
        "plugin:react-native/all",
        "plugin:flowtype/recommended"
    ],

可以繼承一些現(xiàn)有的規(guī)則配置(規(guī)則集合),例如ESLint內(nèi)置的推薦規(guī)則集(eslint:recommended),還有一些流行的第三方配置(例如:airbnb)或者第三方插件中的配置(例如:plugin:react/recommended)等。

  • 可以指定繼承多個(gè)配置
  • 繼承的配置可以是內(nèi)置配置,例如:"eslint:recommended"
  • 可以是第三方配置包中的配置(例如eslint-config-airbnb),可以省略包名的前綴 eslint-config-,例如:"airbnb"
  • 也可以是第三方插件中的配置, extends 屬性值可以由以下組成:(例如"plugin:react/recommended")
    • plugin:
    • 包名 (省略了前綴,比如,react)
    • /
    • 配置名稱 (比如 recommended)
  • 繼承按順序依次繼承,如果有相同規(guī)則的設(shè)置,后面的會(huì)覆蓋前面的

plugins:插件

ESLint 支持使用第三方插件。在使用插件之前,你必須使用 npm 安裝它。

在配置文件里配置插件時(shí),可以使用 plugins 關(guān)鍵字來(lái)存放插件名字的列表。插件名稱可以省略 eslint-plugin- 前綴。

注意:插件是相對(duì)于 ESLint 進(jìn)程的當(dāng)前工作目錄解析的。換句話說(shuō),ESLint 將加載與用戶通過(guò)從項(xiàng)目 Node 交互解釋器運(yùn)行 ('eslint-plugin-pluginname') 獲得的相同的插件。

當(dāng)你需要自定義一些ESLint沒(méi)有提供規(guī)則的時(shí)候就需要用的插件,可以通過(guò)自定義或者使用別人開發(fā)好的插件來(lái)加入一些新的代碼規(guī)則。

配置包(eslint-config-) VS 插件(eslint-plugin-)
相同點(diǎn)
  • 都是 npm 包
  • 都可以共享,通過(guò)npm可以安裝別人分享的包
  • 都可以對(duì)ESLint默認(rèn)的規(guī)則進(jìn)行設(shè)置
  • 都可以提供規(guī)則集(配置)
不同點(diǎn)
  • 配置包(eslint-config-),只是對(duì)已有規(guī)則的修改、聚合等
  • 插件(eslint-plugin-),也可以提供配置,同時(shí)可以新增自定義規(guī)則

rules:規(guī)則

可以在rules中添加一些額外的規(guī)則(除extends繼承的配置中啟用的),或者對(duì)extends引入的規(guī)則進(jìn)行二次定制。

  • 規(guī)則啟用狀態(tài)設(shè)置:要改變一個(gè)規(guī)則設(shè)置,你必須將規(guī)則 ID 設(shè)置為下列值之一:

    • "off" 或 0 - 關(guān)閉規(guī)則
    • "warn" 或 1 - 開啟規(guī)則,使用警告級(jí)別的錯(cuò)誤:warn (不會(huì)導(dǎo)致程序退出)
    • "error" 或 2 - 開啟規(guī)則,使用錯(cuò)誤級(jí)別的錯(cuò)誤:error (當(dāng)被觸發(fā)的時(shí)候,程序會(huì)退出)
  • 額外選項(xiàng)設(shè)置:如果一個(gè)規(guī)則有額外的選項(xiàng),你可以使用數(shù)組字面量指定它們,比如:

    {
        "rules": {
            "quotes": ["error", "double"]
        }
    }
    

"quotes": ["error", "double"] 為規(guī)則 quotes 指定了 “double”選項(xiàng)(雙引號(hào))。數(shù)組的第一項(xiàng)總是規(guī)則的嚴(yán)重程度(數(shù)字或字符串)。

  • 配置定義在插件中的一個(gè)規(guī)則的時(shí)候,你必須使用 插件名/規(guī)則ID 的形式。比如:

    "rules": {
            "react/jsx-filename-extension": "off",
            "react/jsx-indent": "off"
     }
    

    注意:當(dāng)指定來(lái)自插件的規(guī)則時(shí),確保刪除 eslint-plugin- 前綴。ESLint 在內(nèi)部只使用沒(méi)有前綴的名稱去定位規(guī)則。

ESLint與開發(fā)環(huán)境(工具)集成

WebStorm

  1. 進(jìn)入ESLint設(shè)置:Preferences -> Languages & Frameworks -> JavaScript-> Code Quality Tools -> ESLint
  2. 選擇 Menual ESlint configuration
  3. ESlint package 設(shè)置為全局路徑(如果是本地安裝,選擇本地路徑):/usr/local/lib/node_modules/eslint
  4. Configuration file 路徑手動(dòng)設(shè)置為項(xiàng)目 eslint 配置文件的路徑,例如:/Users/xxx/Documents/work_6/JD_Recharge/RN_Recharge/jdreact-jsbundle-jdreactrechargemodule/.eslintrc.json
webstorm設(shè)置

設(shè)置好以后,WebStorm就會(huì)自動(dòng)檢測(cè)工程中的代碼,并會(huì)在發(fā)現(xiàn)的錯(cuò)誤(或不符合規(guī)范)處進(jìn)行波浪線標(biāo)注,例如:

Tips

1.sourceType 是什么意思?

sourceType 有兩個(gè)值,script 和 module。 對(duì)于 ES6+ 的語(yǔ)法和用 import / export 的語(yǔ)法必須用 module.

2. eslint --init

只有在選擇 "To check syntax, find problems, and enforce code style" 才可以選擇 airbnb, standard, recommended 標(biāo)準(zhǔn)。

3. 環(huán)境

有時(shí)候在前端項(xiàng)目中存在前端和 node 的代碼共存的情況,只要在 env 中配置好 browser: true, node: true 就可以把兼容不同環(huán)境的全局變量兼容進(jìn)來(lái),例如 nodejs 中的 global, process 等等。

4. 常見規(guī)則強(qiáng)度

規(guī)則強(qiáng)度是 airbnb > standard > recommended. 看下圖,

recommended 和 standard 大概有 88 出不同,主要是 recommended 很多都是 off, standard 是 error, 同時(shí) standard 還有很多特有的規(guī)則。

左邊是 recommended, 右邊是 standard
standard 特有的規(guī)則

5. 關(guān)于自動(dòng)修復(fù)

現(xiàn)在代碼都比較嚴(yán)格,可能包含縮進(jìn)是 2 個(gè)空格,是否在語(yǔ)句最后加逗號(hào)的情況。不可能自己手動(dòng)去一個(gè)個(gè)修正。

eslint ./src --fix 

加上 --fix 可以自動(dòng)修正一些明顯的問(wèn)題。

參考:

前端工具考 - ESLint 篇:ESLint的誕生和發(fā)展

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容