一、先搞懂:lint-staged 到底是个啥?

简单说:lint-staged 是一个 “只对 Git 暂存区文件执行命令” 的工具 🛠️

● 「暂存区文件」:就是你执行git add后,准备提交的那些文件(没 add 的文件它不管);
● 「核心作用」:提交代码前,自动对这些修改后的文件做 lint 检查(如 ESLint)、格式美化(如 Prettier),有错误就拦截提交,避免不规范代码进仓库;
● 「为啥必须用」:如果直接执行eslint .,会检测整个项目的所有文件(哪怕没修改),Monorepo 项目动辄十几个包,全量检测要等半天!而 lint-staged 只盯你改的文件,速度快到飞起~

举个🌰:你改了packages/ui/Button.tsx并git add,lint-staged 只会对这个文件执行 ESLint+Prettier,其他没动的文件完全不碰,效率直接拉满!

官方定义:lint-staged runs linters against staged git files and don’t let
💩 slip into your codebase!(不让垃圾代码溜进代码库~)

二、核心优势:为啥 Monorepo 项目离不开它?

  1. 速度快:只检测暂存区文件,比全量 lint 快 10 倍 +,大型项目体感差距超明显;
  2. 不折腾:自动修复格式错误(如缩进、引号),不用手动改,省时间;
  3. 强制规范:有无法修复的错误(如语法错误)直接拦截提交,确保代码库整洁;
  4. 灵活配置:支持多文件类型(JS/TS/JSON/MD)、多命令组合,适配 Monorepo 多包结构。

三、实战教程:3 步搞定 lint-staged 配置(Monorepo 专属)

以 pnpm workspace 项目为例,全程复制命令就行,不用懂原理~

3.1 第一步:安装依赖(已装过的跳过)

在项目根目录执行,把 lint-staged 和配套工具一起装了:

若用pnpm(推荐)

pnpm add -Dw lint-staged eslint prettier eslint-config-prettier eslint-plugin-prettier

若用yarn

yarn add -D lint-staged eslint prettier eslint-config-prettier eslint-plugin-prettier

鱼姐小贴士:-Dw是 pnpm 专属,意思是 “作为开发依赖安装到根目录”,Monorepo 项目统一在根目录管理依赖,子包不用单独装~

3.2 第二步:配置 lint-staged(关键!)

有 2 种配置方式,选一种就行,推荐第一种(直接写在 package.json 里,简单方便):

方式 1:在 package.json 中配置(推荐)

打开根目录的package.json,添加lint-staged字段,按文件类型指定要执行的命令:

{
  "lint-staged": {
    // 1. JS/TS/JSX/TSX文件:先eslint自动修复,再prettier格式化
    "packages/**/*.{js,jsx,ts,tsx}": [
      "eslint --fix", // 自动修复可修复的lint错误(如未使用变量、引号不统一)
      "prettier --write" // 格式化代码(如缩进、分号)
    ],
    
    // 2. JSON/MD文件:只做prettier格式化
    "packages/**/*.{json,md}": [
      "prettier --write"
    ],
    // 3. CSS/SCSS文件:可选,需要装stylelint
    "packages/**/*.{css,scss}": [
      "stylelint --fix",
      "prettier --write"
    ]
  }
}

方式 2:单独创建配置文件(适合复杂配置)

在根目录创建.lintstagedrc.js文件,内容如下:

module.exports = {
  "packages/**/*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],
  "packages/**/*.{json,md}": ["prettier --write"],
  "packages/**/*.{css,scss}": ["stylelint --fix", "prettier --write"]
};

Monorepo 专属优化:按包拆分配置(可选)
如果想让不同包执行不同规则(比如 ui 包要检测 CSS,core 包不用),可以这样写:

{
  "lint-staged": {
    "packages/core/**/*.{js,ts}": ["eslint --fix"], // core包只做JS/TS lint
    "packages/ui/**/*.{js,ts,css}": ["eslint --fix", "stylelint --fix", "prettier --write"], // ui包多检测CSS
    "packages/web-app/**/*.{js,tsx}": ["eslint --fix", "prettier --write"] // 应用包检测TSX
  }
}

3.3 第三步:关联 Husky,提交时自动触发

lint-staged 不会自己跑,需要配合 Husky 的pre-commit钩子(提交前触发),之前的教程里已经配置过,这里再补一遍关键步骤:

1. 若未初始化Husky,先执行(已初始化的跳过)

npx husky install
pnpm pkg set scripts.prepare=“husky install” # 安装依赖后自动启用Husky

2. 添加pre-commit钩子,触发lint-staged

npx husky add .husky/pre-commit ‘npx lint-staged’
原理:当你执行git commit(或pnpm run commit)时,Husky 会先触发pre-commit钩子,执行npx lint-staged,对暂存区文件做校验,没问题才允许提交~

四、怎么用?日常开发只需要 3 步!

