首先说下契机,最近公司发生了几次由于不同人ide格式化差异导致的代码冲突覆盖问题,对团队协同开发造成了不小影响,在浪费时间解决冲突的同时也导致了最新代码被覆盖成
我作为其中一员也是不胜其烦,向leader提出问题后,把解决规范的任务给到了我解决。虽然由于平时开发除了eslint以外,对相关内容接触不多而碰到了不少坑,但是还是对代码规范以及git有了更深刻理解。
通过查看其它公司制定规范的案例和自己的思考,从自己的想法出发归纳出了规范实行的三个方面,其中包括:
- 代码风格校验(eslint)
- IDE格式化(eslint、vetur)
- 版本管理工具的提交校验(git pre-commit hook)
三者以eslint为核心,组合起来形成一套流程。
一、代码风格校验工具
作为js核心的校验工具,eslint也是作为了规范核心的一环。其实公司项目里也一直在使用,只不过由于历史遗留原因规则,使用的是仅校验js的airbnb-base
规范,而前端项目技术栈为vue,即使加上vscode上的vetur插件,eslint也只能校验到script标签内的js代码,而template模板内的代码基本处于放飞自我的状态,不受任何规则限制。常见的例子就是当某个组件绑定的属性超多时,单行代码长出天际,代码可读性极差。
实际上,现在eslint已经增加了针对vue文件里template代码段的校验规则plugin:vue/essential等及配套插件 eslint-plugin-vue,详情可以查看文档的规则列表,搭配了例子讲得很清晰,没有中文翻译。
目前用vuecli3搭建项目,只要是在创建时选择了使用eslint校验的都会在项目里自动安装eslint-plugin-vue,无需自行安装。它能够将大多数template代码块的格式错误暴露给使用者,比如重复声明key属性等,能解决部分template内代码风格不统一的问题。
二、IDE格式化插件
上一部分讲到eslint帮助解决了绝大多数代码问题,然而实际使用中依然存在着问题,比方说当代码不符合eslint规则的时候,能否通过自动格式化修改成符合规则的样子?以目前使用最多的vscode为例,它提供了和eslint同名的插件,能够在粘贴、保存代码的时候自动修改部分不符合eslint规则的代码段。使用方法是,首先需要下载插件,同时在vscode配置文件setting.json加入以下配置。
{
"editor.formatOnSave": true, // 编辑器在保存的时候格式化代码
"eslint.autoFixOnSave": true, // eslint在保存的时候格式化代码
// 应用eslint格式化的语言种类
"eslint.validate": [
"javascript",
"javascriptreact",
{
"language": "html",
"autoFix": true,
},
{
"language": "vue",
"autoFix": true,
}
]
}复制代码
配置后,在保存时eslint插件就会对代码自动格式化。但实际使用中,格式化还不足够,例如上面说到的单行代码过长问题,格式化依然没有将代码自动换行。查阅规则列表发现在strongly recommended的规则里,有将存在多属性的标签自动换行的规则vue/max-attributes-per-line
。尝试使用strongly recommended规则,在eslintrc.js加入
extends: [
'plugin:vue/strongly-recommended',
'@vue/airbnb',
],复制代码
虽然是可以用了,但是实际并没有按预期格式化。
格式化前代码是这样的,
格式化后变成了下面奇怪的样子。
stack overflow上面有一篇文章解释了这个问题,大致原因是eslint某些规则的格式化需要格式化数次才完成,而vscode里eslint插件只会在保存的时候格式化一次,并没走完格式化的流程。当你不断保存代码后,eslint会继续一步一步执行格式化,直到格式化完成变成下面的样子。
到这里不得不提vue开发者十分熟悉的插件vetur。以往开发中,我只用到了它提供的语法高亮和属性联想功能,而实际上它还能针对每一个代码块如template、script、style使用不同的格式化工具,达到相同的目的。
首先根据下图步骤进入到vetur插件的配置页。
里面列出了vetur针对vue里面每一种代码块使用的格式化工具的选项。而vetur针对vue文件里面的<template>
代码段,使用了prettyhtml插件进行格式化。正如官方描述,
Opinionated general formatter for your Angular, Vue, Svelte or pure HTML5 templates.
prettyhtml是一款针对vue等使用的通用格式化插件,也是vetur推使用的。通过比较,我发现这个插件它格式化的结果跟使用eslint多次保存后格式化的结果是最为一致的,不会像prettier和js-beutify-html(vetur之前默认使用)按照自己的规则格式化。
因此我们需要将<template>
的格式化交给vetur,而对于<script>
标签里的js代码格式化,还是使用eslint插件进行,两者各司其职。所以这里就将vetur对js代码的格式化设置为none
,防止两者发生冲突。
将所上述的配置,vscode就可以对vue文件内各个代码块进行比较统一的eslint规则格式化了,这里说的比较实际上是指prettyhtml与eslint-plugin-vue提供的规则有少许出入,根据eslint的话,含多属性的标签一定会换行,而prettyhtml则会结合标签的长度决定换行,相对会美观一点。
针对项目配置格式化
如果团队需要强制每个开发人员使用插件的及对应的配置,可以在项目文件夹新建工作区配置文件settings.json。实现起来很简单,只需要将用户设置里面的settings.json内容复制到工作区保存,vscode就会自动生成放进根目录的.vscode文件夹。
接着再将.vscode文件夹提交到远端仓库里,以后每一个参与项目的开发人员都会把对应的项目配置文件随着项目拉下来,统一配置。
注意:工作区配置文件夹只有当它的位置在所打开的工作区域根目录时生效,看文字不好说明白,那就直接上图了。
留意图片顶部的工作区名称,第一幅图打开的工作区域是文件夹YP-WEB-CONSOLE,而.vscode文件夹不在此目录下,所以工作区配置不会生效;而第二幅图打开的是VUECLI3文件夹,根目录有.vscode文件夹,工作区配置生效。
三、版本管理工具提交校验
前面两部分讲解了,如何在团队成员在编写代码时能够按统一的规范格式化代码,而本部分的提交校验则是为了防止成员为了一时之便,在编写过程中绕过了规范限制,直接将非法代码提交到代码库造成污染。
以现在比较常用的git作为实例,git在提交代码的环节针对不同时刻提供了数个可供使用的hooks,这里我们需要达到的目的是校验不通过的代码进行拦截并终止提交过程,所以用到的是pre-commit hook钩子(还有一个常用的钩子commit-msg,通常会用来核对提交信息是否遵循指定的模板,有兴趣的可以自行google,这里不详细讲)。
而一般要在git hook进行操作是需要使用底层命令编写项目中的 .git/hooks
文件的,不过为了降低实现成本,可以使用一个现有的工具husky。husky它可以通过npm进行安装,集成了调用各种git hook的底层命令,使用起来非常傻瓜式,只需要跟着文档走就行,下面是使用例子:
这样就能在提交时pre-commit钩子里面调用eslint校验代码,若是有不符合规则的代码,马上就会终止提交,避免代码污染。不过加入校验后还有两个问题:
1.第一点是eslint会在提交的时候对整个项目里所有文件进行校验,当项目比较庞大的时候,校验会变得十分漫长,降低了提交的速度;
2.第二点是校验后eslint会自动格式化一些不符合规则的代码,但是需要你再次提交自动格式化代码带来的代码更改。
通过google,发现了一个解决问题的插件lint-staged,它将校验的策略从校验整个项目代码改变为只校验本次修改、新增的代码或文件,将校验范围大大缩减,从而提高了校验的效率;同时它可以将多条命令按顺序合并进行,刚才提及的需要再次提交的问题可以通过git add
加入需要提交的更改中。lint-staged同样可以使用npm包安装,使用后的package.json变为下面的样子:
这样就能够实现快速校验的目的了,来看一下加入pre-commit后的效果吧。
粗略测试了下加入lint-staged前后的提交校验速度,同样提交相同的代码更改,左边是加入前,右边是加入后,感觉还是有些效果的。
到此,整个规范流程已经基本建立了,项目成员又能冰释前嫌的代码冲突和丑陋代码,快活的结对编程了哈哈。
后续的话,其实还可以将整套规范制定一个基础的手脚架发布到npx上面,这样以后每一个新的项目都能使用这套规范,在此基础上面进行开发,而不必每一个项目重新制定一次。有时间我会继续把这部分给做好,再发布出来。
最后想说一嘴,工具是死的人是活的,这些规范工具归根到底是只防君子不防小人,只要理解了其中的原理,可以有各种方法绕过规范限制。而真正要实现团队的代码规范,我觉得不能仅仅靠这几个工具做限制,最核心的还是要在团队建设过程中强调规范的重要性,让团队成员心中都坚定规范统一的念头而不是怨念规则的繁杂琐碎,如此工具才能发挥它应有的作用吧。
参考链接:
husky、lint-staged zhuanlan.zhihu.com/p/35913229
eslint vscode plugin stackoverflow.com/questions/5…
所有评论(0)