# vscode 插件与 npm 包,保存时自动修复代码格式错误

# 前言
日常开发中的绝大多数项目,都是以团队为单位进行的。而由于每个成员的代码习惯和编码差异的不同,最终将导致整个项目的代码参差不齐,出现各式各样风格的代码。
而此差异性会严重导致团队协作效率低下,后期可维护性也会严重降低。例如代码缩进问题,大部分都是以2个或者4个空格为标准,倘若在没有格式化工具的前提下,迭代起来就会显得异常麻烦,只能逐行添加或者删除空格,不仅浪费时间也毫无意义。
因此制定统一规范的代码风格,并以此配置出格式化工具显得尤为重要,并且最好是在开发中就将此问题解决掉,于代码运行之前就检测出错误,保证推送到远端的代码是非常规范的。
此篇文章将以vuecli3脚手架为基础项目,以vscode为代码编辑器,从零开始逐步详细配置相关插件,最终达到保存时自动修复代码格式错误,跟随此篇文章你将了解到。
vscode编辑器中Vetur插件的主要功能,多种配置vue代码片段的方式- 解决
ESLint的autofix与prettier格式化之间的冲突,了解eslint-config-prettier与eslint-plugin-prettier之间的区别差异 - 旧脚手架项目如何接入格式化工具
- 代码提交时自动格式化并规范提交日志
git hook工具husky版本由v4迁移至v7时,如何修改相关配置项- 常见的格式化问题以及处理方式
如果你仅关注如何使用,不关心配置流程和步骤,那么你可以跳过并浏览每个章节的小结部分,或者也可以访问 GitHub (opens new window) 仓库。
# 准备工作
# 工具版本
请确保你已经安装了 vscode (opens new window) 编辑器和 node (opens new window) 环境,并且你也已经全局安装了 vuecli (opens new window) 脚手架和 git (opens new window) 工具,此处贴一下相关命令与版本。
vscode
1.61.2
node --version
v14.15.0
vue --version
@vue/cli 4.5.3
git --version
git version 2.27.0.windows.1
# Vuecli3 功能选择
选择目录或文件夹,开始创建vuecli脚手架,细致部分参考 vuecli (opens new window),注意最好是启动Powershell来创建。
磁盘根目录下按住Shift键再鼠标右击,选择在此处打开 Powershell 窗口。

运行命令vue create app,选择Manually select features来手动设置更多的选项。
上下键切换选项,
Enter确认,空格键选中或取消

项目功能只选择Vue版本和Babel转译器。

;vue版本选择2.x,且各项配置在独立文件中。

创建成功。

# Vscode 初始插件
;vscode插件仅安装chinese和Reload两种,其中chinese语言拓展插件可安装也可不安装。
如果你还安装有其它插件,为了保证配置不出错,可以都禁用掉,不必卸载

;Reload插件将在vscode编辑器的右下角状态栏中添加重载按钮,用于快速重载vscode窗口,方便调试。

键入Shift + Ctrl + P并输入settings.json打开设置,为了不影响调试效果,你的个性化等其它配置最好都注释掉。

# 修复流程
# Vetur 代码风格 / jsconfig.json
;vscode打开vuecli3脚手架后,能明显看到App.vue全是文本字体,没有高亮,代码行距也很紧凑,非常难看。

因此视觉上的代码高亮问题要先解决,于是在vscode中搜索并安装 Vetur (opens new window) 插件。

一般在安装完成后vscode右下角会收到警告提示,如果你没有收到,那请点击状态栏Reload按钮,重载后几秒之内你会收到的。
原因在于Vetur会优先查找项目中的tsconfig.json和jsconfig.json文件,如果没有就会查找vetur.config.js文件,如果都没有,Vetur就会抛出此警告。

