如何提高代码(格式)交付质量

785 阅读7分钟

前言

在日常迭代更新中,经常会出现因为代码格式引起的返工,造成了大量的时间浪费,同时让进行CR的人员承担了许多额外的工作(会被打的)。本文主要讲如何利用 huskylint-staged工具将这一现象消灭在上传服务前,保证每一个pr都是完美的的pr( 至少看起来是😀 )

代码格式与个人书写习惯(臭毛病)也有较大关系,需要时间来磨合

起因

正常来说在我们使用了eslint等代码规范工具后,这种情况应该会消失,但是事实并非如此,主要原因有以下两点:

  1. 长期维护项目中堆积了大量的历史包袱,造成eslint无法准确提醒到本应提醒的问题。
  2. eslint是软约束,只是在提醒用户应该怎么去做,并不会强制约束代码格式。

解决方式

为了杜绝因为代码格式引起的代码返工,除了对自身的书写提出要求之外(想都不要想)。

还可以借助外力(不约束都要飞天了),也就是约束工具,在代码交付之前进行格式检查,格式正确后方可进行上传。

食用方法

先介绍一下具体的操作步骤,后面再介绍所用的工具及其原理。

  1. 安装必备工具

运行以下命令前请确定你已经安装并初始化了git仓库初始化了eslint,并处于项目路径中

# 安装必备包
$ npm install -D husky lint-staged eslint-plugin-diff
# yarn 安装
$ yarn add husky lint-staged eslint-plugin-diff
# 初始化git hooks
$ npx husky install
# 添加对应的pre-commit
$ npx husky add .husky/pre-commit "npx lint-staged"

image.png 2. 添加配置项

在你的eslint配置项中加入eslint-plugin-diff

    "extends": [
        "plugin:diff/diff"
    ]

在package内添加lint-staged配置

  "lint-staged": {
    // 这里检查常用的js相关文件
    "**/*.js": "eslint --ext .js",
  }
  1. 大功告成!

尝试写一些无法通过eslint的改动,然后添加到staged池中进行测试,你就能体验到被束缚的快乐了😂

原理

利用githooks机制,在执行commit之前,检查所有修改过的地方,进行eslint检查,eslint检查通过后放可提交commit,从根源上杜绝的不规范的代码生成。

由此便引出了本篇文章的主角:【husky】与【lint-staged

工具介绍

【husky】

Modern native Git hooks made easy

食用方法

首先是安装与配置

在运行以下命令前请确定你安装了git,并且当前目录处于你的项目中

# 初始化husky
$ npx husky install
# 添加git hook其他hooks同理
$ npx husky add .husky/pre-commit "echo commit来啦"

经过上面一顿操作后,在每次commit前都会打印一句“commit来啦”,😀

image.png

如果想要添加其他hooks同理,如果想要修改后续的hooks文件,可以在项目根目录下找到.husky/pre-commit的文件,直接进行修改即可

原理

husky的源码很简单啦,总共不到100行,就是通过命令帮你生成git hooks。

下面简单的介绍下git hooks。git 在执行每个操作(commit,push等)前都有一个钩子,通过钩子运行脚本,只要脚本的退出值不为0,那就中断接下来的动作,

注:在linux进程概念中,不同的退出值代表了进程不同的状态,退出值为0则代表程序正常运行,退出值为其他则代表了错误的出现。详细的可以看这篇文章【进程退出码

由控制退出值来达到我们想要的出现错误就会停止动作的效果。

比如在pre-commit钩子内写入

#!/bin/sh
echo 你以后别想commit了!
exit 1

那么git永远都无法提交新的commit了,我们利用echo的自定义提示,这样我们在使用 vsc,idea等git工具操作时也会有提示值。

image.png 利用这个钩子我们可以达到我们想要的各种提交前的代码检查。

比如:检查commit 信息 是否符合规范

首先添加commit-msg钩子(这个钩子会传入commit的message)

#!/bin/sh
# 利用shell将参数传入js脚本文件
(cd $(dirname "$0"); node check-commit.js  $1)

再在.husky目录下创建check-commit.js文件,编写为

