Pre-commit钩子在前端项目中的实践与踩坑经验分享

百里淑涵 工具 阅读 2,280
赞 18 收藏
二维码
手机扫码查看
反馈

又踩坑了,pre-commit 怎么突然不工作了?

前两天我在项目里加了一个 pre-commit 钩子,用来跑 ESLint 校验代码。本来一切正常,但今天提交代码时,发现 pre-commit 突然不生效了!折腾了半天才发现问题出在哪。

Pre-commit钩子在前端项目中的实践与踩坑经验分享

简单说下解决方案吧:

  • 第一步是检查 .husky/pre-commit 文件是否存在并且配置正确。
  • 第二步是确认 package.json 中的 scripts.husky 字段是否被误删。
  • 最后一步也是最关键的,如果你用的是 pnpm,需要确保在安装依赖时加上 –shamefully-hoist 参数。

核心代码就这几行:

# 确保 Husky 安装正确
npx husky install

# 初始化 pre-commit 钩子
npx husky add .husky/pre-commit "npm run lint"

为什么突然失效?原因分析

事情是这样的:前几天团队里新来了个小伙伴,他负责优化项目的依赖管理。他说原来的 node_modules 结构太乱了,建议我们切换到 pnpm。我当时觉得挺好,pnpm 确实能节省磁盘空间,速度也快一些。

结果就是从那之后,pre-commit 就挂了。我一开始还以为是 Husky 的版本问题,因为最近确实升级了几个依赖。于是我开始翻文档、查 issue,甚至还重新初始化了一遍 Husky:

# 重新初始化 Husky
rm -rf .husky
npx husky-init

但问题依旧存在,pre-commit 还是没反应。

踩坑提醒:pnpm 的依赖提升是个大坑

这里我踩了个坑:pnpm 默认不会把依赖提升到顶层 node_modules。这就导致 Husky 找不到它需要的一些依赖包。

折腾了半天发现,解决办法其实很简单——只需要在安装依赖的时候加上 –shamefully-hoist 参数:

pnpm install --shamefully-hoist

这个参数会强制把所有依赖都提升到顶层 node_modules,虽然违背了 pnpm 的设计理念,但对于像 Husky 这种需要全局访问依赖的工具来说,这是必须的。

排查过程中的其他小插曲

中间我还试过几种方案,比如手动修改 .husky/pre-commit 文件:

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

# 确保路径正确
npm run lint

后来试了下发现还是不行,原因是 Husky 依赖的一些二进制文件(比如 eslint)在 pnpm 的默认结构下根本找不到。

另外,我还怀疑是不是 Git 的问题,于是检查了一下 Git 的 hooks 路径:

bash
git config core.hooksPath
`>

结果显示路径没问题,指向的就是 .husky 目录。

最后实在没办法了,去查了下 pnpm 的官方文档,才发现这个 –shamefully-hoist 参数。名字起得挺有意思,直译过来叫“羞耻地提升”,哈哈。

以上是我踩坑后的总结

总结一下,这次的问题主要是因为 pnpm 的依赖隔离机制和 Husky 的依赖查找方式不兼容导致的。解决办法就是用 –shamefully-hoist 参数强行把依赖提升到顶层。

不过这里也有个小问题:即使加了这个参数,有些依赖还是会偶尔报错,尤其是那些动态 require 的模块。但我目前还没找到更好的办法,只能先这样用了。

如果你有更好的方案,欢迎评论区交流!顺便吐槽一句,pnpm 的这种设计虽然节省空间,但对新手真的不太友好。

本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。
发表评论

暂无评论