虽然说警告影响不大,但是有没有像我一样看着就来气的,真是气死强迫症。
没有那就创建一个jsconfig.json呗。
// jsconfig.json
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": [
"src/*"
]
}
},
"exclude": [
"node_modules",
"dist"
]
}
若目录中存在jsconfig.json,则表示此目录是JavaScript项目的根目录,因此包含以下文件的目录就被认为是根目录,更多 详细参考 (opens new window)。
├── node_modules
├── ...
├── jsconfig.json
├── ...
├── package.json
├── README.md
其中exclude用于告知vscode哪些文件不属于源代码,使其IntelliSense(智能感知,即代码自动补全提示等)保持在高性能水平。baseUrl用于指定基础目录,paths表示相对于baseUrl选项计算的路径映射。
因此@/*即映射到当前目录app下的src目录下的文件或文件夹。如果还是没懂可以看如下图片,输入@/后随即智能提示出了src目录下的文件或文件夹。而此智能提示就是刚才配置jsconfig.json的劳动成果。
可以尝试注释
jsconfig.json,Reload重载窗口,再次输入@/查看是否有无智能提示

代码有高亮看着舒服多了,但是稍显紧凑,因此来修改下行距和Tab空格数。
根目录下创建.vscode文件夹,新增settings.json。lineHeight用于指定行高,tabSize用于指定一个Tab键表示几个空格,但是可能会被覆盖。
原因是因为editor.detectIndentation默认为开启状态,表示根据文件内容自动检测出editor.tabSize,若检测出editor.tabSize则将自动覆盖设置项。因此若要强制一个Tab键为几个空格,可以将editor.detecIndentation设置为false。
// .vscode/settings.json
{
"editor.tabSize": 2,
"editor.lineHeight": 24
// "editor.detectIndentation": false
}
修改后App.vue的风格样式。

# ESLint 错误检查
;Vetur对vue中<template>、<style>、<script>都进行了错误检查,内部默认捆绑了 eslint-plugin-vue (opens new window) 用于模板错误检查。默认情况下Vetur加载 vue/essential (opens new window) 规则集用于vue2项目。

但是由于essential规则集有限,现在选择官方推荐的 vue/recommended (opens new window) 规则集来校验代码,因此将自定义Vetur的规则集,下面来自定义错误检查。
首先关闭Vetur的模板验证。
// .vscode/settings.json
{
...
"vetur.validation.template": false
}
模板验证已经关闭。

然后安装vscode的 ESLint (opens new window) 插件,让ESLint插件来检查错误,而不是Vetur。

;ESLint插件将使用项目中的eslint依赖包,若项目内未提供,则ESLint插件会全局查找,因此项目需安装eslint依赖包。而针对vue项目,必然要一套检查vue代码的规则集,而此规则集可由eslint-plugin-vue提供。
npm i eslint eslint-plugin-vue -D
;eslint-plugin-vue有很多种规则集,而ESLint也不知道具体采用何种规则集,因此还要告知ESLint运用哪一套规则集去检查代码,所以根目录下新建.eslintrc.js文件。
// .eslintrc.js
module.exports = {
root: true,
extends: ['plugin:vue/recommended'],
rules: {
quotes: ['error', 'single'],
},
}
;ESLint检测配置文件的步骤如下,更多 详细参考 (opens new window)。
- 项目内查找
.eslintrc.*或package.json文件(package.json内也可配置相关属性) - 若未找到,则在父级目录中查找,一直查找至磁盘根目录
- 若在以上两步中发现
root: true,则停止往父级目录中查找
另外extends表示启用 vue/recommended (opens new window) 规则集,rules中可自定义检查规则,['error', 'single']表示字符串仅能使用单引号,若非单引号则将以错误下划线高亮。
['warn', 'single']将以警告下划线高亮

新增了配置点击状态栏Reload重载窗口,查看App.vue文件,自定义错误检查已生效。

# Autofix
现在已经可以对代码进行检查了,手动尝试下修复代码。

但是你可以打开component/HelloWorld.vue浏览看看,通篇的警告就问你慌不慌。像App.vue代码较少,尚可以手动修复,但是HelloWorld.vue难道要一行一行修改不成。
有没有可能ESLint检测出代码,并且还能修复呢,嘿嘿,还真有,即ESLint的autofix功能。
将App.vue还是恢复为以下状态。

;vscode命令行执行以下命令,即修复App.vue。
npx eslint src/App.vue --fix
修复后的App.vue。

此时控制台输出2个错误,大致描述就是v-for的元素需指定key,而item也声明但是未被使用。你要知道的是ESLint仅仅能修复简单的错误,像v-for的key值问题等还是需要你手动修复的。

可能你会问,是不是每次代码写完还要针对某个文件执行一次npx eslint ...,如果是那样就真的尴了个大尬。
在settings.json添加如下命令,即在每次文件被保存时,自动执行fix修复。
可能你会在其它文章中看到
source.fixAll,两者区别在于source.fixAll表示针对所有插件开启自动修复,source.fixAll.eslint表示只在ESLint中开启
// .vscode/settings.json
{
...
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
}
;App.vue保存时。

# Prettier 格式化
于是问题都解决了吗?其实并没有哦,看看如下情况。

由于eslint-plugin-vue中提供的规则集vue/recommended中的规则 vue/html-indent (opens new window),此规则对标签强制使用了一致的缩进,因此保存时<template>自动修复了缩进。
但是<script>中却没有修复,因为vue/recommended规则集没有提供用于<script>标签缩进的规则,所以修复时<script>内也就没效果,第一种解决方式很简单,就是添加用于vue文件的<script>缩进的规则 vue/script-indent (opens new window) 即可。
// .eslintrc.js
module.exports = {
...
rules: {
...
'vue/script-indent': ['error', 2, {
'baseIndent': 0,
'switchCase': 0,
'ignores': []
}]
},
'overrides': [
{
'files': ['*.vue'],
'rules': {
'indent': 'off'
}
}
]
}
但是此方式不推荐,因为不仅耗时、规则覆盖不全面(可能会少某几条)而且也没必要。其中配置项各参数释义不赘述,更多 详细参考 (opens new window)。

来看一个有趣的操作,你可以在App.vue右键选择格式化文档(也可键入Shift + Alt + F),紧接着再保存(Ctrl + S),你会发现<template>与<script>中的代码都被修复了。

为什么会被修复呢?原因在于 格式化文档 (opens new window) 是由Vetur提供的,Vetur默认捆绑了多个格式化程序(例如 prettier (opens new window) 等)用来格式化代码。
你应该了解的是 代码规则 (opens new window) 分为两类,代码质量规则和代码风格规则。代码质量出现问题,意味着项目可能没法运转,也可能存在潜在的缺陷。而代码风格不一样,代码风格出现问题,仅仅是代码丑陋,你看着不爽。
代码质量规则。
- no-unused-vars (opens new window):禁止出现未使用过的变量
- no-use-before-define (opens new window):禁止在变量定义之前使用它
- no-v-html (opens new window):禁止使用
v-html来防止XSS攻击 ...
代码风格规则。
- max-len (opens new window):单行的最大长度
- semi (opens new window):强制或禁止使用分号
- indent (opens new window):缩进问题
...
而刚才已经知晓了当前eslint使用的vue/recommended规则集,仅仅包括了<template>中的代码质量(v-for的key值问题等)和代码风格(少部分,包括缩进规则等,例如不包括单行的最大长度等)的检测,但是缺少<script>中的代码风格校验(缩进规则等)。
对于<template>和<script>两部分的代码缩进,vue/recommend规则集已经可以修复<temnplate>的缩进,而<script>的缩进现在让Vetur来做。
;Vetur是开启了vetur.useWorkspaceDependencies为true,即它可以优先使用根目录下的 prettier (opens new window) 格式化依赖包,因此来自定义Vetur的格式化功能。
npm i prettier -D
添加.prettierrc.js,加上几条简单的 规则 (opens new window),printWidth(每行最多多少字符换行)、semi(语句末尾分号)、arrowParens(avoid表示箭头函数是单个参数时,参数周围省略括号)。
// .prettierrc.js
module.exports = {
semi: false,
printWidth: 110,
arrowParens: 'avoid'
}
格式化文档后并保存,可以看到<script>中的缩进已经修复。

# FormatOnSave
频繁右键格式化麻烦不,有没有可能像ESLint一样保存时自动修复呢,答案肯定是有的。
// .vscode/settings.json
{
...
"editor.formatOnSave": true,
}
现在代码还原尝试下保存呢(Crtl + S)。
但是意料之外的情况发生了,保存时,起初运行的是ESLint的autofix,紧接着运行了Vetur的格式化,即autofix介于Vetur格式化之前了。
最后导致风格样式按照prettier来了(例如字符串为双引号),显然不符合ESLint的规则。因此格式是修复了,但是却被ESLint检测出错误了。

以至于频繁保存会频繁闪烁。

# 解决 eslint 与 prettier 冲突
# eslint-config-prettier
频繁闪烁的根本原因在于eslint与prettier一起使用产生了冲突。eslint认为字符串应为单引号,而prettier默认格式化为双引号,所以先来统一单双引号问题,在.prettierrc.js中添加如下规则。
// .prettierrc.js
module.exports = {
...
singleQuote: true
}
现在还存在换行冲突,prettier认为单行最大长度达到110就可以换行,而eslint认为只要是标签属性都应另起一行。

注意实际代码格式问题已经解决了(例如缩进问题、单行最大长度等),你会想要是禁用掉eslint的 vue/max-attributes-per-line (opens new window) 规则,不要它去检查警告,是不是问题就迎刃而解了。
嘿嘿,没错,你猜对了,还真是这样。
但是不用我们去做了,eslint-config-prettier (opens new window) 已经做了,看名字大概也能猜到,config位于eslint与prettier中间,即用于平衡eslint与prettier之间的配置。
npm i eslint-config-prettier -D
但是是用于平衡哪些配置呢,官方文档给出了答案,即关闭了eslint中所有不必要的或者可能与prettier冲突的那些规则,实际也就是代码风格规则。
;.eslintrc.js中添加prettier表示启用eslint-config-prettier,注意一定要在最后,确保覆盖之前的同类规则,否则可能不生效。
// .eslintrc.js
module.exports = {
...
extends: [
'plugin:vue/recommended',
'prettier'
]
}
保存时效果,也能看到eslint相关的代码质量规则未被禁用。

# eslint-plugin-prettier
还记得最开始时,<template>中标签缩进错误时,会高亮黄色警告下划波浪线吗。

如果还是想包含此功能,可以安装一个推荐的可选插件 eslint-plugin-prettier (opens new window)。
由于插件eslint-config-prettier的原因,代码格式问题已经交给prettier负责,而eslint代码格式相关的检测规则也被禁用了,因此即使代码中出现了格式问题,eslint是不会报错的。
而eslint-plugin-prettier做了一件什么事呢?它将prettier格式问题的相关规则,转换成了对应的eslint规则,并注入到了eslint中,由此代码中的格式问题,eslint也会报错。
npm i eslint-plugin-prettier -D
修改.eslintrc.js,其中plugins表示将prettier注册为插件,prettier/pretiier表示将prettier插件提供的规则注入eslint,并且使其在eslint中运行prettier。
module.exports = {
root: true,
extends: ['plugin:vue/recommended', 'prettier'],
plugins: ['prettier'],
rules: {
quotes: ['error', 'single'],
'prettier/prettier': 'error',
},
}
有两个不适用的规则。
- arrow-body-style (opens new window):箭头函数体只能为大括号
const foo = () => { return 0 } // OK
const foo = () => 0 // ERROR
- prefer-arrow-callback (opens new window):使用箭头作为回调函数
foo(arg => {}) // OK
foo(function(arg) {}) // ERROR
很明显都不是很合理,arrow-body-style规则代码也将不是很优雅,修改.eslintrc.js。
// .eslintrc.js
module.exports = {
root: true,
extends: ['plugin:vue/recommended', 'prettier'],
plugins: ['prettier'],
rules: {
quotes: ['error', 'single'],
'prettier/prettier': 'error',
'arrow-body-style': 'off',
'prefer-arrow-callback': 'off',
},
}
而以上配置可以更为便捷地合并为以下,了解更多可参考 官方文档 (opens new window)。
// .eslintrc.js
module.exports = {
root: true,
extends: ['plugin:vue/recommended', 'plugin:prettier/recommended'],
rules: {
quotes: ['error', 'single'],
},
}
以上配置完成后,不出意外,你的App.vue或HelloWord.vue等都将会有很多错误提示。

是由于行尾换行符造成的,不要紧,.prettierrc.js添加如下规则,更多 详细参考 (opens new window)。
// .prettierrc.js
module.exports = {
...
endOfLine: 'crlf'
}
至此格式化相关的步骤就都完成了。

# 区别差异
;eslint-config-prettier不仅提供了prettier的格式化规则,同时也禁用了eslint中所有不必要的或者可能与prettier冲突的那些规则。
代码质量检测均由eslint负责,没有代码格式检测。代码质量修复依赖于eslint的autofix,代码格式的修复依赖于prettier。
所以仅安装eslint-config-prettier时,eslint的autofix和prettier的保存格式化两者一定要同时开启,而且根据上文我们也知道eslint的autofix是介于prettier的格式化之前运行的。
// .vscode/settings.json
{
...
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"editor.formatOnSave": true,
}
仅开启eslint的autofix,能明显看到仅仅修复了代码质量,代码格式并未修复。

仅开启prettier的格式化,代码质量未被修复,代码格式均被修复。

;eslint-plugin-prettier则是将prettier格式问题的相关规则,转换成了对应的eslint规则,并注入到了eslint中。
代码质量检测均由eslint负责,注意代码质量的规则由eslint和eslint-plugin-vue两者提供,代码格式检测也是由eslint负责,代码格式的规则是由prettier提供,且依赖于eslint-plugin-prettier转换并注入到eslint中。
;eslint-plugin-prettier还做了另外一件事,即在eslint的autofix后,紧接着继续运行prettier,因此仅开启eslint的autofix就能完成质量和格式的修复。
但是要明确的是,代码质量修复还是依赖于eslint的autofix,代码格式的修复还是依赖于prettier,只是eslint-plugin-prettier在autofix后帮你自动运行了prettier。
仅开启eslint的autofix,代码质量和格式均高亮,且保存时都被修复。

仅开启prettier的格式化,代码质量和格式均高亮,但是只修复了格式问题。

# 小结
初始脚手架代码都是文本字体,引入Vetur高亮代码。
;Vetur会查找项目中jsconfig.json等文件并抛出警告,新建jsconfig.json。
// jsconfig.json
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": [
"src/*"
]
}
},
"exclude": [
"node_modules",
"dist"
]
}
;vscode引入ESLint插件,安装eslint错误检查包和格式化依赖包,其中eslint和eslint-plugin-vue用于错误检查,prettier用于格式化代码,eslint-config-prettier用于解决eslint与prettier之间的冲突,可选插件eslint-plugin-prettier用于注入prettier格式化规则到eslint。
npm i eslint eslint-plugin-vue prettier eslint-config-prettier eslint-plugin-prettier -D
新建.eslintrc.js,启用eslint-plugin-vue的vue规则集,同时启用eslint-config-prettier,并且启用eslint-config-prettier注入规则。
// .eslintrc.js
module.exports = {
root: true,
extends: ['plugin:vue/recommended', 'plugin:prettier/recommended'],
rules: {
quotes: ['error', 'single'],
},
}
新建.prettierrc.js,统一部分格式化规则和换行符等。
// .prettierrc.js
module.exports = {
semi: false,
printWidth: 110,
arrowParens: 'avoid',
singleQuote: true,
endOfLine: 'crlf'
}
新建settings.json,保存时自动运行eslint的autofix和prettier格式化。
// .vscode/settings.json
{
"editor.tabSize": 2,
"editor.lineHeight": 24,
"vetur.validation.template": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"editor.formatOnSave": true,
}
以上插件和依赖的作用。
- Vetur (opens new window):
vscode插件,用于高亮Vue代码,提供了代码的错误检查和格式化、代码自动补全提示等 - ESLint (opens new window):
vscode插件,依赖于本地工作区或全局下的eslint依赖包 - eslint (opens new window):用于检测和修复代码错误,自定义检测规则,引入
vue代码检测的规则集 - eslint-plugin-vue (opens new window):提供用于检测
vue2代码的规则集 vue/recommended (opens new window) - prettier (opens new window):用于格式化代码,自定义格式规则
- eslint-config-prettier (opens new window):用于解决
eslint和prettier在代码格式上的冲突,禁用了eslint中所有不必要的或者可能与prettier冲突的规则 - eslint-plugin-prettier (opens new window):将
prettier中的代码格式规则,转换为对应的eslint规则并注入到eslint中,使eslint能够检测代码格式问题。另外让eslint在执行autofix后再运行prettier
# Git hook
引入诸多插件都是为了在开发阶段规范或者修复代码,但是都是以vscode编辑器为前提的,倘若其它成员使用的是webstorm等其它编辑器,那么之前做的事情就都白费了。
还好远端是利用git在管理代码,大家提交代码的方式是一致的,编辑器不能做到完全规范代码,但是可以在提交时统一代码。
来了解一下git hook,git hook即git钩子,git在特定事件发生时会触发对应的脚本(类似于vue的生命周期),git init初始化后的仓库中,.git/hooks目录下默认包括很多示例脚本(都是以.sample结尾),删除掉.sample后缀可启用。
常用的钩子包括pre-commit、commit-msg等。
pre-commit:暂存中的文件被提交前触发,或者说在你git commit ...之前触发。若此钩子以非零值退出,git将放弃此次提交(可利用git commit --no-verify跳过),一般可利用此钩子来检查代码风格等commit-msg:输入提交说明后且于pre-commit后触发。若此钩子以非零值退出,git也将放弃提交,一般用于校验提交说明是否符合规范
# Husky(v4) 与 lint-staged 规范代码
思路应该是很清晰了,即在代码提交时,触发对应的钩子来检测并规范代码,因此先初始化一个git仓库。
git init
然后再来了解一下 husky (opens new window),husky是一个为git客户端添加hook的工具,安装v4版本(v4.3.8及之前的版本)后,husky默认会在.git/hooks目录下生成所有类型的git hook。然后在git工作的每个阶段都会调用husky所生成的脚本,在脚本中husky会检查用户是否配置有此钩子,如果有就运行用户配置的命令,没有就继续往后执行。
npm i husky@4.3.8 -D
安装完成后,目录.git/hooks下生成了很多的hook。

来测试一下husky,新建.huskyrc.json,其中pre-commit钩子触发将运行echo hello husky。
// .huskyrc.json
{
"hooks": {
"pre-commit": "echo hello husky"
}
}
修改代码并提交。

已经可以在提交时触发钩子了,现在来考虑一个问题,是在提交前规范目录中所有代码,还是仅仅规范暂存中的代码呢。显然只规范暂存中的代码就可以了,不仅避免检查整个项目,提高运行效率,也避免了修改到其它文件。
而插件 lint-staged (opens new window) 就是对暂存中的文件执行检查的。
npm i lint-staged -D
新建.lintstagedrc.json,注意源码一般位于src目录下,因此仅对src目录下的js和vue文件执行eslint --fix即可,格式修复完成后再执行git add暂存。
// .lintstagedrc.json
{
"src/**/*.{js,vue}": [
"eslint --fix",
"git add"
]
}
修改.huskyrc.json,即pre-commit钩子触发时,将运行.lintstagedrc.json中的命令。
// .huskyrc.json
{
"hooks": {
"pre-commit": "lint-staged"
}
}
关闭eslint的autofix和prettier的格式化,打乱App.vue中代码样式,暂存并提交,可以看到在pre-commit时lint-staged对App.vue进行了检测和修复。