// 引入所需包
const fs = require("fs");
const path = require("path");
const { exit } = require("process");
const [, , $1] = process.argv;
// 读取commit的message
const commit = fs.readFileSync(path.join("..", $1),'utf-8');
// 正则表达式
const reg = /#(FEAT|FIX|STYLE|CR)(:|:)【ID[0-9]+】.*/;
// 不通过就提示
if(!reg.test(commit)){
    console.log(`${commit}不符合规范!`);
    // 退出值为非零
    exit(1);
}
// 通过就退出返回值为0
exit(0);

这时我们再进行commit,便会对我们的commit信息进行检查

image.png

我们尝试一条正确的commit信息

image.png

就大功告成啦!

扩展

利用hooks与脚本,可以做到很多事情,无论是代码规范,检查commit信息,代码美化,上传前的必要检查等。 当然也有许多现成的库供大家使用,比如:【reviewdog】【commitlint】等工具,有很多封装好的完善功能。

同时,利用这一工具还可以检查其他语言,或者在上传commit前进行一些其他操作,至于怎么使用就看想象力啦。

(什么?你问我为什么不直接用完善的工具?我要是早点能知道这些工具就不会写这篇文章了)

有兴趣的也建议了解下。


【🚫💩lint-staged】

从作者的图标就知道对于💩代码有多深恶痛绝了,啊哈哈

Run linters against staged git files and don't let 💩 slip into your code base!

lint-staged会对你载入staged中的所有文件根据后缀名开启一个任务队列,顺序的运行命令,其中还有很多额外的参数可以调试。详细可以查看官方文档

食用方法

在运行以下命令前请确定你安装了git与全局eslint,并且当前目录处于你的项目中

# 全局安装方便后续使用
$ npm install -g lint-staged
# cnpm 安装
$ cnpm install -g lint-staged
# yarn 安装
$ yarn add -g lint-staged

在pack.json内添加对应配置文件,每次运行lint-staged都会从package.json中读取配置,根据配置的文件,运行命令,支持利用数组顺序的运行多个命令

  "lint-staged": {
    // 这里检查常用的js相关文件
    "**/*.js": "eslint --ext .js",
    // 利用数组顺序运行多个命令
    "**/*.js": ["eslint --ext .js","echo 啊哈哈哈"]
  }

随便向staged里面添加一个文件

image.png

运行以下命令

# 手动运行lint-staged
$ npx lint-staged

它就会对载入staged里面每一个符合规则的文件运行eslint进行检查了

image.png

扩展

有了husky与lint-staged这两个工具,我们将其组合起来,便能达到每次commit之前便强制运行eslint检查。


【eslint-plugin-diff】

Run ESLint on your changed lines only. Now with CI support!

有了上面两个工具

如果我的项目是一个长期项目,总是需要在老文件中修改怎么办?那eslint岂不是要把我淹没了。这时候就需要借助eslint的插件了!

eslint-plugin-diff能够帮助我们只对修改过的地方进行eslint检查,太棒啦!

食用方法

在运行以下命令前请确定你安装了git与全局eslint,并且当前目录处于你的项目中

$ cnpm install eslint-plugin-diff

然后将插件添加进你的eslint配置中

module.exports = {
    "env": {
        "browser": true,
        "es2021": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:react/recommended",
        // 这里是新添加的配置项!
        "plugin:diff/diff"
    ],
    "parserOptions": {
        "ecmaFeatures": {
            "jsx": true
        },
        "ecmaVersion": 12,
        "sourceType": "module"
    },
    "plugins": [
        "react"
    ]
};

我们这时再运行eslint,就会发现只会检查staged池内改动部分的代码啦

image.png

扩展

eslint-plugin-diff有两种对比模式

  1. diff/diff 与之前的commit进行比较
  2. diff/staged 只检查进入staged池的文件 实际使用中可以根据项目的要求进行选择,大部分情况下选择diff/diff模式即可

拓展

虽然这套配置可以解决代码上传前的问题,但是它并不是一个完美的方案。

因为eslint-plugin-diff插件的原因,vscode与其他ide的eslint插件不会再提示没有加入到staged的文件,导致每次上传前的修改过程是极其痛苦的。

目前想到的解决方案是创建两个不同的eslint配置文件,一个用于提醒,一个专门用来检查错误,后续也会尝试编写eslint插件进行优化。

还有就是目前的配置方法比较麻烦,后面也会尝试着使用自动化脚手架进行一键配置。

没有解决方案是完美的,只有不断进化的解决方案