React編碼規范及持續集成實踐(EditorConfig+ESLint+Jenkins)

工具

  • EditorConfig
  • ESLint
  • Jenkins

EditorConfig

在編輯時約束代碼風格,在IDE中如:WebStorm格式化時(command+shift+f)將按照配置中的規則進行格式化。官方文檔:https://editorconfig.org/,一份規則示例:

# top-most EditorConfig file
root = true
[*]
Unix-style newlines with a newline ending every file
end_of_line = lf
[*.{js,py}]
# 字符編碼集
charset = utf-8
# 縮進使用 tab 或者 space
indent_style = space
# 縮進為space時縮進字符數
indent_size = 2
# 是否將尾行空格自動刪除
trim_trailing_whitespace = true
# 是否使文件以一個空白行結尾
insert_final_newline = true
# 編碼區字符數(寬度)限定 結合eslint max-len WebStorm支持 VSCode不支持
max_line_length = 100
# 引號樣式 single double auto
quote_type = single
# 花括號是否另起一行
#curly_bracket_next_line = true
# 操作符兩邊是否有空格 true false hybrid
spaces_around_operators = true
# 括號兩邊是否有空格 none inside outside both
#spaces_around_brackets = both

WebStorm默認支持EditorConfig,其它IDE可能需要下載插件支持,WebStorm下導出.editorconfig,Perferences->CodeStyle->EditorConfig如下:


editorconfig.png

ESLint

插件化的javascript代碼檢測工具。官方文檔:https://cn.eslint.org/

安裝ESLint

npm install -g eslint

初始化

eslint -- init
這里我們選擇問答方式生成初始化的eslint配置文件

image.png

選擇完成后ESLint會根據選擇的配置下載相關的插件,如我們選擇使用了React
package.json中就有eslint-plugin-react包,相關依賴下載完成后在項目根目錄下會生成.eslintrc.json(或.eslintrc.js根據你選擇的配置)文件
image.png

  • .eslintrc.json文件
{
    "env": {
        "node": true,
        "browser": true,
        "es6": true
    },
    "parser": "babel-eslint",
    "plugins": [
        "react"
    ],
    "extends": "standard",
    "rules": {
      "react/jsx-uses-vars": 2,
      "camelcase":0
    }
}

文檔配置詳情說明 https://cn.eslint.org/docs/user-guide/configuring

  • parser
"parser": "babel-eslint"

解析器可能的配置有Esprima Babel-ESLint typescript-eslint-parser

  • extends
"extends": "standard"

extends決定了ESLint使用何種配置插件進行代碼檢查,如:

"extends": [
        "eslint:recommended",
        "plugin:react/recommended"
    ],
"plugins": [
        "react"
    ]

就是啟用ESLint推薦規則和React推薦規則,插件eslint-plugin-react及其規則說明,extends其它值可以有:airbnb,eslint:recommended,eslint:all

"extends": "airbnb", // airbnb eslint:recommended standard  eslint:all
npm -i eslint-config-airbnb --save-dev

同時會下載相關依賴插件eslint-plugin-import, eslint-plugin-jsx-a11y,eslint-plugin-react,啟用對React和jsx的一些規則檢查
插件eslint-plugin-import及其規則說明
插件eslint-plugin-react及其規則說明
插件eslint-plugin-jsx-a11y及其規則說明

  • rules
    ESLint 附帶有大量的規則。你可以使用注釋或配置文件修改你項目中要使用的規則。要改變一個規則設置,你必須將規則 ID 設置為下列值之一:
    "off" 或 0 - 關閉規則
    "warn" 或 1 - 開啟規則,使用警告級別的錯誤:warn (不會導致程序退出)
    "error" 或 2 - 開啟規則,使用錯誤級別的錯誤:error (當被觸發的時候,程序會退出)
    如下一個簡單示例:
"rules": {
      "quotes": [
            "error",
            "single"
        ], //強制單引號
      "camelcase":2 //強制駝峰
    }

命令行執行檢查掃描

由于ESLint我是本地安裝的(--save-dev)需要切換到node_modules目錄下執行,目錄結構(React-Native項目)