# Commitlint 规范提交说明
安装 commitlint/cli (opens new window) 和常规配置。
npm i @commitlint/cli @commitlint/config-conventional -D
新增commitlint.config.js引入提交规范集。
// commitlint.config.js
module.exports = {
extends: ['@commitlint/config-conventional']
}
修改.huskyrc.json,即commit-msg钩子触发时,将运行对应的命令。
// .huskyrc.json
{
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
}
再次暂存并提交,可以看到commit-msg钩子触发时commitlint对提交说明进行了验证。

# Husky v4 迁移 v7
先来说说husky为什么由v4破坏性地更新到v7了,v4版本的husky会生成所有类型的git hook,其好处就是无论用户设置任何类型的git hook,husky都能保证其正常运行,但是坏处也很明显,即用户不设置任何git hook,husky也向git添加了所有类型的git hook。
;v4版本缺陷的根本原因在于,任何一个完整的git hook功能,一是要在.git/hooks添加相应的hook,二是要在根目录添加.huskyrc.json文件或package.json中配置此hook要执行的命令,但是作者没有很好的办法来同步它们。
还好git 2.9版本引入了core.hooksPath,此属性可指定git hook所在目录。husky启用git钩子后,将会把git hook的目录指定为.husky,此方式好处就在于,需要什么hook,就在.husky文件夹添加什么hook,不需要什么都不用添加,更多 详细参考 (opens new window)。
现在由v4版本迁移至v7版本,请卸载目录下husky(v4)。
npm un husky
然后安装最新版本的husky(目前v7.0.4)。
npm i husky -D
启用git钩子。
npx husky install
启用后将在根目录生成.husky文件夹,其中默认包括_文件夹、.gitignore和husky.sh。

