为代码保驾护航之husky+lint-staged+stylelint+commitlint

593 阅读5分钟

概念简介

husky: husky是一个git钩子管理工具,它可以帮助开发者在git提交代码时自动执行一些操作,例如:代码格式化代码检查单元测试等。其工作原理是通过在git仓库中添加钩子脚本来实现的。

lint-staged: 针对暂存的git文件运行linters,通过这样,可以确保没有错误进入存储库并强制执行的代码样式。lint运行在整个项目上会很慢,开发者也只想对提交的文件进行lint,所以lint-staged内包含一个脚本,该脚本以暂存的文件列表作为参数运行shell任务。

commitlint: 帮助您的团队遵守提交约定,允许在git历史添加更多语义。例如:type, scopebreaking changes

stylelint: 一个强大的css过滤器,能够帮助我们避免错误并强制执行约定。

开始实战

这里我们用create-react-app创建一个项目。

npx create-react-app my-app

1.安装husky

Automatic(推荐) husky-init是使用husky快速初始化项目的一次性命令。

npx husky-init && npm install        # npm
npx husky-init && yarn               # Yarn 1 
yarn dlx husky-init --yarn2 && yarn  # Yarn 2+ 
pnpm dlx husky-init && pnpm install  # pnpm
1.1 生成脚本

运行上面代码成功后会自动在packjson.json中添加prepare脚本,并在根目录生成一个.husky的文件。默认情况下,它将在你提交时运行npm test

{
  "scripts": {
    "prepare": "husky install"
  }
}

.husky目录结构如下

my-app
└───.husky
│   └───pre-commit       
│
└───src

pre-commit脚本内容如下:

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

# 这里我们先将npm test 改成 npx --no-install lint-staged 
npx --no-install lint-staged 
1.2 新增husky钩子commit-msg

接下来在.husky下添加另外的钩子,请使用husky add

例如:

npx husky add .husky/commit-msg 'npx --no -- commitlint --edit "$1"'

commit-msg脚本内容如下:

#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx --no -- commitlint --edit "$1"

当我们想绕过husky钩子提交时,可以使用Git `-n/--no-verify'

git commit -m 'first commit' --no-verfiy

2.安装lint-staged

npm install --save-dev lint-staged
2.1 新增命令

package.json文件中新增lint-staged命令

{
  "scripts": {
    "lint-staged": "lint-staged"
  }
}
2.2 lint-staged配置方式

lint-staged可以通过多种方式配置:

  • lint-staged配置在package.json
  • .lintstagerc使用JSON或者YML格式的文件,或者明确使用文件扩展名:
    • .lintstagerc.json
    • .lintstagerc.yaml
    • .lintstagerc.yml
  • .lintstagedrc.mjslint-staged.config.mjsESM格式文件
    • 默认导出值应该是一个配置:export default { ... }
  • .lint-staged.config.js.lintstagedrc.js用于ESM或者CommmonJS格式的,具体取决于package.json里面是否包含"type":"module"选项。

在这里,我们以package.json文件中配置为例

{
  "lint-staged": {
    "src/**/*.less": "stylelint --syntax less"
  }
}

此时,我们在使用git commit命令时,就会对暂存区的文件执行"lint-staged"里面的命令了。

这个时候项目还未安装stylelintcommit后会报错。接下来让我们来安装stylelint

3.安装stylelint

使用npm安装Stylelint和配置:

npm install --save-dev stylelint stylelint-config-standard-scss

这里还有其它不错的配置,根据自己情况选择。比如:@umijs/fabric/dist/stylelint

3.1 创建stylelint配置文件

在项目根目录创建一个.stylelintrc.json配置文件,内容如下:

{
  "extends": "stylelint-config-standard-scss"
}
3.2 运行stylelint
npx stylelint "**/*.{css,less}"

单独运行上面命令或者使用git commit提交项目修改的文件。

此时,我们就能看到命令窗口有一些错误:

image.png

此时,我们可以点击文件路径跳转到相关页面,根据报错信息,逐一修改。

4.添加新命令

这个时候我们完善package.json里面lint-staged命令为:

  "lint-staged": {
    "**/*.less": "stylelint --syntax less",
    "**/*.{js,jsx,ts,tsx}": "npm run lint-staged:js",
    "**/*.{js,jsx,ts,tsx,less,md,json}": [
      "prettier --write"
    ]
  }
4.1 安装prittereslint

注意:这里我们使用了Prettier和Eslint,如果项目已经下载则不需要安装,没有我们执行下面命令进行安装。

npm install --save-dev --save-exact prettier

npm init @eslint/config

package.jsonscripts里新增一条命令:

"lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx ",

上面几个命令是当我们在使用git提交暂存代码时,就会执行lint-staged里的linters配置,首先使用stylelint检查.less相关文件。然后在对.{js,jsx,ts,tsx}文执行eslint检查。最后在对.{js,jsx,ts,tsx,md,json}文件使用prettier格式化它们。

完成上面步骤后,就可以对我们暂存区的文件代码进行代码检查代码美化了。然后就是commit代码,接下来就是接入commilint对我们提交的代码信息做规范。

5. 安装commitlint

npm install --save-dev @commitlint/config-conventional @commitlint/cli

和

// 将config-conventional设置为commitlint的常规配置
echo "module.exports = { extends: ['@commitlint/config-conventional'] };" > commitlint.config.js

安装commitlintcommit-config-*作为开发依赖配置并在commitlint使用。

或者可以在commitlint.config.js.commitlintrc.js 、 .commitlintrc 、  .commitlintrc.json 、 .commitlintrc.yml 文件或 package.json 中的 commitlint 字段中定义配置。

5.1 提交格式

git commit提交信息内容格式如下:

<type>: <subject>

type类型一般有以下几种:

类型描述
build编译相关的修改,例如发布版本、对项目构建或者依赖的改动
chore其他修改, 比如改变构建流程、或者增加依赖库、工具等
ci持续集成修改
docs文档修改
feat新特性、新功能
fix修改bug
perf优化相关,比如提升性能、体验
refactor代码重构
revert回滚到上一个版本
style代码格式修改, 注意不是 css 修改
test测试用例修改

例子:

git commit -m 'feat: 新增xxx功能'
git commit -m 'fix: 修复某个bug'
5.2 手动修改配置
/**
* feature:新功能
* update:更新某功能
* fixbug:修补某功能的bug
* refactor:重构某个功能
* optimize: 优化构建工具或运行时性能
* style:仅样式改动
* docs:仅文档新增/改动
* chore:构建过程或辅助工具的变动
*/
module.exports = {
  extends: [
    '@commitlint/config-conventional'
  ],
  rules: {
    'type-enum': [2, 'always', [
      'feature', 'update', 'fixbug', 'refactor', 'optimize', 'style', 'docs', 'chore'
    ]],
    'type-case': [0],
    'type-empty': [0],
    'scope-empty': [0],
    'scope-case': [0],
    'subject-full-stop': [0, 'never'],
    'subject-case': [0, 'never'],
    'header-max-length': [0, 'always', 72]
  }

// 如有更多定制化规则,详情请看https://commitlint.js.org/#/reference-rules

最后,我们就完成了这些配置。团队小伙伴们在协作提交代码时就会更加规范了。