构建前端代码预提交检查(Husky、Lint-staged)

9,675 阅读6分钟

构建前端代码预提交检查(Husky、Lint-staged)

Image by max_duz

引言

大家是否有过类似的经历,接手多人开发的项目,因为每个人的代码风格不一致,使得变得难以阅读,比如分号、混合单引号和双引号的字符串声明,或者糟糕的缩进? 或者一些问题导致项目运行出错。

所以代码一致性非常重要,无论是在开发阶段还是在维护阶段,我们都知道eslint能很好保证代码风格一致性。

当发现每次 commit 的时候总是提交完了才发现少了一个分号,或者代码有格式问题。然后进行提交代码、会引发团队成员编译项目出错或者代码格式错误。为了避免这种出错,每次提交代码的时候,对代码进行预提交检查(pre-commit)来防止,并且规范提交日志,如果发现问题,将停止提交。

预提交检查

什么是预提交检查(pre-commit) 预提交检查在提交更改并运行 git commit 之后和完成提交之前运行。如果检查失败,则不进行提交并显示错误,而如果所有检查都通过,则正常进行提交。

为什么要运行预提交检查? 预提交检查通常用于运行 linting 脚本和测试,允许每次提交都尽可能干净。lint-staged文档状态,防止“💩 滑入你的代码库!”。

提交规范

每次进行 git 提交时,需要写提交说明,规范提交说明的好处如下

  • 更加结构化的提交历史
  • 保证每次信息都有确切的含义
  • 方便直接生成 changelog
  • 方便信息搜索和过滤

Angular 提交信息规范

目前最受开发人员肯定的规范是前端框架 Angular 提出的 Angular 提交信息规范

提交格式如下:

<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>

每次提交可以包含页眉(header)、正文(body)和页脚(footer),每次提交必须包含页眉内容

每次提交的信息不超过 100 个字符

详细文档:AngularJS Git Commit Message Conventions

提交类型指定为下面其中一个:

build:主要目的是修改项目构建系统(例如 glup,webpack,rollup 的配置等)的提交
ci:主要目的是修改项目继续集成流程(例如 Travis,Jenkins,GitLab CI,Circle等)的提交
docs:文档更新
feat:新增功能
merge:分支合并 Merge branch ? of ?
fix:bug 修复
perf:性能, 体验优化
refactor:重构代码(既没有新增功能,也没有修复 bug)
style:不影响程序逻辑的代码修改(修改空白字符,格式缩进,补全缺失的分号等,没有改变代码逻辑)
test:新增测试用例或是更新现有测试
revert:回滚某个更早之前的提交
chore:不属于以上类型的其他类型

构建预提交钩子

使用 ESLintPrettierlint-staged 设置 Husky 预提交钩子,以避免错误的提交并在提交之前正确格式化代

  • Husky 防止错误的 git commitgit push 和更多 🐶 woof!
  • ESLint 查找并修复 JavaScript 代码中的问题
  • Prettier 代码格式化程序、支持多种语言
  • Commitlint 检查您的提交消息是否符合常规的提交格式
  • Commitizen 提交规范消息格式提示

Eslint

npm i --save-dev eslint babel-eslint

创建.eslintrc.js 文件

module.exports = {
  root: true,
  extends: [
    // 插件 (根据项目实际情况安装自定义插件)
    'plugin:vue/recommended',
    'plugin:prettier-vue/recommended',
    'prettier/vue',
  ],
  parserOptions: {
    parser: 'babel-eslint',
  },
  rules: {
    // eslint规则
  },
}

Prettier

npm install --save-dev prettier eslint-plugin-prettier eslint-config-prettier

创建.prettierrc.js文件

module.exports = {
  semi: false,
  singleQuote: true,
  trailingComma: 'none',
}

如项目已安装EslintPrettier则直接跳过此步骤

Husky

npm install --save-dev husky lint-staged

package.json添加配置

"husky": {
  "hooks": {
    "pre-commit": "lint-staged"
  }
},
"lint-staged": {
  "*.{js,jsx,vue}": [
    "prettier --write ./src",
    "eslint --ext .vue,.js,.jsx --fix ./src",
    "git add"
  ]
}

husky 会在你 git commit的时候,调用 pre-commit 钩子,执行 lint-staged,如果代码不符合 prettier 配置的规则,会进行格式化;然后执行 eslint 的规则进行检查,如果有不符合规则且无法自动修复的,就会停止此次提交。

Commitlint

commitlint
commitlint
# Install commitlint cli and conventional config
npm install --save-dev @commitlint/{config-conventional,cli}

# For Windows:
npm install --save-dev @commitlint/config-conventional @commitlint/cli

创建commitlint.config.js

echo "module.exports = {extends: ['@commitlint/config-conventional']};" > commitlint.config.js

package.json添加 Husky's 'commit-msg' hook 要在创建提交之前先完成提交,可以使用 Husky 的'commit-msg'挂钩:

"husky": {
  "hooks": {
    "pre-commit": "lint-staged",
    "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
  }
}

Commitizen

commitizen
commitizen

首先,安装 commitizen cli 工具

npm install commitizen  --save-dev

下一步,安装 cz-conventional-changelog工具

npm install cz-conventional-changelog --save-dev

最后在 package.json 添加 npm script 脚本命和配置

"scripts": {
  "commit": "git-cz",
},
"config": {
  "commitizen": {
    "path": "cz-conventional-changelog"
  }
}

如果您可以通过更改一些文件并运行以下命令、测试 commitlintcommitzen

git add .
npm run commit

如果一切正常,您将在终端中看到以下信息:

> git-cz

cz-cli@4.2.1, cz-conventional-changelog@3.2.0

? Select the type of change that you're committing: (Use arrow keys)
❯ feat:     A new feature
  fix:      A bug fix
  docs:     Documentation only changes
  style:    Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colon
s, etc)
  refactor: A code change that neither fixes a bug nor adds a feature
  perf:     A code change that improves performance
(Move up and down to reveal more choices)

构建使用

使用 husky

现在,当您尝试提交任何更改时,先执行git add.npm run commit规格提交日志,然后在执行 eslintprettier 规则,如果有更改,它将给您错误,并阻止您执行任何错误的提交。如果一切正常、则顺利提交代码

➜  test_demo git:(develop) ✗ git add .
➜  test_demo git:(develop) ✗ npm run commit

> git-cz

cz-cli@4.2.1, cz-conventional-changelog@3.2.0

? Select the type of change that you're committing: fix:      A bug fix
? What is the scope of this change (e.g. component or file name): (press enter to skip) npmscript
? Write a short, imperative tense description of the change (max 84 chars):
 (15) 修复npm run fix命令
? Provide a longer description of the change: (press enter to skip)

? Are there any breaking changes? No
? Does this change affect any open issues? No

husky > pre-commit (node v10.16.3)
⚠ Some of your tasks use `git add` command. Please remove it from the config since all modifications made by tasks will be automatically added to the git commit index.

ℹ No staged files match any configured task.
husky > commit-msg (node v10.16.3)
[develop 10bfcec] fix(npmscript): 修复npm run fix命令
 1 file changed, 1 insertion(+), 1 deletion(-)

禁用 husky

某一次提交想要禁用 husky,可以添加参数--no-verify

git commit --no-verify -m "xxx"

参考资料

本文使用 mdnice 排版