同时.git/config文件中将添加如下属性。
// .git/config
[core]
...
hooksPath = .husky
;.husky目录下新建pre-commit文件,其中--no-install表示强制npx使用本地模块,不下载远程模块,但是本地模块不存在时将会报错。
// .husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
echo 'husky > pre-commit'
npx --no-install lint-staged
验证提交说明的迁移也是一样,在.husky下新建commit-msg钩子。
// .husky/commit-msg
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
echo 'husky > commit-msg'
npx --no-install commitlint --edit $1
最后根目录下的.huskyrc.json也可以删除了,因为v7版本已经不依赖这一层映射关系了,.husky目录内hook将直接运行命令,这也就是v7版本更新后的优点,缺点也很明显,无端增加了用户的学习成本。
# 小结
# Husky v4 版本
由于是利用git来管理代码,因此先要保证项目已经初始化为git仓库。
git init
安装git hook工具和检查工具、提交说明检查工具和检查规则集,其中husky用于为git添加hook工具,lint-staged用于检查暂存中的文件,commitlint用于检查提交说明,config-conventional用于提供检查规则集。
npm i husky@4.3.8 lint-staged @commitlint/cli @commitlint/config-conventional -D
新建.lintstagedrc.json,用于修复暂存中的文件。
// .lintstagedrc.json
{
"src/**/*.{js,vue}": [
"eslint --fix",
"git add"
]
}
新建commitlint.config.js,启用config-conventional规则集。
// commitlint.config.js
module.exports = {
extends: ['@commitlint/config-conventional']
}
新建.huskyrc.json,git钩子触发时执行相应的命令。
// .huskyrc.json
{
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
}
# Husky v7 版本
;v4迁移v7请卸载husky(v4)版本。
npm un husky
安装最新版本husky(目前v7.0.4)。
npm i husky -D
启用git钩子。
npx husky intall
新建pre-commit、commit-msg钩子。
// .husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
echo 'husky > pre-commit'
npx --no-install lint-staged
// .husky/commit-msg
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
echo 'husky > commit-msg'
npx --no-install commitlint --edit $1
再删除.huskyrc.json文件即可。
# 插件
以上插件的作用。
- husky (opens new window):为
git客户端添加hook工具,v4(v4.3.8及之前版本)将在.git/hooks中注入所有类型的hook,而v7版本将指定git hook目录为.husky - lint-staged (opens new window):仅对暂存中的文件执行相应的命令,提高运行效率
- @commitlint/cli (opens new window):用于检查提交说明
- @commitlint/config-conventional (opens new window):提供检查提交说明的规则集
# 常见问题
# 如何关闭或跳过 eslint 校验规则?
有些项目并不能很好地适用eslint的规则集,例如 vue/recommended (opens new window) 规则集中 vue/no-v-html (opens new window) 禁用了v-html指令,但是有时又不得已会使用v-html。
第一种方式可在.eslintrc.js中关闭此规则。
// .eslintrc.js
module.exports = {
...
rules: {
...
'vue/no-v-html': 'off',
},
}
告警级别分为三种,
0/off表示忽略问题,1/warn表示警告,2/error表示报错
第二种方式是利用 vue/comment-directive (opens new window) 规则,即通过注释来跳过某一行或多行的校验。
此规则支持的注释包括。
eslint-disable:关闭校验eslint-enable:开启校验,配合eslint-disabled可关闭多行校验eslint-disable-line:关闭当前行校验eslint-disable-next-line:关闭下一行校验
关闭多行校验,其中6和7行的v-html校验已跳过。

