husky 原理
Install
yarn install husky lint-staged -D
Usage
.git
directory andpackage.json
are at them same level
npm set-script prepare "husky install"
npm run prepare
Add a hook:
npx husky add .husky/pre-commit "yarn lint-staged"
Edit package.json
"scripts": {
"lint-staged": "lint-staged",
"prepare": "husky install",
"lint": "eslint --ignore-path .gitignore \"**/*.{js,jsx}\"",
"lint:fix": "yarn lint --fix"
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"yarn lint:fix"
],
"*.css": [
"prettier --write"
]
}
.git
directory andpackage.json
are not at them same level. For example,project/.git
andproject/front/package.json
.
npm set-script prepare "cd .. && husky install front/.husky"
npm run prepare
Add a hook:
npx husky add .husky/pre-commit "cd front && yarn lint-staged"
Edit package.json
"scripts": {
"lint-staged": "lint-staged",
"prepare": "cd .. && husky install front/.husky",
"lint": "eslint --ignore-path .gitignore \"**/*.{js,jsx}\"",
"lint:fix": "yarn lint --fix"
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"yarn lint:fix"
],
"*.css": [
"prettier --write"
]
}
For more detail you can see in typicode.github.io/husky/#/?id…
源码解析
- bin.ts
运行 husky install
时调用了 insdex.ts
里的 instal 方法,该方法接收一个 dir 参数,允许通过命令行传入 .husky
的目录(当 .git
和 package.json
不在同一级目录时有用)。
export function install(dir = '.husky'): void {
// Ensure that we're inside a git repository
if (spawnSync('git', ['rev-parse']).status !== 0) {
l('not a Git repository, skipping hooks installation')
return
}
// Custom dir help
const url = 'https://typicode.github.io/husky/#/?id=custom-directory'
// Ensure that we're not trying to install outside of cwd
if (!resolve(process.cwd(), dir).startsWith(process.cwd())) {
throw new Error(`.. not allowed (see ${url})`)
}
// Ensure that cwd is git top level
if (!existsSync('.git')) {
throw new Error(`.git can't be found (see ${url})`)
}
try {
// Create .husky/_
mkdirSync(join(dir, '_'), { recursive: true })
// Create .husky/.gitignore
writeFileSync(join(dir, '.gitignore'), '_\n')
// Copy husky.sh to .husky/_/husky.sh
copyFileSync(
fileURLToPath(new URL('./husky.sh', import.meta.url)),
join(dir, '_/husky.sh'),
)
// Configure repo
const { error } = spawnSync('git', ['config', 'core.hooksPath', dir])
if (error) {
throw error
}
} catch (e) {
l('Git hooks failed to install')
throw e
}
l('Git hooks installed')
}
做了几件事:
- a. 确保当前在一个 git repository 里
- b. 确保 dir 在当前目录里
- c. 确保当前目录存在
.git
目录 - d. 创建
.husky
目录,复制husky.sh
到.husky/_/husky.sh
,每次提交都会触发这个脚本,用于实时展示一些信息。 - e.
git config core.hooksPath
配置到.husky
,这样在git commit
前就会触发.husky/pre-commit
,从而执行里面的脚本