一、eslint

        eslint它规范的是代码偏向语法层面上的风格。本篇文章以一个基本的vue项目,来说明eslint+prettier+husky配置项目代码规范,为了更好的描述本文,我恢复了vscode的默认设置(即未安装eslint,prettier等插件,setting中也没有相关配置)

1、新建vue3.0脚手架项目

vue create eslint-test

2、项目安装eslint

npm install eslint --save-dev

3、运行以下命令,生成.eslintrc.js

npx eslint --init

.eslintrc.js文件

module.exports = {
    "env": {
        "browser": true,
        "es2021": true,
        "node": true
    },
    "extends": [
        "eslint:recommended",//继承Eslint中推荐的(打钩的)规则项http://eslint.cn/docs/rules/
        "plugin:vue/essential"// 此项是用来配置vue.js风格
    ],
    "parserOptions": {
        "ecmaVersion": 13,
        "sourceType": "module"
    },
    "plugins": [
        "vue"
    ],
    "rules": {
    }
};

3,查看这个推荐的默认规则

这里的规则,写在后面的会覆盖前面的,并且rules中的规则最后会覆盖这里的,所以我们自定义规则就是写在rules中,才能覆盖之前的规则,从而生效。

"extends": [
    "eslint:recommended",//继承Eslint中推荐的(打钩的)规则项http://eslint.cn/docs/rules/
    "plugin:vue/essential"// 此项是用来配置vue.js风格https://eslint.vuejs.org/rules
],

eslint规则rule官网

eslint-plugin-vue (vuejs.org)

这个默认规则是怎么生效的呢?举个例子,我们点进去链接,可以看到这个no-debugger是打上了对勾(也就是"eslint:recommended")中生效的规则,然后我们再在项目中写个debugger,然后命令行运行检查eslint的命令,就会报错了。

打了勾表示属于recommended采用的规则

有个扳手则表示可自动修复不需手动修复

4,自定义规则 

Eslint附带了大量的校验规则,这些规则的值分别有如下规律:

off | 0 :表示关闭规则。
warn | 1 :表示将该规则转换为警告。
error | 2 :表示将该规则转换为错

常见的rules规则:

// "semi": [2, "always"],//语句强制分号结尾
// "quotes": [2, "double"],//引号类型 ""
//"no-alert": 0,//禁止使用alert
//"no-console": 2,//禁止使用console
//"no-const-assign": 2,//禁止修改const声明的变量
//"no-debugger": 2,//禁止使用debugger
//"no-duplicate-case": 2,//switch中的case标签不能重复
//"no-extra-semi": 2,//禁止多余的冒号
//"no-multi-spaces": 1,//不能用多余的空格

定义好规则后,怎会出现对应的校验报错

5,package.json中配置检查命令行 

上文中,我们是手动输入命令行来检查代码是否符合eslint规范的,这样每次检查都要输入一遍,有的人要是记不住这命令怎么办?于是可以在package.json的script中写死这个脚本:

"lint": "eslint --ext .js --ext .jsx --ext .vue src/",

 于是,项目根目录运行npm run lint,实际上就是运行:

npx eslint --ext .js --ext .jsx --ext .vue src/

6,eslint插件自动检查规范 

为避免每次校验都需要输入命令的问题,可以通过vscode提供的插件实现保存时自动校验

在vscode插件市场搜索Eslint安装且重启即可

7,package.json中配置自动修复命令行 

eslint校验后会通过红色波浪线和控制台提示不符合规则的代码,需要使用命令行进行自动修复,注意有(扳手)🔧的图标对应的规则才是可以修复的

在package.json中添加

"lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/"

在根目录执行这个npm run lint-fix,则会自动修复,某些规则需要手动修复

8,在vscode中配置setting,让每次保存代码时自动修复

通过配置setting.json实现保存的时候自动校验和修复,而不需要像上一步那样需要输入命令行现在利用vscode的eslint插件我们已经能一写完代码,就知道是否符合规范了。然而我们还想实现的是每次写完代码,按下ctrl+s保存时,它能够自动修复

