項目中使用Husky 格式化代碼和校驗 Commit 信息
大家好,我是前端西瓜哥。今天我們學習使用 husky 工具,在 commit 的時候做一些風格的校驗工作,包括 commit 信息格式化和文件格式化。
git hook 和 husky
git hook 讓我們可以在 git 執行一些行為的前后時機,執行一些腳本。
比如 pre-commit? ,能夠在我們真正提交 commit 之前先執行一段代碼,如果這段代碼報錯(exit 1),提交會被取消;如果正常執行,commit 會被真正提交。
或是 commit-msg,也能在真正 commit 前拿到 commit 信息內容,去做一些檢驗工作。
利用 git hook 的能力,我們就可以在 commit 前做一些風格檢驗或格式化,比如 ESLint、Prettier、commit 格式等。
git hook 是 sh 腳本,在項目 .git/hooks 目錄下。這有一個比較尷尬的問題:.git 下的文件是不會被 git 提交的。husky 就是解決這個問題的一個方案。
實際上 git 2.9 之后,我們可以通過配置 git 的 core.hookspath 來指定 hook 目錄為相當項目下的目錄,理論上可以不用 husky。
但 husky 還是算是做了一層封裝,可以更好地操作 hook,比如通過命令行快速生成 hook,并將其設置為可執行。
husky 4 及以前使用的是 .huskyrc 來進行配置。那時候設計上有一些問題,就是沒有配置的 hook 也會觸發鉤子執行。于是在 husky 4 做了破壞性的修改。使用方法變成了在 .husky 目錄下直接加鉤子腳本。
husky 安裝和啟用
不講解 husky 4 及其以前版本的使用,因為已經過時了。
首先是安裝:
然后執行 husky 命令行工具,啟用 git hook:
該命令會創建一個 .husky 目錄。
同時,該命令還將 git 所在項目本地環境的 core.hookspath? 設置為 .husky?。所以,這個 .husky 目錄就是我們放 git hook 腳本的地方。
我們執行下面命令,可以看到當前 git 項目的本地配置有:core.hookspath=.husky。
其他同事拉取項目時,他們可能會忘記執行上面的命令啟用 git hook。但有一個命令他們是一定會執行的,就是執行 npm install? 或 yarn 去安裝依賴。
于是我們需要利用 npm script 的生命周期腳本,加上一個 prepare。prepare 會在 install 之后執行。
這樣就能保證新同事拉項目并安裝依賴后,husky 被啟用。
創建 hook
該命令會給你在 .husky 下創建一個 pre-commit 腳本,并填充 npm test 內容,這樣我們就能在 commit 前先過一過測試用例。
這個腳本會自動設置為可執行。
如果你是手動創建的,你需要手動使用 chmod u+x pre-commit 命令將該文件設置為可執行文件。否則鉤子腳本是不會執行的。
創建的腳本內容為:
它會在真正 commit 前執行 npm test,如果報錯就會中止 commit。
實戰:使用 commitlint 校驗 commit 信息格式
我們希望在提交 commit 時,能夠檢驗 commit 信息,如果不對就不允許提交。這樣能防止開發人員提交一些雜亂、無法理解或不統一的信息。
這種情況下需要用到 commit-msg 鉤子,我們先創建一個沒有內容的 commit-msg。
?在 commit-msg 腳本中,我們可以通過 $1? 拿到提交信息。$1? 指向的是 .git/COMMIT_EDITMSG 文件,該文件保存著最后一次提交的 commit 信息。
可以拿到 commit 信息,那我們就可以在上面做一些校驗工作,比如看是否符合 feat: xxx 的格式。這里有個問題,就是我們需要自己去聲明一些規范,并且要自己去實現代碼。
那,我們去找輪子,輪子找到了,它就是 commitlint。commitlint 是一個命令行工具,能夠做 commit 的校驗,并提供了官方的校驗規則,此外也支持你自己配置規則。
先安裝 commitlint:
然后創建 commitlint.config.js? 配置文件,并添加內容,使用 @commitlint/config-conventional 。
@commitlint/config-conventional? 是一個經典的 commit 規范,我們需要用類似 feat: add util.js? 或 fix: fix wrong text 這樣的格式,具體文檔見:
https://www.conventionalcommits.org/en/v1.0.0/。
然后我們在 commit-msg 鉤子上加上:
- npx --no :表示只使用本地項目 node_modules 下的腳本,不允許找不到的時候嘗試去下載。下載耗費時間,所以要取消,你要確保已經把命令行工具下載好。
- commitment --edit <文件名>?:執行 commitment 命令行工具,并使用--edit? 選項,從一個文件里提取 commit 內容來進行校驗。校驗規則由前面說的commitlint.config.js 配置文件來指定。
配置后,我們測試下,先提交不規范的 commit:
加上開頭的 commit 類別 type,再提交,成功了:
實戰:使用 lint-staged 格式化要暫存區的文件
lint-staged 是一個命令行工具,它能夠對 git 的 staged(暫存區)中的文件使用 linter 工具格式化,修復一些風格問題,并再次添加到 staged 上。
一個經典的搭配是,配合 husky 的 pre-commit 鉤子將文件 格式化后再提交。pre-commit 在真正 commit 前觸發,配合上 lint-staged,就能做一些風格的修正。
使用 lint-staged 強制提交的文件做格式化適用的場景:
- 一些團隊成員使用的編輯器沒有或未安裝格式化插件,代碼不能在保存后自動格式化,容易提交風格錯誤的代碼;
- 項目開發了一段時間才引入了代碼風格規范,希望一點點修正。如果一次性全部格式化,可能會有不少需要手動修復的風格;
下面我們開始配置。
首先我們安裝 lint-staged:
然后新增 pre-commit 鉤子,內容為 npx lint-staged:
因為提交的文件有多種類型,比如 js、md、less、mdx 等。所以我們還需要配置一下,針對不同類型文件使用不同的 linter。
lint-commit 的配置可以放到 package.json,也可以放到專門的配置文件里。我選擇后者,在項目根目錄創建一個 .lintstagedrc.js 文件,然后加上以下內容:
這里表示指定在 src 目錄下 js、jsx、ts、tsx 后綴文件,使用 eslint 做格式化。我只使用 eslint 做 js 和 ts 的格式化,其他的就不管了,你可以考慮用過 prettier 格式化它們。
這里有一個 Github 可以參考,地址為:
https://github.com/F-star/xigua-ui。
結尾
husky 是一個很有用的工具,能夠利用 git hook 在本地 commit 時,配合 eslint 等 linter 工具做文件的格式化,并配合 commitlint 校驗 commit 信息格式,是工程化統一代碼風格的一大利器。