配置好后,平时开发完全不用管 lint-staged,跟着正常流程走就行:

步骤 1:修改文件并暂存

比如修改了ui包的Button组件

git add packages/ui/src/Button.tsx

步骤 2:执行提交(和平时一样)

用之前配置的交互式提交

pnpm run commit

或直接用git commit(也会触发)

git commit -m "feat(ui): 优化Button组件样式"

步骤 3:观察结果

● ✅ 若代码没问题:直接提交成功,不用任何操作;
● ✅ 若有可修复错误(如格式问题):lint-staged 自动修复,然后提交成功;
● ❌ 若有无法修复的错误(如语法错误、未定义变量):提交被拦截,终端会显示错误信息,按提示修改后重新提交。

终端成功示例:

✔ Preparing lint-staged...
✔ Running tasks for staged files...
✔ Applying modifications from tasks...
[feature/ui-button 1234567] feat(ui): 优化Button组件样式
 1 file changed, 5 insertions(+), 3 deletions(-)

终端错误示例(需修复):

✖ eslint --fix found some errors. Please fix them and try committing again.
packages/ui/src/Button.tsx
  10:5  error  'unusedVar' is assigned a value but never used  no-unused-vars

解决方案:删除未使用的变量unusedVar,重新git add并提交~

五、高级技巧:让 lint-staged 更好用

技巧 1:添加调试模式,排查问题

如果 lint-staged 不生效,或想看看它检测了哪些文件,加–debug参数:
npx lint-staged --debug
终端会输出详细日志,比如哪些文件被匹配、执行了什么命令,方便排查配置问题。

技巧 2:禁用并发执行(解决冲突)

默认情况下,lint-staged 会并行执行多个任务(比如同时处理 JS 和 CSS 文件),如果出现冲突,可设置为串行执行:

{
  "lint-staged": {
    "concurrent": false, // 禁用并发,按顺序执行任务
    "packages/**/*.{js,ts}": ["eslint --fix"],
    "packages/**/*.{css,scss}": ["stylelint --fix"]
  }
}

技巧 3:允许空提交(特殊场景)

默认情况下,如果 lint-staged 自动修复后,暂存区文件为空(比如只改了格式,修复后和原文件一致),会拦截提交。如果需要允许空提交,加–allow-empty参数:

修改Husky的pre-commit钩子

npx husky add .husky/pre-commit 'npx lint-staged --allow-empty'

技巧 4:在 CI/CD 中使用(如 GitHub Actions)

之前的 CI/CD 配置里已经用到了,直接在 workflows 文件中执行:

  • name: 执行lint
    run: npx lint-staged # 或 pnpm lint-staged(需在package.json配置脚本)
    这样 PR 提交时,CI 会自动执行 lint-staged,确保远程分支代码也符合规范~

六、常见问题:鱼姐踩过的坑(必看)

坑 1:lint-staged 不生效,提交时没反应

● 原因 1:没关联 Husky 的 pre-commit 钩子,或钩子命令写错;
● 解决方案:重新执行npx husky add .husky/pre-commit ‘npx lint-staged’,检查.husky/pre-commit文件内容是否正确;
● 原因 2:文件没加入暂存区(没执行git add);
● 解决方案:先git add文件,再执行提交。

坑 2:Monorepo 中只检测部分包的文件

● 原因:配置的文件路径不对,没匹配到所有包;
● 解决方案:用packages//*匹配所有包的文件,而不是src//*(只匹配根目录 src)。

坑 3:prettier 和 ESLint 规则冲突(比如引号、分号)

● 原因:两者规则不一致(如 ESLint 要求双引号,Prettier 要求单引号);
● 解决方案:安装eslint-plugin-prettier,让 ESLint 继承 Prettier 规则,在.eslintrc.js中添加:

extends: [
  "eslint:recommended",
  "plugin:prettier/recommended" // 关键:让ESLint遵循Prettier规则
]

坑 4:执行时提示 “command not found: eslint/prettier”

● 原因:依赖没装对,或没装在根目录;
● 解决方案:在根目录重新执行安装命令(pnpm add -Dw …),确保依赖出现在根目录的node_modules中。

最后总结:lint-staged 用起来真的香!
其实 lint-staged 的核心就是 “精准打击”—— 只处理你修改的文件,既保证了代码规范,又不浪费时间,Monorepo 项目用它,提交速度能快一倍~

配置一次,终身受益,团队里不管是新手还是老鸟,都不用再操心格式问题,Code Review 时也能专心看业务逻辑,不用纠结 “缩进不对”“引号不统一” 这种琐事~

如果你的项目是 lerna 架构,或需要配置特殊规则(比如忽略某些文件、自定义命令),可以评论区告诉我你的场景,鱼姐给你定制配置!觉得有用的宝子,记得收藏 + 点赞,关注鱼姐,前端工程化踩坑不迷路~❤️

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