在vscode中按快捷键ctrl+shift+p,输入setting,打开setting.json

增加这段配置即可(如果未生效重启vscode):

 //配置保存时按照eslint文件的规则来处理一下代码
"editor.codeActionsOnSave": {
   "source.fixAll": true,
   "eslint.autoFixOnSave" : true,
},

 9、配置eslintignore

有些文件,我们不希望它受eslint管辖,可以在根目录新建.eslintignore文件,把想要自由的文件或目录丢进去即可:

.eslintrc.js
.prettierrc.js
babel.config.js
vetur.config.js
/node_modules/

10,总结 

1、为什么要使用eslint

因为每个人的代码习惯不一样,每个开发人员都需要和他人协作或者项目需要交接给下一代开发者。
保持统一的代码规范,可以极大地提高效率,降低沟通和理解代码的成本。

2、既然已经有vscode的eslint插件帮助我们自动检查和修复代码了,为什么还需要在pakage.json中配置eslint命令行

因为vscode是我们自己电脑上的编辑器,我们不能保证另一个人拿到我们的代码时他也是用vscode的(也许他用记事本?)。就算他用vscode,我们也不能保证他安装了eslint插件。
	 ,他就可以使用pakage.json的命令行来检查和修复代码。因为项目中肯定需要安装eslint依赖,也肯定有我们配置的.eslintrc.js规则文件,这样依旧能保证代码的统一规范。

二,prettier

1,prettier的作用

上文我们配置了eslint,它规范的是代码偏向语法层面上的风格。比如说不能使用console啦,箭头函数参数必须包裹在括号中啦这些。

prettier规范的是代码偏向于排版层面上的风格

2,安装prettier

npm install --save-dev --save-exact prettier

3,使用命令行修复格式化

npx prettier --write src/

4,配置自定义的prettier规则

需要在根目录新建一个文件.prettierrc.js(则需要module.export),如果是.prettierrc(则只需要json格式)

//编写代码时,尽量符合以下规则
module.exports = {
  printWidth: 80, //单行长度,超过则自动换行
  tabWidth: 2, //缩进长度
  useTabs: false, //使用空格代替tab缩进
  semi: false, //句末使用分号
  singleQuote: true, //使用单引号
  endOfLine: 'auto', //配置换行符格式为auto
  arrowParens: 'avoid', //单参数箭头函数参数周围使用圆括号-eg: (x) => xavoid:省略括号
  bracketSpacing: true, //在对象前后添加空格-eg: { foo: bar }
  insertPragma: false, //在已被preitter格式化的文件顶部加上标注
  jsxBracketSameLine: false, //多属性html标签的‘>’折行放置
  rangeStart: 0,
  requirePragma: false, //无需顶部注释即可格式化
  trailingComma: 'none', //多行时尽可能打印尾随逗号
  useTabs: false //使用空格代替tab缩进
}

为了测试是否生效,我故意把句末是否使用分号写成了false(上文中eslint是需要分号的)。执行npx prettier --write src/,可以看到,分号被取消了,但是不满足eslint规则,报错了:

冲突的问题稍后再说,这里只是说明我们配置的.prettierrc.js是生效的。

5,prettier插件保存代码自动修复

 同样的,我们不可能每写一行代码,就运行npx prettier --write src/来美化一次代码,我们希望保存代码时,就能够自动格式化代码。于是又需要安装prettier插件。

然后再ctrl+shift+p打开vscode的setting.json文件,添加如下配置:

 //prettier可以格式化很多种格式,所以需要在这里对应配置下
 "[html]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[css]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[less]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[vue]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[javascript]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescriptreact]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[jsonc]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescript]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[json]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  //这个设置在ctrl+s的时候,会启用默认的格式化,这里是prettier
  "editor.formatOnSave": true

 这时候按保存代码,会发现在闪动,依旧是报eslint的错:

