寫在最前
最近在初始化工程,為了規(guī)范代碼風(fēng)格和提交風(fēng)格,在代碼提交的時(shí)候利用git hooks對(duì)代碼做了一些處理。在此過程中學(xué)到的東西做一下總結(jié)
一、.git
.git文件夾是git init后在當(dāng)前目錄生成的一個(gè)管理git倉庫的文件夾,這里包含所有g(shù)it操作所需要的東西。
git的命令commit、push、rebase等等,這些命令主要是在執(zhí)行.git文件夾中的東西。
這個(gè) .git 文件夾是隱藏的。需要顯示隱藏文件夾才能看到。
1.Git Hooks
掛鉤都被存儲(chǔ)在 .git 目錄下的 hooks 子目錄中,即項(xiàng)目中的 .git/hooks
git 初始化的時(shí)候生成的默認(rèn)鉤子,已包含了大部分可以使用的鉤子,但是有 .sample 拓展名,防止它們默認(rèn)被執(zhí)行。
啟用對(duì)應(yīng)鉤子,你只需要去掉 .sample 拓展名。
commit操作有 4個(gè)掛鉤被用來處理提交的過程,他們的觸發(fā)時(shí)間順序如下:
pre-commit、prepare-commit-msg、commit-msg、post-commit
鉤子執(zhí)行順序是有先后的
- 前置(pre)鉤子,在動(dòng)作完成前調(diào)用
- 后置(post)鉤子,在動(dòng)作完成后執(zhí)行
當(dāng)鉤子在非零狀態(tài)下退出,git操作就會(huì)停止。
我們想在提交代碼的時(shí)候?qū)Υa做檢查,需要在鉤子里寫入指令,執(zhí)行g(shù)it操作前先運(yùn)行鉤子里的指令,調(diào)用eslint檢查代碼,如果代碼不符合規(guī)范就非零退出,git操作就會(huì)停止,從而達(dá)到我們的目的。
但是手動(dòng)修改hooks會(huì)比較麻煩,我們可以通過husky來創(chuàng)建鉤子進(jìn)行管理
二、利用husky構(gòu)建鉤子
1.husky
https://github.com/typicode/husky
npm install --save-dev husky
改寫了.git/hooks 目錄中的文件,只需在package.json 中配置對(duì)應(yīng)鉤子要執(zhí)行的腳本。在 Git 操作時(shí)觸發(fā);
package.json
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
這段配置做了兩個(gè)事情:
在pre-commit的時(shí)候觸發(fā)lint-staged
在commit-msg的時(shí)候觸發(fā)commitlint
下面來詳細(xì)講講lint-staged、commitlint這兩個(gè)包
2.Lint-staged
https://github.com/okonet/lint-staged
從這個(gè)包名,就可以看出,Run linters on git staged files,只針對(duì)本次提交所改動(dòng)的文件進(jìn)行處理。
安裝:
npm install --save-dev lint-staged
Lint-staged僅僅是文件過濾器,不會(huì)幫你格式化任何東西,所以沒有代碼規(guī)則配置文件,需要自己配置一下,如:.eslintrc、.stylelintrc等,然后在package.json中引入。
package.json中
"lint-staged": {
"*.{js,jsx}": [
"eslint --fix",
"git add"
]
}
當(dāng)文件變化,我們git commit它們,pre-commit鉤子會(huì)啟動(dòng),執(zhí)行lint-staged命令,我們對(duì)于lint-staged如上文配置,對(duì)本次被commited中的所有.js、.jsx文件,執(zhí)行eslint --fix命令和git add命令,前者的的目的是格式化,后者是對(duì)格式化之后的代碼重新提交。
3.eslint
如果同一目錄中有多個(gè)配置文件,則ESLint將僅使用一個(gè)。優(yōu)先順序?yàn)椋?/p>
.eslintrc.js.eslintrc.cjs.eslintrc.yaml.eslintrc.yml.eslintrc.json.eslintrcpackage.json
具體的配置在這里不再贅述,按照自己的代碼需要配置即可
4.commitlint
https://github.com/conventional-changelog/commitlint
用來設(shè)置代碼提交規(guī)范,方便團(tuán)隊(duì)協(xié)作和快速定位問題
安裝:
npm install --save-dev @commitlint/config-conventional @commitlint/cli
配置文件commitlint.config.js,當(dāng)然也可以是 .commitlintrc.js:
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
[
'feat', // 新功能(feature)
'fix', // 修補(bǔ)bug
'docs', // 文檔(documentation)
'style', // 格式(不影響代碼運(yùn)行的變動(dòng))
'refactor', // 重構(gòu)(即不是新增功能,也不是修改bug的代碼變動(dòng))
'test', // 增加測(cè)試
'revert', // 回滾
'config', // 構(gòu)建過程或輔助工具的變動(dòng)
'chore', // 其他改動(dòng)
],
]
}
}
5.鉤子工作流程說明
當(dāng)開發(fā)者執(zhí)行 git add 操作將代碼提交到暫存區(qū)后,再執(zhí)行 git commit 操作時(shí):
- 由于安裝
husky后其在.git/hooks中寫入了pre-commit鉤子,該鉤子在 git commit 執(zhí)行時(shí)被觸發(fā),執(zhí)行npm run precommit腳本(即lint-staged命令); -
lint-staged的配置,就是利用linters對(duì)暫存區(qū)的文件路徑應(yīng)用過濾規(guī)則,匹配的文件將執(zhí)行后面配置的任務(wù),這里的任務(wù)就是調(diào)用項(xiàng)目中的eslint指令檢查文件,如果報(bào)錯(cuò)則先自動(dòng)修復(fù)--fix,最后把沒有問題的代碼加入暫存區(qū)git add。 - 如果最終還有報(bào)錯(cuò),則流程終止,無法執(zhí)行 commit 操作。
操作過程中遇到的一些問題:
husky v4 需要node>=10,而目前在用的node版本還是8,此時(shí)無法觸發(fā)鉤子
因此退到
"husky": "^3.1.0"
"lint-staged": "^9.5.0",
此時(shí)需要最低node版本是v8.12.0
三、EditorConfig
什么是EditorConfig?官方介紹:幫助開發(fā)人員定義和維護(hù)一致性開發(fā)風(fēng)格(coding style)。它可以讓代碼在各種編輯器和IDE中保持風(fēng)格一致,當(dāng)然也可以讓不同的隊(duì)員寫一致風(fēng)格的代碼
1.使用EditorConfig
使用EditorConfig很簡(jiǎn)單,在項(xiàng)目根目錄放置一個(gè). editorconfig文件
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
- indent_style:tab為hard-tabs,space為soft-tabs。
- indent_size:設(shè)置整數(shù)表示規(guī)定每級(jí)縮進(jìn)的列數(shù)和soft-tabs的寬度(譯注:空格數(shù))。如果設(shè)定為tab,則會(huì)使用tab_width的值(如果已指定)。
- tab_width:設(shè)置整數(shù)用于指定替代tab的列數(shù)。默認(rèn)值就是indent_size的值,一般無需指定。
- end_of_line:定義換行符,支持lf、cr和crlf。
- charset:編碼格式,支持latin1、utf-8、utf-8-bom、utf-16be和utf-16le,不建議使用uft-8-bom。
- trim_trailing_whitespace:設(shè)為true表示會(huì)除去換行行首的任意空白字符,false反之。
- insert_final_newline:設(shè)為true表明使文件以一個(gè)空白行結(jié)尾,false反之。
- root:表明是最頂層的配置文件,發(fā)現(xiàn)設(shè)為true時(shí),才會(huì)停止查找.editorconfig文件
按照上面配置即可,IDE中需要開啟相應(yīng)EditorConfig插件,不安裝是沒有效的?。。。?/p>
以vscode為例,需要安裝:
EditorConfig for VS Code插件
四、Prettier
代碼格式化工具
1.有了 ESLint ,為什么還要Prettier 呢?
- eslint的主要校驗(yàn)常見的語法和代碼風(fēng)格錯(cuò)誤(未使用變量、三等號(hào)、全局變量聲明等問題)
- Prettier 只是代碼格式的校驗(yàn)(并格式化代碼)。例如單行代碼長(zhǎng)度、tab長(zhǎng)度、空格、逗號(hào)表達(dá)式等問題。
配合ESLint檢測(cè)代碼風(fēng)格主要有一下兩個(gè)插件:
eslint-plugin-prettier 和 eslint-config-prettier
2.eslint-plugin-prettier
eslint-plugin-prettier 會(huì)對(duì)比格式化前和用 Prettier 格式化后的代碼,有不一致的地方就會(huì)報(bào)錯(cuò)提示
//.eslintrc.js
{
"plugins": ["prettier"],
"rules": {
"prettier/prettier": "error"
}
}
3.eslint-config-prettier
如果你曾經(jīng)嘗試過將 Prettier 和 ESLint 放在一起運(yùn)行,那么可能會(huì)遇到規(guī)則沖突。
這個(gè)插件是如果eslint的規(guī)則和prettier的規(guī)則發(fā)生沖突的時(shí)候(主要是不必要的沖突),例如eslint 限制了必須單引號(hào),prettier也限制了必須單引號(hào),那么如果用 eslint 驅(qū)動(dòng) prettier 來做代碼檢查的話,就會(huì)提示2種報(bào)錯(cuò),雖然他們都指向同一種代碼錯(cuò)誤,這個(gè)時(shí)候就會(huì)由這個(gè)插件來關(guān)閉掉額外的報(bào)錯(cuò)。
實(shí)現(xiàn) prettier 規(guī)則對(duì) eslint 規(guī)則的覆蓋。
使用的時(shí)候需要確保,這個(gè)配置在extends的最后一項(xiàng)。
//.eslintrc.js
{
extends: [
'standard', //使用standard做代碼規(guī)范
"prettier",
],
}
4.同時(shí)設(shè)置eslint-plugin-prettier 和 eslint-config-prettier
如果你同時(shí)使用了上述的兩種配置,那么你可以通過如下方式,簡(jiǎn)化你的配置。(省去了上面兩個(gè)單獨(dú)的配置)
在.eslintrc文件中加入以下配置
{
? plugins: ["prettier"],
? "extends": ["plugin:prettier/recommended"]
}
這段代碼有三個(gè)作用
- 繼承prettier的config規(guī)則
- 開啟rules的 "prettier/prettier": "error"
- eslint fix的同時(shí)執(zhí)行prettier格式化
參考:
利用 git 鉤子做代碼提交前的檢查
前端代碼風(fēng)格自動(dòng)化系列(三)之Lint-staged
一招讓你成為前端大牛
prettier淺出
使用ESLint+Prettier來統(tǒng)一前端代碼風(fēng)格
eslint+husky+prettier+lint-staged提升前端應(yīng)用質(zhì)量