ESLint + Husky 如何只扫描发生改动的文件?

背景

最近公司对代码质量抓得很严, 出台了一系列组合拳:

  1. 制定前端编码规范
  2. 在本地使用git提交代码时进行代码质量检查
  3. 在CI/CD流水线上, 用sonarQube设置了一个代码质量达标阈值,不达标的话无法构建部署
  4. 除了运用工具之外,还增加了定期的CodeReview
  5. 单元测试,线上合并代码时用大模型进行CodeReview也在路上...

今天先说说,在本地使用git提交代码时进行代码质量检查如何实现。现在进入主题

Step1 配置ESLint校验规则

在这一步,踩了一个大坑。现在安装ESLint, 安装的都是ESLint v9.x版本,ESLint v9+的配置文件与之前不太一样了。不管是问大模型,还是上网搜,搜出来的ESLint安装配置方式90%以上都是ESLint V8及以下版本的配置方法。按照那种方式配,会吃很多瘪。

能看懂的,简单一点的报错比如说:

  • .eslintignore文件不再被支持,应该在 eslint.config.jseslint.config.ts 配置文件中,使用 ignores 属性来指定哪些文件或目录需要被忽略。 (node:13688) ESLintIgnoreWarning: The ".eslintignore" file is no longer supported. Switch to using the "ignores" property in "eslint.config.js": https://eslint.org/docs/latest/use/configure/migration-guide#ignoring-files (Use node --trace-warnings ... to show where the warning was created) Oops! Something went wrong! :( ESLint: 9.25.1)

  • 改成ignores又报错, 对象字面量只能指定已知属性,并且"ignores"不在类型"ESLintConfig"中,被大模型忽悠了一回。在 ESLint 9.x 中,应该使用 ignorePatterns 来指定要忽略的文件或文件夹,而不是 ignores

  • jiti包版本不匹配, 需要升级 Oops! Something went wrong! :( ESLint: 9.25.1 Error: You are using an outdated version of the 'jiti' library. Please update to the latest version of 'jiti' to ensure compatibility and access to the latest features.

  • 未安装eslint-define-config模块 Oops! Something went wrong! :( ESLint: 9.25.1 Error: Cannot find module 'eslint-define-config'

不太容易看懂的报错比如说 ESLint 没有找到适用于文件 src/main.ts 的配置规则。0:0 warning File ignored because no matching configuration was supplied , 按照大模型的提示,逐一检查了ESLint 配置文件的路径是否正确,确保 root: true 配置生效; TypeScript 和 Vue 插件及解析器配置是否正确; ignorePatterns 是否误忽略了 src 文件夹; 检查 tsconfig.json 中的 include 配置; 手动检查文件是否被 ESLint 正确解析

bash 复制代码
pnpm eslint --config ./eslint.config.ts src/main.ts

忙活了一圈,未能解决问题。大模型排查技术工具最新版本的故障问题能力偏弱。无奈只能在网上搜,一篇一篇的看与试错。最终验证通过是方案是采用@eslint/config生成eslint v9版本的配置文件。

bash 复制代码
pnpm create @eslint/config

做7个选择(每个选项的含义一眼就能看懂)之后,就能妥妥地生成eslint配置文件。

Step2 配置Husky

这一步比较简单,虽然Husky最新版本的配置方法与先前的版本不一样了。但新版本的配置比老版本的要简单一些。

✅ 1. 安装Husky v9+版本

csharp 复制代码
pnpm add -D husky

✅ 2. Husky v9+版本初始化

csharp 复制代码
npx husky init

这会自动:

  • 创建 .husky/ 目录
  • .husky/下添加 pre-commit hook 示例
  • 在package.json中添加 "prepare": "husky install" 脚本

这一步有个小坑,就是如果npx husky init第一次因为某种原因运行失败,第二次再运行,不会生成.husky目录。解决方法也很简单粗暴,卸载husky重新安装。

✅ 3. 在package.json配置检查指令

sql 复制代码
{
  "scripts": {
    "lint": "run-s lint:*",
    "lint:eslint": "eslint src/**/*.{ts,tsx,vue}  --debug --cache",
    "lint:prettier": "prettier --check ./",
    "lint:style": "stylelint \"src/**/*.{vue,css,less}\" --fix",
  },
}

✅ 4. 修改 .husky/pre-commit hook

bash 复制代码
# 检查指令
pnpm lint

Step3 配置ESLint增量检测

为什么要配置增量检测呢,原因有两点:

  1. ESLint全量检测执行的很慢,如果不加--debug参数,很长一段时间,看不到任何输出,会让人误以为卡死了
  2. 开发业务功能的时间本来就捉襟见肘,对于已有项目,当期要偿还历史技术债务的话,时间不允许。

那么如何做增量检查呢?最质朴的思路就是利用git能监测暂存区代码变更的能力,然后利用ESlint对变更的文件执行代码质量检查。这里有两处要注意一下,一是检查暂存区变更的文件,要过滤掉删除的文件,只检查新增,修改,重命名,复制的文件。另外,当没有匹配类型的文件时,files=$(git diff --cached --name-only --diff-filter=AMRC | grep -E '\.(ts|tsx|vue)$')会抛出一个exit 1的异常,造成改了(ts|tsx|vue)之外的文件不能正常提交,所以要在后面加一个|| true进行兜底。

bash 复制代码
#!/bin/bash
# set -e
# set -x
trap 'echo "Error at line $LINENO"; exit 1' ERR

# 注意这里加了 || true
files=$(git diff --cached --name-only --diff-filter=AMRC | grep -E '\.(ts|tsx|vue)$' || true)

if [ -z "$files" ]; then
  echo "No changed ts/tsx/vue files to check."
  exit 0
fi

echo "Running ESLint on the following files:"
echo "$files"

# 用 xargs -r 只有在有输入时才执行
echo "$files" | xargs -r npx eslint

echo "All files passed ESLint."
exit 0

Step4 测试效果

修改 src 下的某个 main.ts 文件,故意触发代码质量问题,然后提交。

  • 情形1 通过命令行提交,eslint校验未通过,阻断提交,且是增量校验。
bash 复制代码
git add . && git commit -m "测试"
  • 情形2 通过UI界面提交,成功阻断提交

至此大功告成,结果令人满意,如果你的项目也需要实现这样的功能的话,拿走不谢。

相关推荐
艾小逗2 小时前
vue3中的effectScope有什么作用,如何使用?如何自动清理
前端·javascript·vue.js
小小小小宇4 小时前
手写 zustand
前端
Hamm5 小时前
用装饰器和ElementPlus,我们在NPM发布了这个好用的表格组件包
前端·vue.js·typescript
小小小小宇6 小时前
前端国际化看这一篇就够了
前端
大G哥6 小时前
PHP标签+注释+html混写+变量
android·开发语言·前端·html·php
whoarethenext6 小时前
html初识
前端·html
小小小小宇6 小时前
一个功能相对完善的前端 Emoji
前端
m0_627827526 小时前
vue中 vue.config.js反向代理
前端
Java&Develop6 小时前
onloyoffice历史版本功能实现,版本恢复功能,编辑器功能实现 springboot+vue2
前端·spring boot·编辑器
白泽talk6 小时前
2个小时1w字| React & Golang 全栈微服务实战
前端·后端·微服务