6,让编译器能报prettier的错

到目前为止,对于prettier,我们还无法查看哪里不符合规则,而只是通过自动修复来规范代码风格。现在我们想像eslint一样,代码一写,如果不符合,就出现红色的波浪线提示哪里有问题。

这个要怎么实现呢?可以利用eslint的报错,把prettier当成eslint的插件注入eslint中,让eslint来报这个错(实际上还是vscode的eslint实现的)

安装依赖:

npm i -D eslint-plugin-prettier

然后再在.eslintrc.js 配置文件中添加这个配置,意思就是使用 eslint 报prettier的错误:

// .eslintrc.js
{
  "plugins": ["prettier"],
  "rules": {
    "prettier/prettier": "error"
  }
}

这样设置后,我故意把代码排版变乱:

可以注意到,编辑器已经可以同时报eslint和prettier的错误了。

这时保存下代码,除了冲突的部分,都会被自动修复。

接下来可以着手解决这两家伙冲突的问题了。

7,解决eslint和prettier的冲突问题

网上说的解决冲突的依赖安装一下:

npm i -D eslint-config-prettier

 把prettier设置的规则添加到extends数组中:

  extends: [
    'eslint:recommended', //继承Eslint中推荐的(打钩的)规则项http://eslint.cn/docs/rules/
    'plugin:vue/essential', // 此项是用来配置vue.js风格
    'prettier',//把prettier中设置的规则添加进来,让它覆盖上面设置的规则。这样就不会和上面的规则冲突了
  ],

这样一来,就让在它之前的所有可能会与 prettier 规则存在冲突的 eslint规则失效,并使用 prettier 的规则进行代码检查。

接着,在项目中ctrl+s报错代码,可以看到报错消失,变成了prettier设置的单引号了:

这才是真正意义上的解决冲突。

接下来,再来说rules中的冲突怎么办?它的优先级要高于extends中的规则,而extends中冲突的规则已经被prettier搞失效了,你又在rules中再定义,于是又会和prettier中产生冲突。

也就是说,上文解决冲突只会解决extends中的冲突。不会解决rules中的冲突!

那我们这种冲突应该怎么解决?

第一种方案:把自己想要的规则配置成npm包发布,然后引入到这个extends数组中。

第二种方案:relus中的配置和prettier中的保持一致即可。
8,让没有安装prettier的项目也能代码格式化

有的时候,我们的项目并没有配置prettier,而我们希望在vscode中可以在保存代码时美化代码。就可以在ctrl+shift+p打开setting.json配置prettier规则:

 /*  prettier的配置 */
  "prettier.printWidth": 80, // 超过最大值换行
  "prettier.tabWidth": 2, // 缩进字节数
  "prettier.useTabs": false, // 句尾添加分号
  "prettier.singleQuote": false, // 使用单引号代替双引号
  "prettier.proseWrap": "preserve", //  (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid:省略括号
  "prettier.bracketSpacing": true, // 在对象,数组括号与文字之间加空格 "{ foo: bar }"
  "prettier.endOfLine": "auto", // 结尾是 \n \r \n\r auto
  "prettier.eslintIntegration": false, //不让prettier使用eslint的代码格式进行校验
  "prettier.htmlWhitespaceSensitivity": "ignore",
  "prettier.ignorePath": ".prettierignore", // 不使用prettier格式化的文件填写在项目的.prettierignore文件中
  "prettier.jsxBracketSameLine": false, // 在jsx中把'>' 是否单独放一行
  "prettier.jsxSingleQuote": false, // 在jsx中使用单引号代替双引号
  "prettier.parser": "babylon", // 格式化的解析器,默认是babylon
  "prettier.requireConfig": false, // Require a 'prettierconfig' to format prettier
  "prettier.stylelintIntegration": false, //不让prettier使用stylelint的代码格式进行校验
  "prettier.trailingComma": "none", // 在对象或数组最后一个元素后面是否加逗号(在ES5中加尾逗号)
  "prettier.tslintIntegration": false,
  "prettier.arrowParens": "avoid"
  • 既然vscode中设置了pettier(上文第八点),已经能够格式化代码了,还要安装prettier依赖,去配置格式。
