代碼規范是軟件開發領域經久不衰的話題,幾乎所有工程師在開發過程中都會遇到或思考過這一問題。而隨着前端應用的大型化和復雜化,越來越多的前端團隊也開始重視代碼規范。同樣,前段時間,筆者所在的團隊也開展了一波開源治理,而其中代碼規范就占據了很重要的一項。接下來的幾篇文章,將會對JS代碼規范、CSS規范、Git提交規范以及Git工作流規范進行詳細的介紹~
系列文章:
- 前端規范之JS代碼規范(ESLint + Prettier)
- 前端規范之CSS規范(Stylelint)
- 前端規范之Git提交規范(Commitizen)
- 前端規范之Gti工作流規范(Husky + Commitlint + Lint-staged)
本文主要介紹了前端規范之Git工作流規范(Husky + Commitlint + Lint-staged),將會對Husky、Commitlint和Lint-staged的使用進行介紹,歡迎大家交流討論~
1. 背景
在前面的幾篇文章中,我們已經介紹了如何在項目中安裝並配置ESLint、Prettier、Stylelint和Commitizen。有了這些工具,可以很好的幫助我們格式化代碼並提示錯誤。
然而,有些同學可能會把ESLint、Stylelint或Commitizen提示的錯誤忽視不見,直接將代碼提交到代碼倉庫中。這樣做的話,那么其他同學在pull代碼並diff代碼時可能會出現大段代碼標紅,同時在進行CI時又可能因為代碼風格或規范問題被打回重改。
那么,有沒有一種方法,讓大家在提交代碼時需要確保本地的代碼或Commit Message已經通過檢查才能夠push到代碼倉庫,從而更好的保障代碼質量呢?接下來,將會介紹如何使用Husky + Commintlint + Lint-staged打造規范的Git檢查工作流,確保我們的代碼只有符合規范才能提交到代碼倉庫。
2. Husky
首先,先來介紹一下Husky的安裝和相關配置。
2.1 什么是git hook
在介紹Husky之前,我們先來看什么是git hook,也就是常說的Git鈎子。
和其它版本控制系統一樣,Git能在特定的重要動作發生時觸發自定義腳本。有兩組這樣的鈎子:客戶端的和服務器端的。 客戶端鈎子由諸如提交和合並這樣的操作所調用,而服務器端鈎子作用於諸如接收被推送的提交這樣的聯網操作。 你可以隨心所欲地運用這些鈎子。
其中,客戶端鈎子我們可能用的比較多,客戶端鈎子通常包括了提交工作流鈎子、電子郵件工作流鈎子和其它鈎子。這些鈎子通常存儲在項目的.git/hooks目錄下,我們需要關注的主要是提交工作流鈎子。提交工作流鈎子主要包括了以下四種:
- pre-commit:該鈎子在鍵入提交信息前運行。 它用於檢查即將提交的快照。如果該鈎子以非零值退出,Git 將放棄此次提交,你可以利用該鈎子,來檢查代碼風格是否一致。
- prepare-commit-msg:該鈎子在啟動提交信息編輯器之前,默認信息被創建之后運行。 它允許你編輯提交者所看到的默認信息。
- commit-msg:該鈎子接收一個參數,此參數存有當前提交信息的臨時文件的路徑。 如果該鈎子腳本以非零值退出,Git 將放棄提交,因此,可以用來在提交通過前驗證項目狀態或提交信息。
- post-commit:該鈎子一般用於通知之類的事情。
在上面的鈎子中,我們需要關注pre-commit和commit-msg鈎子。
2.2 什么是husky
husky是常見的git hook工具,使用husky可以掛載Git鈎子,當我們本地進行git commit或git push等操作前,能夠執行其它一些操作,比如進行ESLint檢查,如果不通過,就不允許commit或push。
2.3 安裝husky
安裝husky,可以使用npm進行安裝。
npm install husky --save-dev
2.4 配置husky
安裝好husky之后,還需要對husky進行配置。不同版本的husky配置方法有些不同,這里主要對4.3.8版本的配置進行介紹。
首先,我們需要先安裝配置好ESLint或Stylelint,並且在package.json中加入以下代碼。
"husky": { "hooks": { "pre-commit": "eslint src/**/*.{js,jsx,ts,tsx}", } }
接着,當我們執行git commit時,就會觸發pre-commit鈎子,並且執行對應命令,這里將會指定目錄下的文件進行ESLint檢查,如果ESLint檢查不通過,是無法進行commit的。
如果ESLint檢查通過,就可以正常進行commit。
在安裝並配置好husky之后,如果發現在commit時不能觸發pre-commit,可以試着重新安裝husky,並且重啟VSCode。
2.5 只使用husky的問題
使用husky雖然能夠幫助我們在commit或push前執行一些指令,但是如果只使用husky,仍然存在下面這些問題:
- 在某次提交時,我們只修改了某個文件,但是只使用husky會把所有的文件都運行一遍Lint檢查,時間成本太高。此外,有些項目會在中途才加上husky,但是在commit時husky也會對其它未修改的歷史代碼進行檢查,可能會一下子報了很多錯誤,這個時候我們更希望只對當前修改過的文件進行檢查,而不是對項目中的代碼都進行檢查。
- husky的鈎子只能執行一個指令,但是有時候我們希望能夠在git commit之前執行多個指令,比如執行ESLint、Stylelint或Commitlint等操作。
為了解決上面的問題,就需要結合Lint-staged一起使用。
3. Lint-staged
接下來,將會對Lint-staged的安裝和配置進行介紹。
3.1 什么是Lint-staged
Lint-staged可以在git staged階段的文件上執行Linters,簡單說就是當我們運行ESlint或Stylelint命令時,可以通過設置指定只檢查我們通過git add添加到暫存區的文件,可以避免我們每次檢查都把整個項目的代碼都檢查一遍,從而提高效率。
其次,Lint-staged允許指定不同類型后綴文件執行不同指令的操作,並且可以按步驟再額外執行一些其它shell指令。
3.2 安裝Lint-staged
安裝Lint-staged,可以使用npm進行安裝。
npm install lint-staged --save-dev
3.3 配置Lint-staged
安裝好了Lint-staged之后,就需要配置Lint-staged。我們可以在package.json中加入以下代碼,這里需要先安裝配置好husky,ESLint和Stylelint。
"husky": { "hooks": { "pre-commit": "lint-staged", } }, "lint-staged": { "*.vue": [ "eslint --fix", "stylelint --fix", "git add" ], "*.{js,jsx,ts,tsx}": [ "eslint --fix", "git add" ], "*.{htm,html,css,sss,less,scss,sass}": [ "stylelint --fix", "git add" ] }
當我們執行git commit時,就會觸發husky的pre-commit鈎子,調用lint-staged命令。而lint-staged包含了對*.vue,*.{js,jsx,ts,tsx},*.{htm,html,css,sss,less,scss,sass}類型文件的操作。以*.vue為例,當匹配到后綴名為.vue的文件時,就會分別執行以下操作:
- 首先會執行eslint --fix命令,對.vue文件執行ESLint檢查,並且自動修復一些JS格式問題
- 接着會執行stylelint --fix命令,對.vue文件的CSS執行Stylelint檢查,並且自動修復一些CSS格式問題
- 最后,若前面的指令都執行通過,那么將通過git add命令將文件重新加入到本地的git commit中,如果沒有執行通過,那么將不能commit
4. Commitlint
除了在commit前對JS和CSS執行ESLint和Stylelint檢查之外,也可以對Commit Message進行檢查。接下來,將會介紹Commitlint的安裝和配置方法。
4.1 什么是Commitlint
在使用Git提交代碼時,通常都需要填寫提交說明,也就是Commit Message。在前面的文章中,已經介紹了如何使用Commitizen或可視化工具編寫符合規范的Commit Message。然而有些同學可能還是會使用git commit方式提交一些不符合規范的Commit Message。為了禁止不符合規范的Commit Message的提交,我們就需要采用一些工具,只有當開發者編寫了符合規范的Commit Message才能夠進行commit。而Commitlint就是這樣一種工具,通過結合husky一起使用,可以在開發者進行commit前就對Commit Message進行檢查,只有符合規范,才能夠進行commit。
4.2 安裝Commitlint
使用npm安裝Commitlint相關依賴包。
npm install @commitlint/cli @commitlint/config-conventional --save-dev
4.3 配置Commitlint
安裝好Commitlint之后,就需要配置Commitlint,可以在根目錄創建commitlint.config.js文件進行配置。
在comminlint.config.js中加入以下代碼,表示使用config-conventional規范對提交說明進行檢查。具體的規范配置可以查看:https://github.com/conventional-changelog/commitlint
module.exports = { extends: ['@commitlint/config-conventional'] };
接下來,需要在package.json中加入commit-msg鈎子。
"husky": { "hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS" } }
配置好了之后,當我們進行git commit時,就會觸發commit-msg鈎子,執行commintlint命令,並且讀取commitlint.config.js中的規則對我們的提交說明進行檢查,如果校驗不通過,將不能提交。
5. Git檢查工作流
在介紹完Husky,Commitlint和Lint-staged之后,接下來,我們就可以將這幾個工具結合起來,打造完整的Git檢查工作流。下面給出了一份示例代碼,其中,該項目采用了Vue-cli進行構建,下面是該項目對應的package.json文件。
{ "name": "test", "version": "0.1.0", "private": true, "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "lint": "vue-cli-service lint", }, "dependencies": { "core-js": "^3.6.5", "vue": "^2.6.11", "vue-router": "^3.2.0", "vuex": "^3.4.0" }, "devDependencies": { "@commitlint/cli": "^12.1.4", "@commitlint/config-conventional": "^12.1.4","@vue/cli-plugin-babel": "^4.5.0", "@vue/cli-plugin-eslint": "^4.5.0", "@vue/cli-service": "^4.5.0", "@vue/eslint-config-prettier": "^6.0.0", "babel-eslint": "^10.1.0", "eslint": "^6.7.2", "eslint-plugin-prettier": "^3.3.1", "eslint-plugin-vue": "^6.2.2", "husky": "^4.3.8", "less": "^3.0.4", "less-loader": "^5.0.0", "lint-staged": "^11.0.0", "prettier": "^2.2.1", "stylelint": "^13.13.1", "stylelint-config-prettier": "^8.0.2","stylelint-config-standard": "^22.0.0", "stylelint-order": "^4.1.0", "stylelint-webpack-plugin": "^2.2.2", "vue-template-compiler": "^2.6.11" }, "husky": { "hooks": { "pre-commit": "lint-staged", "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" } }, "lint-staged": {
"*.vue": [
"vue-cli-service lint",
"stylelint --fix",
"git add"
],
"*.{js,jsx,ts,tsx}": [
"vue-cli-service lint"
"git add"
],
"*.{htm,html,css,sss,less,scss,saas}":[
"stylelint --fix"
"git add"
]
}
}
配置好package.json之后,當我們進行git commit提交時,首先將會觸發pre-commit鈎子,調用lint-staged命令,並且會對不同后綴的文件執行不同的檢查。接着,還將會觸發commit-msg鈎子,調用commitlint對我們的提交說明進行檢查。如果其中一個無法通過檢查,將無法提交。
當校驗通過時,就可以放心的將代碼提交到代碼倉庫中,而不用再擔心代碼風格等問題啦~