Skip to content

本章主要说明结合了 Git HooksNPM Hookshusky 仓库。

以实现在 git commit 操作时对代码进行 lint-staged 操作。

1.yorkie & husky

1-1.yorkie

yorkieforkhusky 的项目。目前较新版本是yorkie@2.0.0

  1. 项目中执行 git init,以支持 yorkie.git/hooks 目录下创建 hooks 文件。

  2. 它内置了 install 生命周期钩子,在安装该依赖包时,会自动在 .git/hooks 目录下注册所有可用 hooks

  3. 用户在使用时,需要在 package.json 中定制化声明 Git Hooks,譬如:

json
{
	"gitHooks": {
		"pre-commit": "lint-staged"
	},
	"lint-staged": {
		"*.{js,jsx,vue}": ["vue-cli-service lint", "git add"]
	}
}

这样,在执行 git commit 时,就会触发 pre-commit 钩子。

要注意的的一点,由于 yorkie 依赖 .git 目录,所以在安装 yorkie 之前,最好保证当前项目目录已经执行 git init 命令,创建了 .git 目录

如果说,先安装了 yorkie,后执行了 git init。那么你可以手动执行 yorkiebin/install.js 文件进行补救:

shell
node "node_modules/yorkie/bin/install.js"

另外 yorkie@2.0.0pnpm 存在兼容性问题,因为在 yorkie源码中有如下设置:

js
const isInSubNodeModule = (depDir.match(/node_modules/g) || []).length > 1
if (isInSubNodeModule) {
	return console.log(
		"trying to install from sub 'node_module' directory,",
		'skipping Git hooks installation'
	)
}

而当使用 pnpm 安装 yorkie 时,实际的 depDir 目录会是 /Users/xxx/projects/test-yorike/node_modules/.pnpm/yorkie@2.0.0/node_modules/yorkie(因为 pnpm 使用了文件短链接的缘故)。

这样就会导致上述逻辑拦截,从而跳过 Git Hooks 的安装。

解决办法是使用yorkie-pnpm

实际上,yorkie-pnpmyorkiefork 项目,专门用于解决 yorkiepnpm 的兼容性问题。

可见此处具体的PR

1-2.husky

较新版本的husky 已经不推荐 autoinstall

譬如笔者在测试中使用的版本是husky@^8.0.3

新版本的 husky 使用方式有两种:

  1. 第一种是利用 npx husky-init

  2. 第二种是手动安装 husky,然后配置 Git Hooks

详见安装husky

安装完成后,执行 git config -l 会发现 core.hookspath=.husky

如果要卸载 husky 的话,执行:

shell
npm uninstall husky && git config --unset core.hooksPath

然后你可以根据实际需求,抉择是否删除 .husky 目录:

shell
rm -rf .husky

husky 根据 git 提供的 core.hooksPath 创建了 .husky 目录,不再依赖 .git 目录

但由于映射关系的存在,同样需要先利用 git init 创建 .git 目录

2.yorkie of vue-cli

yorkieforkhusky,在安装时,会 autoinstall

假设 vue-app-gitvue-app-not-git 都是利用 vue create 创建的项目。

二者的唯一区别是,vue-app-git 是在本机检测有 git 的情况下安装的,而 vue-app-not-git 则是在本机检测没有 git 的情况下安装的。

上述区别是通过更改全局包 @vue/cli-shared-utils 中的 hasGit 函数返回值实现的。

vue-app-gitvue-app-not-git 都是选择了 lint on commit,但实际执行,会发现:

  1. vue-app-gitgit commit 会触发检测。
  2. vue-app-not-gitgit commit 则不会触发检测。

这是因为当 yorkie 在安装会自动执行,但在 vue-app-not-git 下没有找到 .git 目录,也就无法在 .git/hooks 下注入执行脚本。

3.Notes

3-1.prepare

scripts 下定义了 prepare 生命周期钩子。

但利用 yarn add yorkie -D 时,prepare 会触发,而 npm install yorkie --save-dev 并不会触发。

执行 npm install 会触发 prepare 生命周期钩子。

3-2.install & uninstall

scripts 下定义了 installuninstall

但为什么触发 installuninstall 时,并没有打印 node bin/install.js 中的 console 呢?

答案是npm 版本相关

测试了下,pnpm@7.33.6 在安装或者卸载包时,不会触发 installuninstall 生命周期钩子。

因此 vue-app-git-pnpm 目录下的 git commit 不会触发 pre-commit 钩子。

4.NPM Life Cycle Scripts

查看 NPM 支持的生命周期钩子:life-cycle-scripts

5.Git Hooks

查看 Git 支持的钩子:Git Hooks