原因和eslint中一样,vscode中配置的,其他人也许不用vscode,也许安装了vscode,但是没有在setting.json中设置规范。而项目读取prettier规范时有一个优先级的,如果在根目录找到了.prettier文件,则不会去查找setting.json中的规则了。只有找不到.prettier文件时,我们配置在setting.json中的规则才会生效。

 三,提交代码时eslint校验

1,husky 

为了保证每次提交的 git 代码是正确的,为此我们可以使用 eslint 配合 git hook, 在进行git commit 的时候验证eslint规范

如果 eslint 验证不通过,则不能提交。

我们需要安装一个 git 的 hook 工具 – husky (我刚开始安装的是最新版本,发现没有生效,回退后才生效)

npm install husky@4.3.8 --save-dev

意思是在进行 git commit 的时候 先去执行 pre-commit 里面的命令 : 我们在这里输出 husky 并且执行 npm run lint (我们在上文第一章,第5点加上的验证eslint的命令)

如果eslint验证通过了,则会进行commit 操作,否则会报eslint的错误提示。

生效的标志是项目的.git/hooks目录下,会生成一堆文件,原本是只有pre-commit.sample这类文件,等husky安装完成,会多出pre-commit等文件。

再运行git commit命令,就会检查代码了。

2,lint-staged

如果这是一个新项目以上的就已经满足要求了,但是如果拿到的项目是一个老项目呢,别人开发了很久,这个时候加入再加入 eslint 规则,全局去检查,会发现一堆报错信息。这个就慌了。修改可能带来其他问题。

为了解决这种问题,我们就需要引入 lint-staged

lint-staged 的作用是只对 git add 缓存区的代码进行 eslint 代码规范校验。这样就避免了全局校验的问题。你修改了上面代码,你就提交了什么代码,其他代码不做 eslint 校验。

npm install --save-dev lint-staged

 在 package.json 中添加:

"lint-staged": {
    "src/**/*.{css,scss,less}": [
      "npm run lint",
      "git commit"
    ],
    "src/**/*.{js,vue}": [
      "npm run lint",
      "git commit"
    ]
  }

参考:eslint+pretter

详细完成配置

.eslintrc.js

module.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true
  },
  extends: [
    'eslint:recommended',
    'plugin:vue/essential',
    'prettier' //把prettier中设置的规则添加进来,让它覆盖上面设置的规则。这样就不会和上面的规则冲突了,表示 eslint-plugin-prettier,需要放到最后以覆盖别的规则
  ],
  parserOptions: {
    ecmaVersion: 12,
    sourceType: 'module'
  },
  plugins: ['vue', 'prettier'], // 表示 eslint-config-prettier
  rules: {
    //0关闭,1警告,2禁止
    'prettier/prettier': 'error', //使用prettier
    semi: [0, 'always'], //语句强制分号结尾
    quotes: [0, 'double'], //引号类型 ""
    'no-alert': 0, //禁止使用alert
    'no-console': 0, //禁止使用console
    'no-const-assign': 2, //禁止修改const声明的变量
    'no-debugger': 2, //禁止使用debugger
    'no-duplicate-case': 2, //switch中的case标签不能重复
    'no-extra-semi': 2, //禁止多余的冒号
    'no-multi-spaces': 1, //不能用多余的空格
    'no-unused-vars': 1, //不能出现未使用变量
    'vue/no-reserved-component-names': 0, //不允许在组件定义中使用保留名称
    'vue/multi-word-component-names': 0 //要求组件名称始终为多字
  }
}

 .prettierrc.js

