前端项目集成husky + lint-staged + commitlint
简述
husky 提供git hooks(钩子)操作
lint-staged 针对git暂存区中的文件应用代码检查与格式化修复
commitlint 严格约束git commit的提交信息,保证统一规范
我下面的做的事情就是利用husky提供的钩子操作,在代码推送到本地git暂存区时,做代码风格格式化,并对commit时提交的描述信息进行规范约束
1. 安装husky
husky没有复杂的东西,简单来说就是单文件对应git hooks的钩子
pnpm add --save-dev husky
运行此命令会在本地生成.husky文件夹,和一些基础的文件
pnpm exec husky init
之后在这个文件夹中创建钩子文件,目前我只用到了两个,仅客户端侧的钩子 ,这两个文件建议还是手动创建吧,因为在通过
echo “npm run commitlint ${1}” > .husky/commit-msg 命令创建的文件,在实际执行的出问题了,是创建文件时的编码问题,它自动创建的是utf-16的编码,导致运行的时候失败了,我们默认自己创建的文件都是utf-8
pre-commit 在用户输入提交信息之前触发(执行 git commit 后立即运行)作用:提交的代码检查阶段
commit-msg 在用户输入提交信息之后触发(提交信息已生成但未最终提交)作用: 提交的信息校验阶段
2. 安装lint-staged
这些具体不写了,看这篇文章
前端项目集成lint-staged
安装完成后,在pre-commit文件中添加对应的命令,如果按照上面这篇文章下来的话,在package.json的scripts中是由lint-staged命令的,而且该功能是可以正常使用的,因为在上面的文章中已经做过测试,确保pnpm lint-staged命令是能生效的。
这里再来测试一次,看看使用 git commit -m “test” 有没有效果
准备三个测试文件
使用 git add . 将其添加入git暂存区
运行 git commit -m “test” ,可以看到代码运行完毕后,对应的测试文件都被成功的修复了错误,证明功能没问题
3. 安装commitlint
pnpm add -D @commitlint/cli @commitlint/config-conventional conventional-changelog-angular @commitlint/format @commitlint/cz-commitlint
@commitlint/cli 提供命令行接口(CLI),用于校验 Git 提交信息是否符合预设规则
@commitlint/config-conventional 定义提交信息的校验规则,确保每次提交符合约定格式(如 type(scope): subject)
conventional-changelog-angular 解析符合 Angular 规范的提交历史,自动生成版本变更日志(CHANGELOG.md)
@commitlint/format 格式化 commitlint 的校验结果输出,提升可读性。
@commitlint/cz-commitlint 基于 Commitizen 的交互式提交引导工具,通过问答生成规范提交消息。
提供配置文件 (commitlint.config.js)
提示词这部分的配置我直接在 ’@commitlint/config-conventional‘这个包里面复制出来的。给他改成中文了。这样在后面通过交互工具访问的时候更加直观
const Configuration = {/** 继承 `@commitlint/config-conventional` 的预设规则* 需确保已安装该依赖(通过 npm/yarn/pnpm)*/extends: ['@commitlint/config-conventional'], // 引用社区通用的提交规范/** 指定提交信息解析器,这个标准是最常用吧,开源库和中大项目都用这个,比如vue,那我也用这个* 需确保已安装对应依赖*/parserPreset: 'conventional-changelog-angular', // 用于解析提交消息的语法规则/** 指定输出格式化工具为 `@commitlint/format`* 需确保已安装该依赖*/formatter: '@commitlint/format', // 控制校验结果的显示格式[10](@ref)/** 自定义忽略条件(函数形式)* 此处忽略空提交消息(例如 `git commit -m ""`)*/ignores: [(commit) => commit === ''], // 返回 `true` 时跳过校验[10](@ref)/** 是否启用默认忽略规则* 默认忽略合并提交(Merge)、回滚提交(Revert)等[10](@ref)*/defaultIgnores: true,/** 校验失败时显示的帮助文档链接*/helpUrl: 'https://github.com/conventional-changelog/commitlint/#what-is-commitlint', // 引导用户查阅文档[6](@ref)/** 交互式提交提示的配置* 可自定义提示信息和问题描述* 我一定要给换成中文,这个是从@commitlint/config-conventional复制出来的,我把里面的英文改成中文了* 也可以给他删了,直接用@commitlint/config-conventional中的*/prompt: {questions: {type: {description: '选择您要提交的更改类型',enum: {feat: {description: '新增功能(如模块、组件、接口等)',title: '新功能',emoji: '✨'},fix: {description: '修复代码缺陷(如逻辑错误、边界条件问题等)',title: '缺陷修复',emoji: '🐛'},docs: {description: '仅文档变更(如 README、API 文档、注释等)',title: '文档',emoji: '📚'},style: {description: '代码格式调整(空格/缩进/分号等,**不改变运行逻辑**)\n⚠️ 注意:CSS 样式修改属于功能变更,请用 `feat`/`fix`',title: '代码格式调整',emoji: '💎'},refactor: {description: '代码重构(既非新功能也非缺陷修复,如优化结构、重命名等)',title: '代码重构',emoji: '📦'},perf: {description: '性能优化(如算法改进、缓存机制、渲染效率提升等)',title: '性能优化',emoji: '🚀'},test: {description: '测试相关(新增/修改单元测试、E2E 测试等)',title: '测试相关',emoji: '🚨'},build: {description: '构建系统变更(如 Webpack/Vite 配置、npm 依赖更新等)',title: '构建系统变更',emoji: '🛠'},ci: {description: '持续集成配置变更(如 GitHub Actions/Jenkins/Travis 脚本等)',title: '持续集成(CI)',emoji: '⚙️'},chore: {description: '其他杂项变更(如工具链调整、配置文件修改等,不涉及代码逻辑)',title: '其他杂项变更',emoji: '♻️'},revert: {description: '回滚某次错误提交(需注明被回滚的 Commit Hash)',title: '回滚提交',emoji: '🗑'}}},scope: {description: '影响范围(如模块名、组件名、文件名等,示例: `login`, `button`, `utils`)'},subject: {description: '简短描述变更内容(使用命令式语气,如『修复XX问题』而非『修复了XX问题』)'},body: {description: '详细说明变更原因与实现细节(可选,复杂变更建议填写)'},isBreaking: {description: '是否包含破坏性变更?(会导致其他代码不兼容的修改)'},breakingBody: {description: '请详细描述破坏性变更的影响及迁移方案(格式: `BREAKING CHANGE: <说明>`)'},breaking: {description: '破坏性变更摘要(示例: `移除旧API XX`)'},isIssueAffected: {description: '是否关联未关闭的 Issue?(如修复 Bug 或实现需求)'},issuesBody: {description: '请说明变更与 Issue 的关联性(可选)'},issues: {description: '关联的 Issue 编号(格式: `fix #123`, `close #456`)'}}}
}export default Configuration
增加pageage.json中scripts的脚本命令
这里第一个是实现基本功能的,而第二个是用来使用交互工具的方式使用commitlint
"commitlint": "commitlint --edit","commit": "git-cz"
编辑husky钩子
这个 \ 是windows中的写法,更多内容看commitlint的文档
4. 测试
两个方式都试一下,我还是喜欢交互工具的那种方式,一项一项选的直观且方便多了
1.普通提交方式
-
创建测试文件a.txt。没有内容,目前只是往缓存区提交一点内容,不然都无法commit
-
尝试运行 git commit -m “错误提交” ,这是一定会失败的,因为提交信息格式不正确,比如未指定当前操作类型等。
-
尝试运行 git commit -m “docs: 正确提交” ,可以看到指定了类型后,提交就通过了
2.交互工具
直接运行刚才定义的脚本,往暂存区放文件的操作就不贴了
pnpm commit
可以看到非常方便,一项一项选,不可能选错的