(注:文末有直接集成两个工具的方法,与单独集成不冲突。)
一、husky
注:本文引入的 husky 都是 8.0.0 以上的版本,老版本的使用可能与下文描述的不一致!
1. husky 是什么?
husky 的 README 开篇是这么描述的:
Modern native Git hooks made easy (轻松创建现代化的原生 git hooks) Husky improves your commits and more 🐶 woof!
最重要的就是:它可以在项目中植入你设定的 git hooks,在 git 提交代码的前后,你预设的 git hooks 可以得到执行,以对代码、文件等进行预设的检查,一旦检查不通过,就可以阻止当前的代码提交,避免了不规范的代码和 git 提交出现在项目中。
git hooks 是本地的,不会被同步到 git 仓库里。为了保证每个人的本地仓库都能执行预设的 git hooks,于是就有了 husky。
2. husky 的特性
husky 的 官方文档 是这么描述的 (直译):
- 零依赖,轻量级的 (6k)
- 由 git 的新特性提供支持
- 遵循关于 npm 和 Yarn 自动安装的最佳实践
- 提供用户友好的消息提示
- 提供可选的安装
- husky 4 支持:
- macOS, Linux, Windows 三大操作系统
- Git GUI
- 自定义目录
- monorepo
官方文档 列举了非常多牛X轰轰的项目在使用 husky。
3. 引入 husky
这里先介绍如何引入单独的 husky,下文会介绍如何同时引入 husky 和 lint-staged。如果你期望同时引入这两个工具,可以忽略这一小节。
3.1 空项目
如果还没有创建项目,你可以通过以下命令中的某一条,来初始化一个带有 husky 的项目:
npx husky-init # npm
npx husky-init # Yarn 1
yarn dlx husky-init --yarn2 # Yarn 2+
pnpm dlx husky-init # pnpm
上面的命令执行完之后,只需要再执行安装依赖的命令即可:
npm install # npm
yarn # Yarn
pnpm install # pnpm
这是官方推荐的做法。如果你想在目前已有的项目中引入 husky,可参考下一节。
3.2 已有项目
要想在已有的项目中使用 husky,可按如下步骤操作:
-
安装 husky
npm i husky -D # npm yarn add husky -D # yarn pnpm i husky -D # pnpm
-
启用 git hooks
npx husky install # npm pnpx husky install # pnpm
-
加入 husky prepare 命令
- 直接在
package.json
的scripts
里加上如下命令:{ "scripts": { "prepare": "husky install" } }
- 直接在
4. husky 的使用
前置知识:git hooks
git hooks 的分类如下
- 客户端 hooks
- 提交工作流
pre-commit
prepare-commit-msg
commit-msg
post-commit
- email 工作流
applypatch-msg
pre-applypatch
post-applypatch
- 其它
pre-rebase
post-rewrite
post-checkout
post-merge
pre-push
pre-auto-gc
- 提交工作流
- 服务器端 hooks
pre-receive
update
post-receive
注意:在客户端 hooks 中,developer 可以通过
git comiit -m "commit message" -n
(-n 等价于 --no-verify) 来忽略掉pre-commit
hook 的执行!
使用 husky
使用 husky 的时候,我们通常只关注 提交工作流 的几个 hooks,用得最多的一个是 pre-commit
。
使用 hosky 的时候,通常是用它来创建一系列的 git hooks,并在对应的文件中撰写 shell
脚本代码。
下面是官方示例中的一个,创建了 pre-commit
hook 文件。
- 创建一个 hook:
husky add <file> [cmd]
- file: 指定保存命令的文件,通常是在
.husky
目录下 - cmd: 指定 git hooks 的名字,最常使用的是
pre-commit
# 创建一个 pre-commit 的 hooks 文件 npx husky add .husky/pre-commit "npm test" # npm pnpx husky add .husky/pre-commit "npm test" # pnpm git add .husky/pre-commit # 创建好这个文件之后,你就可以根据你的需要去编写这个 shell 脚本了
- file: 指定保存命令的文件,通常是在
二、lint-staged
1. lint-staged 是什么?
背景
随着 Web 前端开发的逐渐大前端化,Web 前端项目的体积变得越来越大,一个项目的参与者也越来越多,对代码规范、代码检查的要求越来越高。因此越来越多的项目要求 developer 在提交代码之前,必须让自己的代码通过如 ESLint, Stylelint 等代码格式化工具的格式化 (规范化)。
在起初的开发过程中,项目小,代码量少,全量跑一次 lint 的时间也相对较短。但随着项目体量的增大,全量跑一次 lint 的时间越来越长。而我们都知道,如果每一个人提交的代码都是通过了 lint 工具的格式化,那么在一次提交的时候,可能没有规范化的文件,就仅仅是当前 developer 即将提交的这些。如果在一次提交的时候,只对这一部分代码做规范化,那将大大缩短 developer 提交代码的速度,于是就诞生了一个工具:lint-staged
。
介绍
通过这个工具诞生的背景,我们可以知道, lint-staged
是一个专门用于在通过 git
提交代码之前,对暂存区的代码执行一系列的格式化。当 lint-staged
配合 git hooks 使用时,可以在 git 提交前的 hook 中加入 lint-staged
命令,这样就能在提交代码之前,对即将提交的代码进行格式化,成功之后就会提交代码。
2. 引入 lint-staged
直接执行下面的脚本来安装 lint-staged
即可。
npm i lint-staged -D # npm
yarn add lint-staged -D # yarn
pnpm i lint-staged -D # pnpm
3. lint-staged 的使用
配置方式:
package.json
中的lint-staged
配置项- JSON 风格或 YML 风格的
.lintstagedrc
.lintstagedrc.json
.lintstagedrc.yaml
.lintstagedrc.yml
.lintstagedrc.mjs
或.lintstagedrc.config.mjs
.lintstagedrc.cjs
或.lintstagedrc.config.cjs
lint-staged.js
或lint-staged.config.js
以 package.json
为例:
{
"lint-staged": {
"<glob-pattern>": <command>
}
}
-
<command>
可以是单个命令的字符串,也可以多个命令组成的数组。使用 js 作为配置文件时,还可以是导出一个如下类型的函数:(filenames: string[]) => string | string[] | Promise<string | string[]>
虽然配置好了 lint-staged
,但目前还不能自动地使用它,因为通常它是放在 Git 的 pre-commit 阶段去执行,因此要在 .husky/pre-commit 文件中增加执行 lint-staged
的命令
# 如果使用的是 npm/yarn 且 npm 版本为 v8 及以下,就加下面的命令
npx lint-staged
# 如果使用的是 npm/yarn 且 npm 版本为 v9 及以上,就加下面的命令
npm exec lint-staged
# 如果使用的是 pnpm,就加下面的命令
pnpm exec lint-staged
# ! 注意,上面的这三个命令必须根据实际情况来选择,且只能存在一个
三、安装 husky 与 lint-staged 命令
注:版本更新
版本更新后,直接执行命令
npx mrm@2 lint-staged # npm/yarn
pnpx mrm@2 lint-staged # pnpm
时,只会补充 husky
和 lint-staged
的命令,不再安装这两个依赖。
因此如果想同时集成这两个依赖,还需在上述命令执行完之前,先执行如下命令:
npm i husky lint-staged -D # npm
yarn add husky lint-staged -D # yarn
pnpm i husky lint-staged -D # pnpm
3.1 集成方式
二者的官方都推荐了使用 mrm
这个库来同时集成 husky 和 lint-staged。
在你的项目根目录下,直接执行如下命令:
npx mrm@2 lint-staged # npm/yarn
pnpx mrm@2 lint-staged # pnpm
执行命令之后,你就会看到你的 package.json
里多了一个 lint-staged
配置项,且根目录下多了一个 .husky
目录,里面就包含了 pre-commit 文件,里面包含了一个最基础的命令:npx lint-staged
。
在后续的开发工作中,任何需要在 pre-commit 阶段执行的命令,都可以添加到 .husky/pre-commit 文件中。
四、总结
本文详细介绍了 husky 和 lint-staged 的集成。成功集成这两个工具之后,在项目根目录下会多出 .husky 目录,在 package.json
中会多出 lint-staged 配置项。
在 .husky/pre-commit 文件中存在
附:npx 查找规则
- 去
/node_modules/.bin
目录下查找是否存在对应的命令,如果没有找到则执行第 2 步; - 去查找全局安装的命令里是否有对应的命令,如果没有找到则执行第 3 步;
- 创建一个临时目录,下载命令对应的依赖,然后执行这个命令,完成之后就删除这个临时目录。
了解了这个规则之后,就可以放心地使用 npx
来执行一些命令了。如果期望项目里的命令在每一个 developer 那里都能有相同的表现,墙裂建议在项目内统一安装对应的 dependency。