背景
隨著項?復雜度提?、團隊成員增多,但編碼的?格不統(tǒng)?,會增加后期維護代碼的成本以及編碼效率。如果制定?套好的規(guī)范,可以解決很多意外的bug、可以規(guī)范??的編碼習慣、可以讓 code Review 更加簡單。
?標
- 降低維護代碼的成本、提高多?協(xié)作的效率
- 遵守最佳實踐,確保寫出更?效且優(yōu)雅的代碼
Git提交信息規(guī)范
在使? Git 進?代碼的分布式版本控制時,規(guī)范化 commit message 可以幫助開發(fā)人員在多? 開發(fā)協(xié)作中更好的理解他?對代碼的改動信息,避免?家按照各?的理解和習慣(甚?是隨意)書寫,?對他?和??造成困惑,從?增加代碼審查和糾錯的時間成本。
本規(guī)范基于 Conventional 規(guī)范,這是標準的 commit message 的寫法,?較合理和系統(tǒng)化,并且可以搭配?具校驗。
作?
?個規(guī)范化的 commit message ,具有以下作?:
? 提供更多的歷史信息,?便快速瀏覽
? 可以過濾某些 commit (?如?檔改動),便于快速查找信息
? 可以直接從 commit ?成 CHANGELOG.md
格式
使? git commit 可以提交多?,完整的格式包括三個部分:
? Header【必填】
? Body【選填】
? Footer【選填】
<type>(<scope>): <subject> <!-- header -->
<!-- 空?? -->
<body>
<!-- 空?? -->
<footer>
任意??都不應(yīng)該超過100字符,這樣的信息在 github 和各種各樣的 git ?具上能有更好的可讀性。
Header 是必填,Body 和 Footer 是選填 ,因此這里只介紹Header的寫法
Header 包括三個字段:
? type(必填)
? scope(選填)
? subject(必填)
<type>(<scope>): <subject>
Type
?于說明 commit 的類別,只允許使?下? 7 個標識:
? feat:新功能(feature)
? fix:修補bug
? docs:?檔(documentation)
? style:格式(不影響代碼運?的變動)
? refactor:重構(gòu)(即不是新增功能,也不是修改bug的代碼變動)
? test:增加測試
? chore:構(gòu)建過程或輔助?具的變動
Scope
?于說明 commit 影響的范圍,?如數(shù)據(jù)層、控制層、視圖層等等
Subject
?于對 commit ?的的簡短描述,不超過50個字符
以動詞開頭,使?第??稱現(xiàn)在時,?如 change ,?不是 changed 或 changes 第?個字??寫
注意:結(jié)尾不需要加句號(.)
# ?例?
fix(login): 修改登錄賬號加密?式
# ?例?
fix: 去除登錄??console代碼
配合?具
- 使??具 commitozen 來輔助格式化 git commit message ,它提供了?種問詢式的?式去獲取所需信息
https://www.npmjs.com/package/commitizen
? Git提交信息鉤?:husky
https://typicode.github.io/husky/#/?id=install - 提交信息自動驗證?具: @commitline/cli
https://commitlint.js.org/#/
使用如下代碼后,便自動生成校驗鉤子,在代碼提交前校驗提交信息規(guī)范,對于格式不對的會阻止提交
# Install Husky v6
npm install husky --save-dev
# or
yarn add husky --dev
# Active hooks
npx husky install
# or
yarn husky install
# Install and configure if needed
npm install --save-dev commitizen @commitlint/{cli,config-conventional}
# For Windows:
npm install --save-dev commitizen @commitlint/config-conventional @commitlint/cli
# Configure commitlint to use conventional config
echo "module.exports = { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js
# Add hook
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'
# or
yarn husky add .husky/commit-msg 'yarn commitlint --edit $1'
編碼規(guī)范
ESLint 是?個按照規(guī)則給出報告的代碼檢測?具 ,使?它可以避免低級錯誤和統(tǒng)?代碼?格,這對公司團隊開發(fā)?常實?。
以React / Vue3 Cli項?中配置ESLint為例,?概說明下基本配置以及作?
// 需要安裝 babel-eslint
// babel-eslint 將不能被常規(guī)linter解析的代碼轉(zhuǎn)換為能被常規(guī)解析的代碼
npm install --save-dev eslint babel-eslint
// 進?初始化,如果選擇airbnb,會?動安裝部分相關(guān)的插件
eslint --init
// 進?初始化后,會在項?根?錄下?成?個 .eslintrc.js ?件
React 版本 安裝完后會 package.json 一般會添加如下?個依賴包
"eslint": "^7.29.0",
"babel-eslint": "^10.1.0",
"eslint-config-airbnb/react-app": "^18.2.1",
// 使用create-react-app創(chuàng)建的 默認將使用 eslint-config-react-app
"eslint-plugin-import": "^2.23.4",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-react": "^7.24.0",
"eslint-plugin-react-hooks": "^4.2.0",
Vue 版本 由于是通過vue-cli創(chuàng)建的,所以會額外增加 @vue/cli-plugin-eslint
"eslint": "^7.29.0",
"babel-eslint": "^10.1.0",
@vue/cli-plugin-eslint
eslint-plugin-vue
通過 eslint --init 后會自動生成 .eslintrc.js
React
module.exports = {
root: true,
env: {
browser: true,
es6: true,
node: true,
},
extends: ["react-app"],
globals: {},
parserOptions: {
ecmaVersion: 2018,
sourceType: "module",
parser: "babel-eslint",
},
plugins: [],
rules: {
eqeqeq: 1,
"no-unused-vars": 1,
"no-var": 2,
"no-debugger": process.env.NODE_ENV === "production" ? 2 : 1,
},
};
Vue
module.exports = {
root: true,
env: {
browser: true,
es6: true,
node: true
},
extends: ['plugin:vue/vue3-essential', 'eslint:recommended'],
globals: {
PhotoSwipe: 'readonly',
PhotoSwipeUI_Default: 'readonly'
},
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
parser: 'babel-eslint'
},
plugins: ['vue'],
rules: {
eqeqeq: 1,
'no-unused-vars': 1,
'no-var': 2,
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 1
}
}
可以看到兩個項目使用的rules規(guī)則相同,只是針對不同語法糖的格式校驗,由于本身項目是通過cli項目創(chuàng)建的,所以使用cli默認封裝的lint插件會更合適。
相關(guān)變量含義
- globals :全局變量,如果你的項??到其他?些?定義的全局變量, "fetch": false 這樣配置,true 和 false 代表可不可以被修改。
- env : Environments,指定代碼的運?環(huán)境。不同的運?環(huán)境,全局變量不?樣,指明運?環(huán)境 這樣ESLint就能識別特定的全局變量。同時也會開啟對應(yīng)環(huán)境的語法?持,例如:es6。這些環(huán)境不是相互排斥的,因此可以?次定義多個。
- extends : ESLint 不需要??定義?量的規(guī)則,因為很多規(guī)則已被分組作為?個規(guī)則配置。
- parserOptions : ESLint ?持 ECMAScript 5 語法。你可以覆蓋該設(shè)置,以啟?對 ECMAScript 其它版本和 JSX 的?持。通過使?解析器選項,可以覆蓋該設(shè)置以?持其他ECMAScript版本以及 JSX。
- parser : ESLint 默認使? Espree 作為其解析器,但它并不能很好的適應(yīng) React 環(huán)境,所以剛才安裝了 babel-eslint ?來代替默認的解析器,在配置?這么寫 "parser": "babel-eslint"
https://github.com/eslint/espree - plugins : 顧名思義就是插件,插件是單獨的npm包,命名?般以eslint-plugin開頭,寫的時候?字符串數(shù)組的形式,可以省略eslint-plugin開頭。plugins?般包含?個或多個規(guī)則配置,也可以在 extends 中引?。
- rules : 這?可以對規(guī)則進?細致的定義了, 覆蓋之前前?說的extends/plugins中定義的規(guī)則 。規(guī)則等級有三種:
a. "off" / 0: 關(guān)閉規(guī)則
b. "warn" / 1: 打開規(guī)則,作為警告。
c. "error" / 2: 打開規(guī)則,作為錯誤( 錯誤級別的校驗將會中斷提交)
配合 husky 校驗
- 在 package.json ?件中加?以下代碼
"scripts": {
"lint": "echo 'eslint 檢查開始...' && eslint ./src --ext .js .vue --fix"
}
命令??具, 在根?錄下?動執(zhí)? npm run lint , 即會檢測代碼
- 使? pre-commit git hook
pre-commit Hook是在Git提交之前?來?動檢查待提交代碼是否有錯誤的?具。
使?以下命令添加相關(guān)鉤?
npx husky add .husky/pre-commit "npm run lint"
這樣就可以對指定目錄下的文件進行l(wèi)int校驗
添加 Prettier 統(tǒng)?格式化代碼?格
Prettier的中?意思是“漂亮的、機靈的”,也是?個流?的代碼格式化?具的名稱,它能夠解析代碼,使?你??設(shè)定的規(guī)則來重新打印出格式規(guī)范的代碼。eslint 和 prettier 可以配合使?,也可以單獨使?。下?我們主要講eslint和prettier結(jié)合使?
ESLint 已經(jīng)有了代碼格式化的功能,為什么還需要使?Prettier呢?
各種 Linters 是按照規(guī)則(Rules)去檢查代碼的,遇到不符合規(guī)則的代碼就會提?你,有的規(guī)則還能?動幫你解決沖突。
這些規(guī)則分為兩類:
? Formatting rules
例如 ESlint 的 max-len 規(guī)則,設(shè)置單??度不能超過 80 字符。ESLint會提?你去修復。? Prettier 則不會這么?煩,它根本不管你之前符不符合什么規(guī)則,都先把你的代碼解析成 AST,然后 按照它??的?格給你重新輸出代碼。
換句話說,Prettier 對應(yīng)的是各種 Linters 的 Formatting rules 這?類規(guī)則,并且更加豐富和完善。?且你?了 Prettier 之后,就不會再違反這類規(guī)則了!不需要你???動修改代碼。
? Code-quality rules
例如 ESLint 的no-unused-vars規(guī)則,不允許沒?的變量定義出現(xiàn)。這種錯誤只能????去? 動修復。Prettier 對這類規(guī)則束??策。?且這類規(guī)則也正是各種 Linters 的重點,因為它們真的能幫你發(fā)現(xiàn)很多低級的 Bug。
那么既要讓 Prettier 幫你格式化代碼,還想讓 Linters 幫你挑出潛在的 Code-quality 類錯誤,怎么辦?就需要 Prettier 和 Linters 配合使?。
Prettier 和 Linters 的整合需要做的兩件事
- 禁? Linters ??的 Formatting rules,讓 Prettier 接管這些職責。
- 讓 Linters 執(zhí)?時?先調(diào)? Prettier 格式化,然后再檢查 Code-quality 類規(guī)則。這是 由 Linters 的 Plugin 實現(xiàn)的。
Prettier配置
npm i --D --save-exact prettier
npm i -D eslint-plugin-prettier eslint-config-prettier
// vue 需要額外安裝
npm i -D @vue/eslint-config-prettier
prettier 代碼格式化核?
eslint-plugin-prettier 插件,可以讓eslint使?prettier規(guī)則進?檢查,并使? --fix 選項。像之前的格式不對時,eslint提?的紅線。
eslint-config-prettier 插件,之前說了 eslint 也會檢查代碼的格式,這個插件就是關(guān)閉eslint 所有不必要或可能跟prettier產(chǎn)?沖突的規(guī)則。讓prettier接?代碼的格式校驗
結(jié)合.eslintrc.js配置
// vue 中
extends: [... '@vue/prettier'],
// React
extends: [... "plugin:prettier/recommended"],
以上配置做如下三件事:
1. 使eslint-plugin-prettier?效
2. 不符合prettier/prettier的規(guī)則,會報錯。就是代碼中提?的紅線。
3. 使eslint-config-prettier?效。就是會覆蓋eslint中與prettier沖突的配置。
配置.prettierrc.json
{
"tabWidth": 2, // tab占?的字符數(shù)
"trailingComma": "none", // 最后?個對象元素加逗號
"semi": false, // 是否句末加分號
"singleQuote": true, // 是否?單引號
"bracketSpacing": true // 是否對象,數(shù)組加空格
}
使? lint-staged 只校驗暫存區(qū)?件
lint-staged 是?個在git暫存?件上運?linters的?具,如果不使?這個?具的話,不管修改了?個?件在提交的時候會給所有?件執(zhí)??次lint檢查,這樣對于龐?的項?來說會浪費?量的校驗時間。
npx mrm lint-staged
使?以上命令它將根據(jù) package.json 依賴項中的代碼質(zhì)量?具來?動安裝和配置husky和 lint-staged 。
- ?動在husky?件下 創(chuàng)建 pre-commit ?件:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged
- ?動在package.json?件中添加如下配置:
"lint-staged": {
"*.js": "eslint --cache --fix"
}
有了以上基礎(chǔ)配置后,在commit的時候就只對修改的?件進?lint和修復 。但上面lint-staged配置還不夠,因此可以擴展如下:
"lint-staged": { // lint-staged 配置
"*.{js,jsx,md,vue}": [
"prettier --write",
"eslint --cache --fix",
"git add"
]
}
這? lint-staged 的配置是:
在 git 的待提交的?件中,在所有?錄下的符合的文件都要執(zhí)?三條命令。
? 第?條命令 prettier --write
? --write :默認prettier是直接標準輸出到終端的,這個配置代表直接格式化改寫?件。
? 關(guān)于prettier的還有?些配置參考這? prettier 配置文檔
https://prettier.io/docs/en/options.html
? 第三條命令, 將處理過的代碼重新 add 到 git 中。
最終在使?Git提交代碼的時候,會?動檢測暫存區(qū)里的代碼文件并進?格式化,如果有l(wèi)int錯誤(error)會終?當前的commit push
添加 .editorconfig ?件覆蓋編輯器?格
配置?個 .editorconfig ?件,在其中設(shè)置好要遵守的代碼規(guī)范,放在項?的根?錄下,就能夠 在?乎所有的主流 IDE 和編輯器中復?了,并將 .editorconfig ?件也提交到版本控制系統(tǒng)中, 這樣就不需要針對不同 IDE 和編輯器再單獨進?設(shè)置了。
// 表?是最頂層的配置?件,發(fā)現(xiàn)設(shè)為true時,才會停?查找.editorconfig?件
root = true
// * 表?所有的?件
[*]
// 對于所有的?件 始終在?件末尾插??個新?
insert_final_newline = true
// 對于所有的?件,設(shè)置?件字符集為utf-8
charset = utf-8
// 設(shè)為true表?會去除換???的任意空?字符
trim_trailing_whitespace = true
// ?尾?件格式(Unix、DOS、Mac),值為lf、cr和crlf
end_of_line = lf
// 對于特定?件
[*.{js,json,ts,tsx,vue}]
// 設(shè)置縮進?格(tab是硬縮進,space為軟縮進)
indent_style = space
// ??個整數(shù)定義的列數(shù)來設(shè)置縮進的寬度
indent_size = 2
// 使?空格替代tab,并且?個tab會被替換為2個空格。
編輯器擴展(VSCode)
? 代碼?格檢查擴展: ESlint ;
? 代碼?格格式化擴展: Prettier ;
? 編輯器設(shè)置擴展: EditorConfig for VS Code ;
關(guān)于 VScode 相關(guān)校驗插件參考
https://juejin.cn/post/6844904099092119565
參考文檔
1、Git提交信息規(guī)范
https://github.com/lingz1/standard/blob/master/code-repository/git-commit-message.md
2、ESlint 官方配置文檔
https://eslint.org/docs/user-guide/configuring/
3、ESlint 中文文檔
https://cn.eslint.org/docs/user-guide/configuring
4、EditorCOnfig 配置屬性介紹
https://github.com/editorconfig/editorconfig/wiki/EditorConfig-Properties
5、ESlint + prettier 配置及介紹
https://www.cnblogs.com/qiqi715/p/10247598.html
6、Lint _ stagged 使用教程
https://www.cnblogs.com/jiaoshou/p/12250278.html
7、vue+ vetur+eslint + prettier 自動格式化功能
https://juejin.cn/post/6844904099092119565
8、寫React Hooks 前必讀
https://zhuanlan.zhihu.com/p/113216415