为什么我改了 ESLint 配置但 `lint-staged` 没生效?一次诡异的调试记录

365 阅读3分钟

背景

在前端项目中,lint-staged 是非常常见的工具,我们经常用它配合 husky 实现提交前的自动代码检查和修复流程。在一次日常开发中,我遇到了一个诡异的现象

我修改了 eslint.config.js,添加了一些规则。但在执行 npm run lint-staged 时,发现 ESLint 根本没有使用我的新配置,而是仍然报着老的规则错误。

我百思不得其解,甚至一度怀疑是 ESLint 缓存出了问题,试图清除缓存、重启进程,甚至重装依赖,但问题依然存在。

直到我深入了解了 lint-staged 的工作机制,才终于发现真相(耗时1h)。


现象回顾

  1. 修改了 eslint.config.js,比如添加或关闭某条规则。
  2. 运行 npm run lint-staged
  3. 意外发现:执行结果仍然基于旧配置。
  4. 检查 eslint.config.js 文件,惊讶地发现:在运行 lint-staged 的那一瞬间,文件内容“变回”了旧的版本,执行完又恢复了回来。

真相揭秘:lint-staged 运行的是暂存区的代码!

这个现象其实和 lint-staged核心设计理念有关:它的目标是只校验你即将提交(即已 git add)的代码,而不是当前工作区中所有修改。

为此,它做了一个聪明又容易让人误解的事情:

lint-staged 的工作流程:

  1. 提取暂存区(staged)的文件列表
  2. 将当前工作区(未暂存的修改)用 git stash 临时备份
  3. 对暂存区文件运行配置的任务;
  4. 执行完成后 还原未暂存的工作区内容
  5. 如果有问题,终止提交。

关键点是:

  • 如果你修改了配置文件(如 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 的语义设计,不建议用作常规方案。


最佳实践建议

  1. 每次修改 lint 配置后,git add 再运行 lint-staged
  2. 可以写一个辅助脚本或 husky 检查,提示开发者配置文件未被暂存。
  3. 避免对配置文件频繁修改未提交的情况下测试 lint-staged,容易造成误判。

总结

看似简单的 lint-staged 流程,隐藏着许多自动化的设计细节。它不是“配置没生效”,而是你误解了它只运行暂存区的代码,从而在不经意间引发了「配置变了但没被识别」的问题。

希望这篇文章能帮你在工作中更好地理解 lint-staged 的原理,避免类似的踩坑。