3

1340.640.jpg

引言

上篇文章前端面试必备-eslint篇在结尾处给了vue-cli配置eslint与git钩子的代码,但是估计你心中还是有很多疑问,为什么这么配,怎么自定义配置,为什么配置不能生效。莫急,看完这篇文章,估计你就真的会了。

git钩子简介

1.是什么

和其它版本控制系统一样,Git 能在特定的重要动作发生时触发自定义脚本。 有两组这样的钩子:客户端的和服务器端的。 客户端钩子由诸如提交和合并这样的操作所调用,而服务器端钩子作用于诸如接收被推送的提交这样的联网操作。

2.为什么

随心所欲地运用这些钩子,能增加我们对程序的控制力,能实现更多的功能。

3.用法

在当前项目 .git/hooks下有很多钩子.sample文件,这里只讲pre-commit钩子

pre-commit 钩子在键入提交信息前运行。 它用于检查即将提交的快照,例如,检查是否有所遗漏,确保测试运行,以及核查代码。 如果该钩子以非零值退出,Git 将放弃此次提交

去掉.simple 再git commit的时候钩子就会生效

4.编写一个git hook小脚本

删掉pre-commit里面的内容,我们通过shell编程可以编写脚本。

// pre-commit文件
echo "在git commit 之前执行脚本"

在控制台输入git commit 我们可以看到控制台打印这句话
至此,我们完成了一个最简单的钩子脚本编写

eslint与git钩子

1.工程化

在开发团队中为了保持团队所使用钩子一致,维护起来算是比较复杂的,因为 .git/hooks 目录不随你的项目一起拷贝,也不受版本控制影响。
简单的解决办法是把钩子文件存放在项目的实际目录中(在.git 外),这样就可以像其他文件一样进行版本控制,然后在.git/hooks中创建一个链接,或者简单地在更新后把它们复制到.git/hooks目录下。

具体做法是在根目录下创建pre-commit可执行文件,在配置npm script
"hooks": "copy /y .\\.git_hooks\\*.* .\\.git\\hooks\\"
npm install 周后npm run hooks可以完成上述操作

2.直接编写钩子脚本

之前我们编写的是最最简单的脚本,了解了编写脚本的原理
现在我们编写一个能用到实际环境的pre-commit(eslint)脚本
颜色部分大家可以看这篇文章,虽然他有地方写错了系统默认颜色

//pre-commit

#!/bin/sh

#定义颜色的变量
RED_COLOR='\x1b[31;4m'   #红

GREEN_COLOR='\x1b[32;4m' #绿
YELLOW_COLOR='\x1b[33;4m' #黄
BLUE_COLOR='\x1b[34;4m'  #蓝
PINK='\x1b[1;35;4m'        #粉红
LIGHT_BLUE='\x1b[1;36;4m'  #天蓝
WHITE='\x1b[1;37;4m'  #天蓝
RES='\x1b[0m'
# 下面这一行我确实看不懂,肯定和git add  commit文件有关系,有兴趣的可以研究下
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep ".\(js\|vue\)$" | grep -v "node_modules" | grep -v "static")
# 没有提交文件,退出
if [[ "$STAGED_FILES" = "" ]]; then
  exit 0
fi

PASS=true

echo  "\nValidating Javascript:\n"
# 这里用变量代替特殊字符,所以不需要echo -e
# Check for eslint
which eslint &> /dev/null
if [[ "$?" == 1 ]]; then
  echo  "${RED_COLOR}Please install ESlint${RES}"
  exit 1
fi

# 获取每个文件 执行eslint
for FILE in $STAGED_FILES   
do
  eslint "$FILE"

  if [[ "$?" == 0 ]]; then
    echo  "\t${GREEN_COLOR}ESLint Passed: $FILE${RES}"
  else
    echo  "${RED_COLOR}ESLint Failed: $FILE${RES}"
    PASS=false
  fi
done

if ! $PASS; then
  echo  "${RED_COLOR}COMMIT FAILED:${RES} eslint校验未通过。请修复eslint错误,然后重试.\n"
  exit 1
else
  echo  "${YELLOW_COLOR}COMMIT SUCCEEDED${RES}"
fi
# $? 为上一次的执行结果
exit $?  

3.通过pre-commit

