新版 husky 使用
husky 在前端工程化是一个必不可少的工具,用于在项目里添加 git hooks,在 commit 前校验代码规范、commit 信息规范等。
v6 版本之前
安装相关依赖
yarn add -D husky lint-staged
然后在 package.json 直接配置
{
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "node scripts/verify-commit-msg.js"
}
},
"lint-staged": {
"*.{js,vue}": [
"npm run lint",
"git add"
]
}
}
在 scripts 配置校验 commit-msg 的脚本 scripts/verify-commit-msg.js
v6 版本以前是这么配置的。
新版工作原理
v6 版本之后的 husky 的配置方式全部都变了
新版工作原理:
使用了从 git 2.9 开始引入的一个新功能 core.hooksPath。core.hooksPath 可以让你指定 git hooks 所在的目录而不是使用默认的 .git/hooks/。这样 husky 可以使用 husky install 将 git hooks 的目录指定为 .husky/,然后使用 husky add 命令向 .husky/ 中添加 hook。通过这种方式我们就可以只添加我们需要的 git hook,而且所有的脚本都保存在 .husky/ 目录下,因此也就不存在同步文件的问题了。
新版 husky 实践
1、 precommit 会用到 lint-staged,所以还要安装
yarn add -D husky lint-staged
2、在 package.json 添加一个 prepare script
{
"scripts": {
"prepare": "husky install"
}
}
3、然后执行 prepare
yarn prepare
husky – Git hooks installed
就会发现项目根目录增加了一个文件夹 .husky/ 并指定该目录为 git hooks 所在的目录。
而 prepare 脚本会在 npm install / yarn(不带参数)之后自动执行,也就是说当我们克隆项目安装完依赖后会自动执行 husky install 命令。
4、添加 pre-commit git hook
npx husky add .husky/pre-commit "npx --no-install lint-staged"
可以发现 .husky/ 目录下新增了 pre-commit 脚本,内容如下:
. "$(dirname "$0")/_/husky.sh"
npx --no-install lint-staged
也就是在执行 git commit 前会先执行 pre-commit 脚本
5、上面在 git commit 前会执行 npx --no-install lint-staged,这一步需要配置 lint-staged。
在项目根目录新建 .lintstagedrc.json,配置内容跟以前在 package.json 一样
{
"*.{js,jsx,vue,ts,tsx}": [
"eslint --fix"
],
"*.{vue,css,scss}": [
"stylelint --fix"
]
}
这样就会执行代码校验了
6、添加 commit-msg git hook,校验每次提交的信息规范
以前在 package.json 配置的 commit-msg 是这样
{
"husky": {
"hooks": {
"commit-msg": "node scripts/verify-commit-msg.js --name=$HUSKY_GIT_PARAMS"
}
}
}
现在新版的 $HUSKY_GIT_PARAMS 变量已不再使用,取而代之是 $1
所以配置 commit-msg 脚本如下
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
# Previous HUSKY_GIT_PARAMS environment variable is replaced by native params $1, $2, etc.
node scripts/verify-commit-msg.js --name=$1
此时添加了两个脚本

再配置校验脚本 scripts/verify-commit-msg.js
const chalk = require('chalk')
const args = require('minimist')(process.argv.slice(2))
const msgPath = args['name']
const msg = require('fs')
.readFileSync(msgPath, 'utf-8')
.trim()
const commitRE = /^(revert: )?(feat|fix|polish|docs|style|refactor|perf|test|workflow|ci|chore|types|build)((.+))?: .{1,50}/
if (!commitRE.test(msg)) {
console.log()
console.error(
` ${chalk.bgRed.white(' ERROR ')} ${chalk.red(
`invalid commit message format.`
)}nn` +
chalk.red(
` Proper commit message format is required for automated changelog generation. Examples:nn`
) +
` ${chalk.green(`feat(compiler): add 'comments' option`)}n` +
` ${chalk.green(
`fix(v-model): handle events on blur (close #28)`
)}nn` +
chalk.red(
` You can also use ${chalk.cyan(
`git cz`
)} to interactively generate a commit message.n`
)
)
process.exit(1)
}
大功告成,执行一次 commit,可以看到钩子执行过程



