一、前端代码规范工具
1、前言
代码规范和质量是编码中很重要的一部分,目前有很多工具可以帮助我们处理。
在使用这些工具的过程中发现,存在一下问题:
- 功能重复
- 不同工具,相同配置冲突
- 版本迭代导致配置变更
工具相互组合,使用困难
这篇文章主要从工程化的角度出发,分享以下内容:
1、介绍各种工具的使用(Prettier、ESLint、lint-staged、commitlint、Hooks)
- 2、通过Git Hooks来自动化执行这些工具。
- 3、配置CI在代码提交阶段格式化、检测代码、检测提交信息。
学习完这篇文章你将了解:
- 1、了解如何区分这些工具、不同的配置入口
- 2、在项目中如何配置这些检测工具
- 3、如果避免每次的全量检测代码
- 4、如何规范提交代码和描述信息
- 5、学习Git Hooks知识
- 6、如何将这些工具通过Hooks自动化处理
- 7、通过CI将这些流程自动化执行
2、工具分类介绍
检测代码的工具很多,主要分为三类:
- 一类是代码格式化工具,专注代码结构美化,不处理任何有关语法的内容
[Prettier](https://link.zhihu.com/?target=https%3A//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/29e62e3c6c514314b06e0f37aca21b3b~tplv-k3u1fbpfcp-zoom-1.image)
:专注代码格式化[Stylelint](https://link.zhihu.com/?target=https%3A//stylelint.io/)
:专注CSS语法格式化
- 一类是lint类,这些工具也支持处理代码格式,但重点是检测代码语法质量
[ESLint](https://link.zhihu.com/?target=https%3A//cn.eslint.org/)
: 可以配置代码格式规则,也可以检测代码语法质量
- 一类是将不同的工具进行合成,成为一个包含子功能或者有定制功能的插件,可以避免Prettier和Lint二者在代码处理上的冲突。
[eslint-config-prettier](https://link.zhihu.com/?target=https%3A//github.com/prettier/eslint-config-prettier)
:ESLint检测和Prettier格式化[tslint-config-prettier](https://link.zhihu.com/?target=https%3A//github.com/alexjoverm/tslint-config-prettier)
:TS检测和代码格式化[lint-staged](https://link.zhihu.com/?target=https%3A//github.com/okonet/lint-staged%23readme)
:仅过滤Git暂存区上的文件,可以有效避免每次提交处理所有文件。
Git暂存区:执行命令git add后,要提交的代码存放的空间
这些工具有小而精的,也有大而全的,具体使用要根据具体场景
- 写一个主题样式,肯定首选Stylelint,重点处理CSS;
- 开发一个产品,不妨使用大而全。因为项目中有很多格式需要处理,如果都用小而精的处理,会引入很多荣誉的配置。
这些工具配置都比较相似,但尤其要注意版本的不同,导致的配置不同。
3、本文环境
下文依赖的工具和环境
- OS:mac m1
- Git版本:2.24.3
- npm版本:7.21.1
- Husky版本:7.0.4
- Nodejs版本:v16.9.0
二、自动化工具原理和配置
1、原理
Prettier、ESLint
两者的工作原理是将代码解析成AST
,再通过我们写的配置,还原格式化后的代码,具体转化可以体验下https://cn.eslint.org/parser/。
lint-staged、commitlint、husky
lint-staged
是获取git add后暂存区的代码。commitlint
是获取git commit的描述信息然后对格式进行规则校验。husky
是将git内置的勾子函数暴露出来,便于配置
2、配置对比
下面这些自动化工具,可以不同的地方进行配置,版本也不同,看起来很复杂,其实并没有,除了注意大版本的不同,其他的配置方式都大同小异。这里我们整理下这些配置通用的部分,下面就不再分开写,只展示package.json这一种方式。
工具名称 | package.json关键字 | 常用配置文件 | 忽略文件 | 共享文件 | 插件 |
---|---|---|---|---|---|
注意:
- 配置示例地址
- package.json中关键字内容和配置文件内容一致
- 共享配置一般都是导出配置文件,上传npm,规范命名即可
- 这些工具大都还提供了编辑器集成、CLI等
三、代码格式美化:Prettier
1、初始化项目构建
新建项目,并在index.html和index.js写一些格式不规范的代码
1 | mkdir front-demo |
目录结构如图:
2、插件使用
安装Prettier插件
1 | yarn add prettier -D |
执行命令:
1 | yarn prettier -w . |
发现当前所有目录下的文件,都进行了格式化
这里使用yarn prettier是为了读取项目下的prettier指令,如果你安装全局命令或者配置了环境变量,可以不用yarn指令
prettier
格式有一套默认的格式化规则,一般情况下,选择默认就可以了
当然也可以自行配置,下面有两种配置方法:
- 在package.json中添加关键词
prettier
- 在项目根目录下新建
.prettierrc
文件,js、json、yaml等也可以。 - 下面就不再写package.json中配置了,具体关键字可以查看上面的表格。我们统一通过配置文件进行配置,其他的工具也是一样的。
- 规则解释见配置文件Github地址
这里在根目录下新建文件.prettierrc
1 | { |
此时Prettier根据.prettierrc
定义的规则,对整个项目做了格式化操作。 但一些场景下需要我们对个别文件进行处理,可以通过覆盖配置来实现
3、覆盖配置
修改.prettierrc
文件,添加overrides
字段
1 | { |
这样针对test.js
文件、html
文件和legacy/**/*.js
的格式就会按当前配置走。
4、共享配置
项目的配置一般都不会变化,所以常常多个项目使用同一个配置,特别是针对大点的项目。
下面我们实践下创建一份Prettier配置到npm仓库
1、注册npm账号
2、创建一个包、包的命名规则:@prettier/plugin-
or prettier-plugin-
or @<scope>/prettier-plugin-
1 | cd ./config/prettier/prettier-plugin-frontdemo |
3、发布创建好的包
1 | # 如果第一次发布需要创建 |
4、登陆npm官网,即可看到上传的包prettier-plugin-frontdemo
5、使用包,在package.json
中,添加远程仓库地址:
1 | { |
6、执行yarn prettier
5、忽略文件
如果想要忽略某个文件的格式化,可以新建文件.prettierignore
,添加要忽略的文件
1 | /dist |
四、代码质量检测:ESLint
1、安装ESLint插件
yarn add eslint -D
2、新建配置文件
yarn add eslint --init
上述命令行会弹出选择提示,根据需要选择eslint规则,最后会在根目录下生成.eslintrc.js
文件
1 | module.exports = { |
- env: 包含了执行环境配置,浏览器环境、node环境或支持es5、es6.
- extends: 使用的扩展配置,这里主要是引入一些集成好的检测规则
- parseOptioins: 解析器配置
- plugins: 引入的eslint插件
- rules: 用来定义具体规则,检查缩进,函数是否有返回值等。
第一个参数,如果只有一个参数,直接使用字符串或数字就可以了
"off"
或0
- 关闭规则"warn"
或1
- 开启规则,使用警告级别的错误:warn
(不会导致程序退出,即可以正常提交代码)"error"
或2
- 开启规则,使用错误级别的错误:error
(当被触发的时候,程序会退出,存在error告警不能提交代码)
第二个参数:你想要的配置参数
"quotes": ["error", "double"]
,如果存在单引号的就报错,终止提交。"quotes": ["warn", "double"]
,如果存在单引号就告警,但可以正常提交。
ESLint的配置规则
执行命令
1 | yarn eslint src/*.js |
ESLint对代码进行了检测
注意,如果项目根目录配置了.eslintrc
, 那么package.json中配置了eslintConfig将不会生效
1 | module.exports = { |
3、覆盖ESLint配置
我们看到不管是共享的配置还是使用官方推荐的配置,如果我们想要在这个基础上修改某个规则怎么办,使用overrides来覆盖,可以指定使用的范围。
1 | { |
我们可以看到no-console告警出来了。
其实ESLint还提供了创建规则,自定义解析器,编写插件的能力,下面我们主要实践下编写插件
4、共享配置
和Prettier一样,如果每个项目都配置一个太麻烦了,可以整体使用一套
新建一个项目导出这个js文件,然后上传到npm,直接通过extends字段引用就可以了。发布流程和prettier是一样的,命名还要用eslint-config-开头。官网
安装yarn add -D eslint-config-frontdemo
修改package.json
(修改.eslintrc.js文件也是一样的,这里用了package.json的配置,所以根目录下的.eslintrc.js要删除掉)
1 | "scripts": { |
执行yarn eslint
,成功
五、Git暂存区代码过滤:lint-staged
在实际使用过程,会遇到这样的问题:
- 每次都要全局处理代码,浪费时间
- 每个人对所有代码格式化,规则不同,导致大量代码冲突
lint-staged,仅过滤Git暂存区的代码
1、安装lint-staged
1 | yarn add lint-staged -D |
2、package.json
配置lint-staged
1 | { |
3、执行命令
1 | # 修改业务代码 |
此时发现,这些命令仅对暂存区*.js
的内容进行了格式化。
六、Git提交规范自动化
1、规范说明
如图所示,我们看到优秀的开源项目,对提交代码的描述信息都是很规范的。想要和这些项目一样清晰,我们可以借助插件commitlint
在此之前我们要了解常用的Git提交规范
1 | Subject 一句话概述commit主题(必须) |
比如我们修改了一个列表Bug:git commit -m "bug: change id columns"
,这样我们后面查询起来就很简单了。
2、提交信息规范配置:commitlint
安装commitlint-cli和commitlint常用配置
1 | cd font-demo |
.commitlint.config.js
1 | "commitlint": { |
@commitlint/config-conventional
默认使用这个提交规范
执行命令
1 | echo "this is a new feature" | commitlint |
commitlint用来检测Git提交信息是否规范。
3、通过插件来规范提交信息
虽然我们按照格式提交没有问题,但是很多时候,可能记不住这些命令,我们可以弹出提示信息进行交互式提交
安装依赖@commitlint/cz-commitlint
1 | yarn add -D @commitlint/cz-commitlint commitizen @commitlint/cli @commitlint/config-conventional |
在package.json中配置
1 | { |
在项目根目录下新建文件[commitlint.config.js](https://link.zhihu.com/?target=https%3A//github.com/richLpf/auto-format-demo/blob/main/commitlint.config.js)
修改业务代码,并执行命令
1 | yarn commit |
就可以通过选择来提交代码了。
4、一键执行自动化工具
以上prettier
、esliint
、lint-staged
、commitlint
都配置在package.json中,通过命令yarn commit
按顺序执行这些工具。
1 | "scripts": { |
配置完成后,修改业务代码,执行yarn commit
,发现对Git暂存区的文件依次进行了ESLint检测
、prettier
、commitlint录入
,这就完成了简单的自动化工作流。
然而这种方法把git的命令覆盖了,而且可能很多人不想要每次都通过提示提交信息,那么下面我们接着看,如何通过Hooks处理自动化工作流。
七、Git Hooks
1、Git Hooks介绍
要自动化上面的流程,就要用到Git的钩子函数Hooks。
Git Hooks通过一个个钩子,允许Git在每个节点执行一些shell脚本,如果哪个阶段有问题,就会抛出错误,拒绝提交代码。
常见的Git 钩子:
客户端钩子:
pre-commit
,输入git commit调出提交信息编辑器之前,主要用来代码格式,代码检测、单元测试等。prepare-commit-msg
git commit编辑器启动提交信息之前,默认信息被创建之后,主要编辑提交信息commit-msg
git commit 信息提交,用来检查提交信息的格式。post-commit
在提交完成后,可以用来发送通知,提醒其他同事等。
服务器端钩子:
pre-receive
:客户端推送代码到服务器时,只会触发一次update
:客户端推送代码到服务器,如果多个分支,分别触发一次post-receive
:推送完成后。
整个钩子触发的时间点可以理解为:在网站上打开一个弹框输入信息,提交信息,关闭弹框的过程
- 1、点击新建按钮,弹框弹出前(pre-commit)
- 2、弹框获取初始模版信息后(prepare-commit-msg)
- 3、编辑信息以后,点击提交时(commit-msg),这时可以对提交的信息进行检测
- 4、点击保存信息完成(post-commit)
2、Git Hooks实践
安装Git(默认本地安装了Git)
1 | cd front-demo |
Git Hooks每个钩子都有示例文件,这些是git预置的hooks脚本示例,因为加了sample后缀,所以并不会被执行。
我们在当前目录下新建pre-commit
脚本,文件内容如下
1 | #!/bin/sh |
回到项目根目录下,修改项目内任意文件,提交代码,发现成功提交,但是有告警。
因为pre-commit
没有执行权限,我们给文件执行权限
1 | chmod +x pre-commit |
然后再次提交代码,发现git commit后,打印出了this is a test file
,我们写在.git/hooks/pre-commit
中的代码,这就说明Git Hooks触发了。
3、Husky实践
Hooks需要更改.git下的配置,非常不方便,所以有了Husky,将Hooks暴露在项目中。
安装Git Hooks,husky v4版本可以在package.json中配置,v5版本后,husky就独立在项目根目录下配置,这里使用的是
7.0.4
1 | # 安装husky |
4.x.x版本在package.json中配置
1 | "husky": { |
7.x.x版本
1 | # 添加一个钩子脚本,检测Git提交信息规范 |
我们看到在项目根目录下,生成了.husky文件夹,下面有Hooks相关的脚本。
这里不光可以使用shell脚本,用node、python脚本都可以。
提交代码,发现如果没有按标准格式,就会被拦截。
4、通过Husky自动化规范
pre-commit
钩子:prettier和eslint检测代码格式和代码质量
commit-msg
钩子:执行commitlint,检测提交信息是否符合格式
首先安装这两个钩子
1 | yarn husky add .husky/pre-commit 'yarn lint-staged --allow-empty' |
这里lint-staged 添加允许空提交是为了避免报错lint-staged issues
然后改动代码src/index.js
执行命令:
1 | git add . |
发现检测出了不符合eslint规范的编码。
修复eslint错误,再次提交,发现报错提交信息不规范,但代码已经格式化过了。
修改提交信息,Ok大功告成,成功提交。
八、通过CI自动化检测代码
之前介绍的是,本地提交代码的自动化检测。
那么并不是每个开发都会去注意这一块,针对提交上线的代码,除了服务器端钩子来检测,还可以通过CI/CD来检测。这块的工具也很多,常用的有:Gitlab/CI、Github/Action。
这里我们选择Github/Action
1 | cd front-demo |
github-action.yml
1 | name: GitHub Actions Demo |
每次推送都执行下面两个任务
- 执行eslint校验
- 执行prettier检查
修改front-demo项目下的package.json
,运行命令检查是否Prettier格式化
直接提交代码,推送Github,打开Action页面
两个任务执行成功
接着注释掉本地钩子执行的 eslint和prettier,修改代码提交到远程仓库(故意打乱)
打开Action页面,发现任务都失败了,并且提示除了错误信息。
如果任务执行成功,就可以继续执行构建,部署,打包文件检测等。
当然也可以在这个阶段,增加单元测试,代码分析等操作。
九、参考文章
欢迎加入讨论,如果觉得还不错,给个赞吧
本文转自 https://zhuanlan.zhihu.com/p/487898449,如有侵权,请联系删除。