上面这个是我们项目里面使用的,真实可跑,由我们老大编写,shell编程。
但是我等菜鸡前端并不会这么高端的东西,咋整呢?...
莫怕,有pre-commit能自动在git commit之前调用我们的npm run test (可以指定)

pre-commit is a pre-commit hook installer for git. It will ensure that your npm test (or other specified scripts) passes before you can commit your changes. This all conveniently configured in your package.json.
"scripts": {
    "test": "echo \"Error: I SHOULD FAIL LOLOLOLOLOL \" && exit 1",
    "foo": "echo \"fooo\" && exit 0",
    "bar": "echo \"bar\" && exit 1"
  },
  "pre-commit": [
    "foo",
    "bar", //遇到1停止
    "test"
  ]

在安装完以后,可以按上面这个配置一下。应该会正常执行foo->然后执行bar的时候返回1,报错,停止
实际上我们有这个工具之后我们再也不用编写令人厌烦的shell脚本了
聪明的你估计已经想出来了,可以直接按上篇文章所说,执行配置的lint脚本即可

"scripts": {
    "lint": "eslint --ext .js .jsx .vue src"
  },
  "pre-commit": [
    "lint" //标记1
    "foo"
  ]

eslint校验不通过返回1,正好使程序在标记1处停止,不会执行foo

4.用lint-stage优化

上面的配置其实已经能满足绝要求了,但是聪明的你发现每次lint的时候都是lint的src文件夹,但是我们实际只想lint提交的问题,这时候我们就需要请出我们另外一个库了,lint-stage,它只帮我们处理git stage里面的文件(也就是每次git add的文件)

Linting makes more sense when run before committing your code. By doing so you can ensure no errors go into the repository and enforce code style. But running a lint process on a whole project is slow and linting results can be irrelevant. Ultimately you only want to lint files that will be committed.

本么总结了文档中的标准写法,有如下业务写法
注意这里我没验证过,加husky这个玩意是否有用,因为我的项目在vue-cli里面,不用加husky

{
  "scripts": {
    "lint": "eslint --fix --ext .js .jsx .vue src"
    "lint-staged": "lint-staged"
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "*.{js,jsx,vue}": ["npm run lint","git add"] //标记2
  }
}

这里说一下为什么标记2处要加上git add,这是因为我们selint 后面加了参数--fix 会自动修复文件,修复后的属于新产生的文件,我们自动git add添加到staged里面

5.vue-cli下的配置

vue-cli官方文档写的是

{
  "gitHooks": {
    "pre-commit": "lint-staged"
  }
}

但是我发现这种写法是错的,如果有gitHooks这个属性vue会一直执行test脚本,而且会报错。

下面这个写法我项目里正在用,肯定没问题,大家放心的copy吧

 "scripts": {
    "dev": "vue-cli-service serve",
    "build": "vue-cli-service build ",
    "test": "vue-cli-service build --mode productionTest",
    "lint": "vue-cli-service lint --fix --quiet",
    "lint-staged": "lint-staged"
  },
  "pre-commit": "lint-staged",
  "lint-staged": {
    "*.{js,jsx,vue}": ["npm run lint","git add"]
  },

不知道为什么在另外一个多页面项目里面每次都是检测的src里面的全体js、vue、jsx文件。而且--fix没啥用,去掉也能自动修复不知道是什么原因,但是是我研究错了?妈的,费解
多页面暂时改用下面这套配置,lint后面手动添加文件范围
`
"scripts": {

"dev": "vue-cli-service serve --inline --progress ",
"build": "vue-cli-service build && node src/utils/copy.js",
"buildTest": "vue-cli-service build --mode productionTest && node src/utils/copy.js",
"buildLocalTest": "vue-cli-service build --mode productionLocalTest && node src/utils/copy.js",
"lint": "vue-cli-service lint --fix --quiet src/module/toutiaoSearch/",
"lint-staged": "lint-staged"

},
"pre-commit": "lint-staged",
"lint-staged": {

"*.{js,jsx,vue}": [
  "npm run lint",
  "git add"
]

},
`

总结

本文对eslint和git钩子的联系做了详细介绍,希望能给大家的项目带来帮助。
很久没写文章了,罪过罪过。今天一口气写了两篇,希望能一扫往日颓废,重新振作起来,,,加油!


Runningfyy
1.3k 声望661 粉丝