关闭当前行的校验,其中32行中的语句末尾分号校验已跳过。

关闭下一行校验。

注意以上注释会关闭掉所有eslint校验规则,建议在注释后添加禁用的规则名称,更多 详细参考 (opens new window)。

# 旧项目如何接入格式化工具?
旧项目通常情况下源文件格式都会存在问题,但是不可能每个文件都去Ctrl + S手动修复格式,可在package.json中添加命令来修复src内源文件。
但是强烈不推荐你这么做,因为格式化可能会造成潜在的问题。如果源文件较少,且能够保证做全量测试,那么你可以这样做。但是源文件较多,建议只格式化你修改的文件,其余不相关的文件还是不要动。
// package.json
{
...
"scripts": {
...
"eslint:fix": "eslint src/**/*.js src/**/*.vue --fix"
}
}
注意
eslint:fix仅能修复简单的错误,其它例如组件props默认值的情况,还是需要你手动修复
# 无法格式化的文件如何修复?
部分文件保存时无法格式化,频繁闪烁。

此情况最好是对某个文件执行eslint的fix功能,如果文件较多,建议执行npm run eslint:fix命令。
npx eslint src/main.js --fix
# 提交时如何跳过 lint 阶段?
如果你觉得在执行git commit -m ...提交时非常耗时,你可以执行以下命令来跳过lint-staged和commitlint两个阶段。
但是还是建议不要这样做,因为你无法保证提交到远端的代码是非常规范的。
git commit -m 'xxx' --no-verify
# lint-staged 在 pre-commit 阶段报错
在node版本较低的情况下,且安装了lint-staged的v12版本(目前v12.3.4)。
;node版本为v12.14.1时,提交时抛出以下错误。

