專案組 eslint 統一配置及疑難解決
背景
專案組前端程式碼eslint
久失維護,大家有的人有程式碼規範,有的人沒有。新來的程式碼規範也是從老的手裡copy一份。每個人eslint
外掛的版本、配置、程式碼項均不同。導致改程式碼的時候,為了避免自動fix
帶來的大量程式碼改動,不得不暫時關閉eslint
,改完後,無規則校驗上庫。程式碼規範缺乏校驗,上庫程式碼質量日益下降。
第一步
按照可信認證規則(標準程式碼規範)配置eslintrc
檔案,外掛的配置自不必說。為了支援js/ts/jsx/tsx
,需要安裝eslint
的4個外掛,配置在plugin
中。注意為了支援ts
,parser
需要指定為@typescript-eslint/parser
ts
規則。
- eslint-react
- eslint-react-hooks
- eslint-typescript
- [email protected]
編寫eslint fix
指令碼,全域性fix專案中的程式碼。共計上庫改動600
餘個檔案。
eslintrc.js
module.exports = {
'root':true,
'env': {
'browser': true,
'es6': true,
'node': true
},
'globals': {
'Atomics': 'readonly' ,
'SharedArrayBuffer': 'readonly'
},
"parser": "@typescript-eslint/parser",
'parserOptions': {
'ecmaFeatures': {
'jsx': true
},
'ecmaVersion': 6,
'sourceType': 'module'
},
'plugins': [
'react',
"react-hooks" ,
"typescript",
"@typescript-eslint"
],
'settings':{
"react": {
"version": "16.13.0",
},
},
"overrides": [
{
"files":["*.tsx","*.jsx"],
"rules": {
"react/jsx-indent-props": 0, //禁用驗證JSX中的props縮排
}
}
],
//覆蓋規則
'rules': {
'indent': [//縮排
'error',
4
],
'semi': [//語句強制分號結尾
'error',
'always'
],
//引數一:0或‘off’ 關閉規則,1或‘warn’ 規則等級警告,2或者‘error’ 規則等級錯誤
//引數二:可以使用預設,也可以根據文件自定義
'no-unused-vars': 0,//禁止出現未使用過的變數
'no-console': 1,//建議不使用console
'no-var': 1,//建議使用let或const替代var
'object-shorthand': 2,//物件屬性、方法簡寫語法
'prefer-spread':1,//建議使用擴充套件運算子...複製陣列
'comma-dangle': ['error', {
'arrays': 'only-multiline',
'objects': 'only-multiline',
'imports': 'never',
'exports': 'never',
'functions': 'ignore'
}],//要求使用尾逗號
'func-style':['error','declaration',{"allowArrowFunctions": true}],//要求函式使用宣告式取代表達式
'prefer-rest-params':2,//要求使用rest語法...替代arguments
'no-param-reassign':1,//函式引數禁止再賦值
"curly": ["error", "all"],//控制語句使用大括號
"prefer-destructuring": ["warn", {
"array": true,
"object": true
}, {
"enforceForRenamedProperties": false//解構是否應用於重構
}],//陣列解構和物件解構
"max-len": ["warn", 120, 4],//行的最大長度120 縮排4
'no-eval':2,//禁止使用eval
'no-with':2,//禁止使用with
'brace-style':[2,'1tbs',{"allowSingleLine": true}],//花括號風格:左開與語句在同一行,允許花括號左右在同一行
'no-const-assign':2,//禁止修改const宣告變數
'no-empty':[1,{"allowEmptyCatch": true }],//建議不要存在空語句塊,允許catch塊為空
'no-cond-assign':[2,"always"],//禁止在 if、for、while 和 do...while 語句中出現模稜兩可的賦值操作符
'no-unreachable':2,//禁止在 return、throw、continue 和 break 語句後出現不可達程式碼
"jsx-quotes": [2, "prefer-double"], //強制在JSX屬性(jsx-quotes)中一致使用雙引號
"react/jsx-closing-bracket-location": 0, //在JSX中驗證右括號位置
"react/jsx-curly-spacing": [2, {"when": "never", "children": true}], //在JSX屬性和表示式中加強或禁止大括號內的空格。
"react/jsx-indent-props": [2, 4], //驗證JSX中的props縮排
"react/jsx-key": 2, //在陣列或迭代器中驗證JSX具有key屬性
"react/jsx-no-bind": 0, //JSX中不允許使用箭頭函式和bind
"react/jsx-no-duplicate-props": 2, //防止在JSX中重複的props
"react/jsx-no-undef": 1, //在JSX中禁止未宣告的變數
"react/jsx-pascal-case": 1, //為使用者定義的JSX元件強制使用PascalCase
"react/jsx-uses-vars": 1, //防止在JSX中使用的變數被錯誤地標記為未使用
"react/no-danger": 1, //防止使用危險的JSX屬性
"react/no-did-mount-set-state": 0, //防止在componentDidMount中使用setState
"react/no-did-update-set-state": 1, //防止在componentDidUpdate中使用setState
"react/no-direct-mutation-state": 2, //防止this.state的直接變異
"react/no-multi-comp": 1, //防止每個檔案有多個元件定義
"react/no-set-state": 0, //防止使用setState
"react/no-unknown-property": 2, //防止使用未知的DOM屬性
"react/prefer-es6-class": 2, //為React元件強制執行ES5或ES6類
"react/prop-types": 0, //防止在React元件定義中丟失props驗證
"react/react-in-jsx-scope": 2, //使用JSX時防止丟失React
"react/self-closing-comp": 0, //防止沒有children的元件的額外結束標籤
"react/sort-comp": 1, //強制元件方法順序
"no-extra-boolean-cast": 0, //禁止不必要的bool轉換
"react/no-array-index-key": 0, //防止在陣列中遍歷中使用陣列key做索引
"react/no-deprecated": 1, //不使用棄用的方法
"react/jsx-equals-spacing": 2, //在JSX屬性中強制或禁止等號周圍的空格
"comma-dangle": 2, // 陣列和物件鍵值對最後一個逗號, never引數:不能帶末尾的逗號, always引數:必須帶末尾的逗號
"comma-spacing": [2, {'before': false, 'after': true}], // 控制逗號前後的空格
"no-mixed-spaces-and-tabs": 0, //禁止混用tab和空格
"prefer-arrow-callback": 0, //比較喜歡箭頭回調
//空格 建議
"space-before-blocks": [1, "always"],//程式碼塊花括號左{空格
"space-before-function-paren": [1, "never"],//函式定義時括號前面要有空格
"space-in-parens": [1, "never"],//小括號裡面要有空格
"space-infix-ops":[1,{"int32Hint": true}],//操作符空格 true允許B|0
//--FIX dyj react-hooks相關
"react-hooks/rules-of-hooks": "error", // Checks rules of Hooks
//--FIX dyj 補充可信認證中的規範
"arrow-body-style":1, //--規則31 箭頭函式的簡寫
"eqeqeq":1, //--建議47 判斷相等時使用 === 和 !== ,而不是 == 和 !=
"no-else-return":1, //--規則32 要求使用一致的 return 語句
"no-useless-return":1,//--規則 66 禁止多餘的 return 語句
"consistent-return":1,
"prefer-template":1,//--規則36 使用模板字串(`)實現字串拼接
"no-prototype-builtins":1, //--規則 43 禁止在物件例項上直接使用 Object.prototypes 的內建屬性
"dot-notation":1, //--規則 41 使用點號來訪問物件的屬性,只有屬性是動態的時候使用 []
"guard-for-in":1, //規則 44 需要約束 for-in
"no-nested-ternary":1, //規則 46 禁止使用巢狀的三元表示式
"default-case":1, // 規則 47 每個 switch 語句都包含一個 default 語句,即使它不包含任何程式碼
"no-case-declarations":1, //--規則 49 case 語句中需要宣告詞法時, 花括號 {} 不能省略
"no-duplicate-imports":1, //--規則 52 不要多次 import 同一個模組
"no-useless-rename":1, //--規則 55 不要從 import 中直接 export
"no-floating-decimal":1,//--規則 57 禁止省略小數點前後的 0
"use-isnan":1,//--規則 58 要求呼叫 isNaN() 檢查 NaN
"no-unsafe-finally":1,//--規則 59 禁止在 finally 語句塊中出現控制流語句
"no-return-await":1,//--規則 60 禁用不必要的 return await
"no-implicit-coercion":1, //--規則 65 禁止使用較短的符號實現型別轉換
"new-cap":1, //--構造器函式、類採用首字母大寫的駝峰命名方法
"no-shadow":1,//--規則67 塊內變數不能與函式內的其他變數同名,塊內函式應該使用函式表示式宣告
}
}
"scripts": {
"eslint": "eslint src scripts config --ext .jsx --ext .tsx --ext .js --ext ts -o eslint-report.txt -c .eslintrc.js",
"eslint-fix": "eslint --fix src scripts config --ext .jsx --ext .tsx --ext .js --ext ts -c .eslintrc.js",
},
第二步
通過npm run eslint
生成報告,手動修改無法fix
的問題,例如重複props
、繞過setState
直接修改state
、或者引數重賦值等問題累計60
餘處。
第三步
配置 eslint-vscode
外掛。統一使用2.1.14
版本,使用通用的工作區設定:
{
"eslint.run": "onType",
"eslint.format.enable":true,
"eslint.options": {
"extensions": [
"web.js",
"js",
"web.ts",
"ts",
"web.tsx",
"tsx",
"json",
"web.jsx",
"jsx",
"node"
]
},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"editor.suggestSelection": "first"
}
第四步
設定webpack編譯時校驗(僅限開發模式)
rules: [
// Disable require.ensure as it's not a standard language feature.
{ parser: { requireEnsure: false } },
// First, run the linter.
// It's important to do this before Babel processes the JS.
isEnvDevelopment ? {
test: /\.(js|mjs|jsx|ts|tsx)$/,
enforce: 'pre',
use: [
{
options: {
formatter: require.resolve('react-dev-utils/eslintFormatter'),
eslintPath: require.resolve('eslint')
},
loader: require.resolve('eslint-loader')
}
],
include: paths.appSrc
} : {},
]
問題
1、eslint
規則衝突 導致無限fix
解決eslint
規則衝突的問題。eslint
規則衝突會導致不論是eslint-vscode
外掛還是npm eslint
,無限fix
程式碼的過程。例如最常見的,eslint
原始規則 indent
,設定程式碼應該的間隔,極容易與react
外掛配置的一些規則衝突。這時候,就需要我們對react
字尾(jsx、tsx
)檔案做覆蓋規則處理:
//--eslintrc.js
"overrides": [
{
"files":["*.tsx","*.jsx"],
"rules": {
"react/jsx-indent-props": 0, //禁用驗證JSX中的props縮排
}
}
]
2、專案成員明明eslint配置全部一致,實際規則卻不一致
這是由於eslint在查詢配置檔案時,會不斷的冒泡向上查詢規則直到系統根路徑。如果eslintrc.js沒有配置root:true
。參加這裡,則eslint會不斷的在電腦中尋找配置檔案。部分成員根目錄中配置了額外規則,導致覆寫的時候出現問題。在eslintrc.js
中新增即可
'root':true
五、成效
專案成員使用統一的eslint規範,再也不用害怕ctrl+s改壞原來的程式碼。且存在程式碼壞味道的程式碼會在開發階段的門禁就被攔截掉,避免引入更大的問題。
專案 | Value |
---|---|
自動修復檔案數 | 583 |
自動修復程式碼行數 | 15000 |
手動修復程式碼問題(風險問題) | 56 |