背景
在前端项目中,lint-staged 是非常常见的工具,我们经常用它配合 husky 实现提交前的自动代码检查和修复流程。在一次日常开发中,我遇到了一个诡异的现象:
我修改了
eslint.config.js,添加了一些规则。但在执行npm run lint-staged时,发现 ESLint 根本没有使用我的新配置,而是仍然报着老的规则错误。
我百思不得其解,甚至一度怀疑是 ESLint 缓存出了问题,试图清除缓存、重启进程,甚至重装依赖,但问题依然存在。
直到我深入了解了 lint-staged 的工作机制,才终于发现真相(耗时1h)。
现象回顾
- 修改了
eslint.config.js,比如添加或关闭某条规则。 - 运行
npm run lint-staged。 - 意外发现:执行结果仍然基于旧配置。
- 检查
eslint.config.js文件,惊讶地发现:在运行lint-staged的那一瞬间,文件内容“变回”了旧的版本,执行完又恢复了回来。
真相揭秘:lint-staged 运行的是暂存区的代码!
这个现象其实和 lint-staged 的核心设计理念有关:它的目标是只校验你即将提交(即已 git add)的代码,而不是当前工作区中所有修改。
为此,它做了一个聪明又容易让人误解的事情:
lint-staged 的工作流程:
- 提取暂存区(staged)的文件列表;
- 将当前工作区(未暂存的修改)用
git stash临时备份; - 对暂存区文件运行配置的任务;
- 执行完成后 还原未暂存的工作区内容;
- 如果有问题,终止提交。
关键点是:
- 如果你修改了配置文件(如
eslint.config.js)但没有执行git add,那对lint-staged来说,它看不到你的新配置。 - 它会临时 stash 掉你修改的配置文件(因为它没进入暂存区),然后运行那份旧的(staged)版本。
怎么解决呢
方法一:改完配置后 git add
这是最简单有效的方式。
git add eslint.config.js
npm run lint-staged
这样 lint-staged 就能“看到”你最新的配置,并正常运行。
方法二:临时禁用 lint-staged 的 stash 功能
你可以在配置中禁用 stash 功能,这样就不会恢复老的文件版本:
npx lint-staged --no-stash
或者在 package.json 里配置:
"lint-staged": {
"config": {
"stash": false
}
}
⚠️ 注意:禁用 stash 意味着你也会 lint 到未暂存的改动,失去了
lint-staged精准控制提交内容的初衷,不推荐长期使用。
方法三:在任务中显式处理配置文件(不推荐)
有些人可能会在任务中加入以下内容,来强行恢复配置:
"*.{js,ts,vue}": [
"git restore --staged eslint.config.js",
"eslint --fix ."
]
但这其实是绕过了 lint-staged 的语义设计,不建议用作常规方案。
最佳实践建议
- 每次修改 lint 配置后,先
git add再运行lint-staged。 - 可以写一个辅助脚本或 husky 检查,提示开发者配置文件未被暂存。
- 避免对配置文件频繁修改未提交的情况下测试
lint-staged,容易造成误判。
总结
看似简单的 lint-staged 流程,隐藏着许多自动化的设计细节。它不是“配置没生效”,而是你误解了它只运行暂存区的代码,从而在不经意间引发了「配置变了但没被识别」的问题。
希望这篇文章能帮你在工作中更好地理解 lint-staged 的原理,避免类似的踩坑。