;node版本为v14.10.1时,提交时抛出以下错误。

;官方 (opens new window)明确了所支持的node版本。

两种解决方式,方式一可升级node版本,方式二则可安装lint-staged的v11.2.6及以下版本,推荐方式二。
# 维护配置文件到 package.json
诸如.eslintrc.js和.prettierrc.js等配置文件,都维护在开发目录下,显得多而复杂,另外后期此类文件都是不用修改的,还有另外一种配置方式,就是维护至package.json下。
;eslint。
// .eslintrc.js
module.exports = {
root: true,
extends: ['plugin:vue/recommended', 'plugin:prettier/recommended'],
rules: {
quotes: ['error', 'single'],
},
}
// package.json
{
...
"eslintConfig": {
"root": true,
"extends": [
"plugin:vue/recommended",
"plugin:prettier/recommended"
],
"rules": {
"quotes": [
"error",
"single"
]
}
}
}
;prettier。
// .prettierrc.js
module.exports = {
semi: false,
printWidth: 110,
singleQuote: true,
endOfLine: 'crlf',
arrowParens: 'avoid',
}
// package.json
{
...
"prettier": {
"semi": false,
"printWidth": 110,
"singleQuote": true,
"endOfLine": "crlf",
"arrowParens": "avoid"
}
}
;husky。
// .huskyrc.json
{
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
}
// package.json
{
...
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
}
}
;lint-staged。
// .lintstagedrc.json
{
"src/**/*.{js,vue}": [
"eslint --fix",
"git add"
]
}
// package.json
{
...
"lint-staged": {
"src/**/*.{js,vue}": [
"eslint --fix",
"git add"
]
}
}
;commitlint。
// commitlint.config.js
module.exports = {
extends: ['@commitlint/config-conventional'],
}
// package.json
{
...
"commitlint": {
"extends": [
"@commitlint/config-conventional"
]
}
}
;babel。
// babel.config.js
module.exports = {
presets: ['@vue/cli-plugin-babel/preset'],
}
// package.json
{
...
"babel": {
"presets": [
"@vue/cli-plugin-babel/preset"
]
}
}
;browserslist。
// .browserslistrc
> 1%
last 2 versions
not dead
// package.json
{
...
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
# 如何配置 vue 代码片段?
;vetur提供了代码片段用来提高开发效率。

# vscode 中 vue.json 文件
;vscode中键入Shift + Ctrl + P,输入snippets,选择配置用户代码片段。
然后输入vue,选择vue.json。

删除掉所有注释,添加以下内容。
// vue.json
{
"Vue Component": {
"prefix": "cpt",
"body": [
"<template>",
" $1",
"</template>",
"",
"<script>",
"export default {",
"",
"}",
"</script>",
"",
"<style>",
"",
"</style>"
],
"description": "Vue 组件模板"
}
}
;vue单文件内输入cpt,代码片段已生效。
此方式配置在vscode中,在任何项目中都能生效,但是配置起来很麻烦,vue.json中要一行一行添加。

# 项目级模板
项目根目录下.vscode目录结构如下。
├── .vscode
│ ├── settings.json
│ ├── vetur
│ │ ├── snippets
│ │ │ ├── template.vue
可在snippets文件夹下添加template.vue文件。
// .vscode/vetur/snippets/template.vue
<template>
<div>
${0}
</div>
</template>
此方式新增vue文件后,Reload重载后可生效,此方式相对vue.json文件,仅设置单文件即可,不需要一行一行添加。

# vscode 插件目录
;vscode键入Shift + Ctrl + P,输入extensions folder,选择打开拓展文件夹。
打开octref.vetur-xx.xx.xx目录,进入server/dist/veturSnippets文件夹。

添加自定义代码片段,也可复制default.vue然后修改。
// veturSnippets/page.vue
<template>
${0}
</template>
<script>
export default {
name:''
}
</script>
<style>
</style>
;Reload重载后生效。

# 🎉 写在最后
🍻伙伴们,如果你已经看到了这里,觉得这篇文章有帮助到你的话不妨点赞👍或 Star (opens new window) ✨支持一下哦!
手动码字,如有错误,欢迎在评论区指正💬~
你的支持就是我更新的最大动力💪~
GitHub (opens new window) / Gitee (opens new window)、GitHub Pages (opens new window)、掘金 (opens new window)、CSDN (opens new window) 同步更新,欢迎关注😉~