image.png

node_modules/.bin/eslint src index.js

掃描src目錄以及根目錄下的index.js文件,掃描結算后我們在命令行會看到如下結果:

image.png

Jenkins

在命令行中生成的結果,不方便定位與查看,這里通過Jekins做持續集成對項目進行規范化管理。

  • package.json
    編輯package.json增加lint命令支持
"scripts": {
    "lint": "node_modules/.bin/eslint --ext .js src index.js -c .eslintrc.json -f checkstyle > eslint.xml",
    "start": "node node_modules/react-native/local-cli/cli.js start"
  }

--ext .js src index.js 表示掃描/src目錄下擴展名為.js的文件 以及根目錄下的index.js文件
-c .eslintrc.json 表示選擇根目錄下的.eslintrc.json文件作為掃描的配置文件
-f checkstyle >eslint.xml將掃描結果以checkstyle方式輸出報告,輸出到根目錄下的eslint.xml
eslint命令詳情-官方文檔

  • 配置工程與選擇分支


    image.png
  • 配置submodule
    由于node_modules以sub-modules添加到了工程源碼庫管理,需要拉取子module


    image.png
  • 添加構建腳本


    image.png

    切換到library(node_modules)目錄拉取目標分支最新代碼,再切換回根目錄執行lint命令。

  • 添加構建后步驟
    將構建結果以Checkstyle results的形式輸出,選擇CheckStyle需要Jenkins插件支持。


    image.png
  • 查看結果
    image.png

    查看整個項目的掃描結果,根據需要瀏覽具體代碼,選擇或者禁用某些規則,然后重新編輯.eslintrc.json文件生成一份適用于自己團隊的規則文件。

eslint配置示例(基于airbnb規范)

  • array-bracket-spacing 強制數組方括號中使用一致的空格 2
  • array-callback-return 強制數組方法的回調函數中有 return 語句 0
  • arrow-body-style 要求箭頭函數體使用大括號 1
  • arrow-parens 要求箭頭函數的參數使用圓括號 0
  • brace-style 強制在代碼塊中使用一致的大括號風格 2
  • camelcase 強制使用駱駝拼寫法命名約定 2
  • class-methods-use-this 強制類方法使用 this 1
  • comma-dangle 要求或禁止末尾逗號
"comma-dangle": [1, {
            "objects": "always",
            "imports": "never",
            "arrays": "never",
            "exports": "never",
            "functions": "never"
    }]
  • consistent-return要求 return 語句要么總是指定返回的值,要么不指定 2
  • default-case要求 switch 語句中有 default 分支 0
  • dot-notation 強制盡可能地使用點號 2
  • eol-last 要求或禁止文件末尾存在空行 2
  • eqeqeq 要求使用 === 和 !== 2
  • func-names 要求或禁止使用命名的 function 表達式 2
  • function-paren-newline 強制在函數括號內使用一致的換行 2
  • global-require 要求 require() 出現在頂層模塊作用域中 0
  • guard-for-in 要求 for-in 循環中有一個 if 語句 1
  • import/first 將全部import寫在模塊開始的位置 0
  • import/newline-after-import improt結束后應有空行 2
  • import/no-duplicates 禁止重復導入相同文件 2
  • import/no-extraneous-dependencies 禁止導入未在包中聲明的外部模塊 2
  • import/no-mutable-exports 可導出對象禁止用let或者var修飾 ->const 2
  • import/no-unresolved 確保導入的模塊可以被解析為本地文件系統上的模塊 0
  • import/prefer-default-export 當從模塊中只導出單個出口時使用默認導出 1
  • indent 縮進風格
"indent": [
            "error",
            2,
            {"SwitchCase": 1} // set 1 -> 2 spaces; set 2 -> 4 spaces
    ]
  • jsx-quotes 強制在 JSX 屬性中一致地使用雙引號或單引號 2 prefer-single
  • linebreak-style 強制使用一致的換行風格 2 lf
"linebreak-style": [
            "error",
            "unix"
    ]
  • max-len 強制一行的最大長度 100 1