//编写代码时,尽量符合以下规则
module.exports = {
  printWidth: 80, //单行长度,超过则自动换行
  tabWidth: 2, //缩进长度
  useTabs: false, //使用空格代替tab缩进
  semi: false, //句末使用分号
  singleQuote: true, //使用单引号
  endOfLine: 'auto', //配置换行符格式为auto
  arrowParens: 'avoid', //单参数箭头函数参数周围使用圆括号-eg: (x) => xavoid:省略括号
  bracketSpacing: true, //在对象前后添加空格-eg: { foo: bar }
  insertPragma: false, //在已被preitter格式化的文件顶部加上标注
  jsxBracketSameLine: false, //多属性html标签的‘>’折行放置
  rangeStart: 0,
  requirePragma: false, //无需顶部注释即可格式化
  trailingComma: 'none', //多行时尽可能打印尾随逗号
  useTabs: false //使用空格代替tab缩进
}

.eslintignore

.eslintrc.js
.prettierrc.js
vue.config.js
babel.config.js
vetur.config.js
/node_modules/

package.json

{
  "name": "cloudui",
  "version": "2.0.2",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "eslint --ext .js --ext .jsx --ext .vue src/",
    "lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/"
  },
  "dependencies": {
    ...
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-router": "~4.5.0",
    "@vue/cli-plugin-vuex": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/compiler-sfc": "^3.0.0",
    "babel-eslint": "^10.1.0",
    "compression-webpack-plugin": "^6.1.1",
    "copy-webpack-plugin": "^5.1.2",
    "eslint": "^7.32.0",
    "eslint-config-prettier": "^8.5.0",
    "eslint-loader": "^4.0.2",
    "eslint-plugin-prettier": "^4.0.0",
    "eslint-plugin-vue": "^9.1.1",
    "node-sass": "^5.0.0",
    "prettier": "2.7.1",
    "sass-loader": "^10.1.0",
    "spark-md5": "^3.0.1",
    "svg-sprite-loader": "^3.8.0",
    "vue-simple-uploader": "^0.7.6",
    "vue-template-compiler": "^2.6.11"
  }
}

settings.json

{
  //配置保存时按照eslint文件的规则来处理一下代码
  "editor.codeActionsOnSave": {
    "source.fixAll": true,
    "eslint.autoFixOnSave": true
  },
  //prettier可以格式化很多种格式,所以需要在这里对应配置下
  "[html]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[css]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[less]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[vue]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescriptreact]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[jsonc]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[typescript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  "[json]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
  //这个设置在ctrl+s的时候,会启用默认的格式化,这里是prettier
  "editor.formatOnSave": true,
  /*  prettier的配置,为没有配置prettier使用 */
  "prettier.printWidth": 80, // 超过最大值换行
  "prettier.tabWidth": 2, // 缩进字节数
  "prettier.useTabs": false, // 句尾添加分号
  "prettier.singleQuote": false, // 使用单引号代替双引号
  "prettier.proseWrap": "preserve", //  (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid:省略括号
  "prettier.bracketSpacing": true, // 在对象,数组括号与文字之间加空格 "{ foo: bar }"
  "prettier.endOfLine": "auto", // 结尾是 \n \r \n\r auto
  "prettier.eslintIntegration": false, //不让prettier使用eslint的代码格式进行校验
  "prettier.htmlWhitespaceSensitivity": "ignore",
  "prettier.ignorePath": ".prettierignore", // 不使用prettier格式化的文件填写在项目的.prettierignore文件中
  "prettier.jsxBracketSameLine": false, // 在jsx中把'>' 是否单独放一行
  "prettier.jsxSingleQuote": false, // 在jsx中使用单引号代替双引号
  "prettier.parser": "babylon", // 格式化的解析器,默认是babylon
  "prettier.requireConfig": false, // Require a 'prettierconfig' to format prettier
  "prettier.stylelintIntegration": false, //不让prettier使用stylelint的代码格式进行校验
  "prettier.trailingComma": "none", // 在对象或数组最后一个元素后面是否加逗号(在ES5中加尾逗号)
  "prettier.tslintIntegration": false,
  "prettier.arrowParens": "avoid"
}

Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