"max-len": [
            "warn",
            100
    ]
  • newline-per-chained-call 要求方法鏈中每個調用都有一個換行符 2
  • no-bitwise 禁用按位運算符 1
  • no-case-declarations 不允許在 case 子句中使用詞法聲明 2
  • no-confusing-arrow 禁止在可能與比較操作符相混淆的地方使用箭頭函數 2
  • no-continue 禁用 continue 語句 1
  • no-else-return 禁止 if 語句中 return 語句之后有 else 塊 2
  • no-empty 禁止出現空語句塊 2
  • no-extend-native 禁止擴展原生類型 2 exceptions Date
"no-extend-native": [
            "error",
            {"exceptions": ["Date"]}
    ]
  • no-extra-semi 禁止不必要的分號 2
  • no-lonely-if 禁止 if 作為唯一的語句出現在 else 語句中 2
  • no-loop-func 禁止在循環中出現 function 聲明和表達式 1
  • no-mixed-operators 禁止混合使用不同的操作符 0
  • no-mixed-spaces-and-tabs 禁止空格和 tab 的混合縮進 2
  • no-multi-assign 禁止連續賦值 2
  • no-nested-ternary 禁用嵌套的三元表達式 2
  • no-param-reassign 禁止對 function 的參數進行重新賦值 2
  • no-plusplus 禁用一元操作符 ++ 和 -- 0
  • no-prototype-builtins 禁止直接調用 Object.prototypes 的內置屬性 2
  • no-restricted-globals 禁用特定的全局變量 2
  • no-restricted-properties 禁止使用對象的某些屬性 1
  • no-restricted-syntax 禁用特定的語法 使用for-each map for-i 2
  • no-shadow 禁止變量聲明與外層作用域的變量同名 2
  • no-tabs 禁用 tab 2
  • no-trailing-spaces 禁用行尾空格 2
  • no-undef 禁用未聲明的變量,除非它們在 /*global */ 注釋中被提到 2
  • no-underscore-dangle 禁止標識符中有懸空下劃線 0
  • no-unreachable 禁止在return、throw、continue 和 break 語句之后出現不可達代碼 2
  • no-unused-expressions 禁止出現未使用過的表達式 2 allowShortCircuit true
"no-unused-expressions": ["error", {"allowShortCircuit": true}]
  • no-unused-vars 禁止出現未使用過的變量 2
  • no-use-before-define 禁止在變量定義之前使用它們 2
  • no-useless-concat 禁止不必要的字符串字面量或模板字面量的連接 0
  • no-useless-constructor 禁用不必要的構造函數 2
  • no-useless-escape 禁用不必要的轉義字符 0
  • no-var 要求使用 let 或 const 而不是 var 2
  • object-curly-newline 強制大括號內換行符的一致性 2
  • object-curly-spacing 強制在大括號中使用一致的空格 2
  • object-shorthand 要求或禁止對象字面量中方法和屬性使用簡寫語法 2
  • one-var 強制函數中的變量要么一起聲明要么分開聲明 0
  • one-var-declaration-per-line 要求或禁止在變量聲明周圍換行 0
  • operator-assignment 要求或禁止在可能的情況下使用簡化的賦值操作符 1
  • padded-blocks 要求或禁止塊內填充 2 class always
"padded-blocks": [
            "error", {"classes": "always"}
    ]
  • prefer-arrow-callback 要求回調函數使用箭頭函數 2
  • prefer-const 要求使用 const 聲明那些聲明后不再被修改的變量 2
  • prefer-destructuring 優先使用數組和對象解構 2 object
"prefer-destructuring": [
            "error", {"array": false, "object": true}
    ]
  • prefer-rest-params 要求使用剩余參數而不是 arguments 2
  • prefer-spread 要求使用擴展運算符而非 .apply() 2
  • prefer-template 要求使用模板字面量而非字符串連接 2
  • quote-props 要求對象字面量屬性名稱用引號括起來 2
  • quotes 強制使用一致的反勾號、雙引號或單引號 2
"quotes": [
            "error",
            "single"
    ]
  • radix 強制在parseInt()使用基數參數 0
  • react/forbid-prop-types 禁止某些propTypes 1
  • react/jsx-boolean-value 在JSX中強制布爾屬性符號 2
  • react/jsx-closing-bracket-location 在JSX中驗證右括號位置 1
  • react/jsx-closing-tag-location 在JSX中驗證右標簽位置 2
  • react/jsx-curly-brace-presence 在JSX中啟用或者禁用不必要的大括號 props always children never
"react/jsx-curly-brace-presence": [
            "error",
            {"props": "always", "children": "never"}
    ]
  • react/jsx-curly-spacing 在JSX屬性和表達式中加強或禁止大括號內的空格 禁止 2
  • react/jsx-equals-spacing 在JSX屬性中強制或禁止等號周圍的空格 禁止 2
  • react/jsx-filename-extension 限制包含JSX的文件擴展名 0
  • react/jsx-first-prop-new-line 屬性強制換行 2
  • react/jsx-indent jsx中縮進檢查 2
  • react/jsx-indent-props jsx中屬性縮進檢查 2
  • react/jsx-max-props-per-line 限制JSX中單行上的props的最大數量 2
  • react/jsx-no-bind JSX中不允許使用箭頭函數和bind 2
  • react/jsx-no-duplicate-props 防止在JSX中重復的props 2
  • react/jsx-tag-spacing JSX中開起標簽開始和結束空格檢查 2
  • react/jsx-wrap-multilines 多行JSX中避免丟失括號 2
  • react/no-array-index-key 防止在數組中遍歷中使用數組key做索引 2
  • react/no-did-mount-set-state 防止在componentDidMount中使用setState 2
  • react/no-multi-comp 防止每個文件有多個組件定義 2
  • react/no-unescaped-entities 防止無效字符出現在標記中 1
  • react/no-unused-prop-types 避免定義未使用的PropType, defined but never used 1
  • react/no-unused-state 避免定義未使用的state 2
  • react/prefer-stateless-function 無狀態管理(stateless)的React組件應該繼承PureComponent 1
  • react/prop-types 防止在React組件定義中丟失props驗證(類型驗證) 1
  • react/require-default-props 非require的props需在defaultProps中申明 1
  • react/self-closing-comp 防止沒有children的組件的額外結束標簽<Text></Text> 2
  • react/sort-comp強制組件方法順序2

    ① static methods and proper

    ② lifecycle methods

    ③ custom methods

    ④ render method
  • semi 要求或禁止使用分號 2 禁止分號
"semi": [
            "error", "never"
    ]
  • space-before-function-paren 強制在 function的左括號之前使用一致的空格 2
  • spaced-comment 強制在注釋中 // 或 /\ 使用一致的空格 2
  • switch-colon-spacing 強制在 switch 的冒號左右有空格 2
  • vars-on-top 要求所有的 var 聲明出現在它們所在的作用域頂部 2
  • no-console: 禁止使用console 0
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,663評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,125評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,506評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,614評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,402評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,934評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,021評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,168評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,690評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,596評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,288評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,027評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,404評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,662評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,398評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,743評論 2 370

推薦閱讀更多精彩內容

  • 什么是 ESLint ESLint(中文站點)是一個開源的 JavaScript 代碼檢查工具,使用 Node.j...
    小肆逸閱讀 1,503評論 0 3
  • ESLint規范說明1、工具簡介ESLint是一個QA工具,用來避免低級錯誤和統一代碼的風格。ESLint被設計為...
    小漠窮秋閱讀 2,949評論 0 0
  • 前提:如果沒有安裝package control,可以參考sublime插件推薦以下按照順序安裝: 安裝Subli...
    real勾玉閱讀 1,681評論 1 2
  • ESLint 配置 ESlint 被設計為完全可配置的,這意味著你可以關閉每一個規則而只運行基本語法驗證,或混合和...
    靜默虛空閱讀 41,400評論 3 14
  • 自從1月份開始訂閱李笑來《通往財富自由之路》的專欄,便按照專欄的節奏,每日一字不差的閱讀,每日結合自身進行留言,每...
    眼睛歪了閱讀 241評論 1 1