定制开发vue3 +vite+ts实战项目添加 eslint + prettier + lint-staged 踩坑指南

定制开发初始化项目

// 定制开发创建一个空的 vue3-ts 项目,yarn create vite my-vue-app --template vue-ts// 安装依赖cd my-vue-app && yarn// 定制开发默认是没有创建git仓库的,定制开发这里我们初始化一下git init
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

定制开发这个模板是没有使用配置eslintprettier的,定制开发接下来我们依次安装这些依赖。

集成

定制开发首先我们安装eslint

yarn add eslint  -D
  • 1

定制开发接下来初始化eslint:

npx eslint --init
  • 1

定制开发依次选择这些选项:

询问:How would you like to use ESLint? ...选择:To check syntax and find problems询问:What type of modules does your project use? ...选择:JavaScript modules (import/export)询问:Which framework does your project use? ...选择:Vue.js询问:Does your project use TypeScript?选择:yes询问:Where does your code run? ...选择:Browser  (node定制开发服务端选择node项)询问:What format do you want your config file to be in? ...选择:JavaScript询问:Would you like to install them now with npm?选择:yes...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

到这一步,定制开发我们就已经安装了相关的依赖了,定制开发并且得到一个已配置好的.eslintrc.json文件:

{    // 定制开发设置我们的运行环境为浏览器 + es2021 + node ,否则eslint在遇到 Promise,window定制开发等全局对象时会报错    "env": {        "browser": true,        "es2021": true,        "node": true    },    // 继承eslint定制开发推荐的规则集,vue定制开发基本的规则集,typescript的规则集    "extends": [        "eslint:recommended",        "plugin:vue/essential",        "plugin:@typescript-eslint/recommended"    ],    // 支持ts定制开发的最新语法    "parserOptions": {        "ecmaVersion": "latest",        "parser": "@typescript-eslint/parser",        "sourceType": "module"    },    // 添加vue和@typescript-eslint插件,增强eslint的能力    "plugins": [        "vue",        "@typescript-eslint"    ],    "rules": {    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

定制开发然后我们为package.json定制开发文件增加一个lint命令

{    "scripts":{        // lint定制开发当前项目中的文件并且定制开发开启自动修复        "lint": "eslint . --ext .vue,.js,.ts,.jsx,.tsx --fix",    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

定制开发一切进行得非常顺利,定制开发然而当我们运行lint命令时,定制开发会发现不是我们想要的结果:

定制开发命令行在解析vue文件会报parsing error。这是因为,默认eslint不会解析vue文件,定制开发所以我们需要一个额外定制开发的解析器来帮我们解析vue文件。

定制开发这一步本来是在我们继承plugin:vue/essential的时候,定制开发默认为我们配置了的

定制开发但是我们后续又extend"plugin:@typescript-eslint/recommended",定制开发它又继承来自./node_modules/@typescript-eslint/eslint-plugin/dist/configs/base.js

定制开发而我们在配置文件中的extends顺序是:

{    "extends": [        "eslint:recommended",        "plugin:vue/essential",        "plugin:@typescript-eslint/recommended"    ],}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

所以vue-eslint-parser@typescript-eslint/parser覆盖了。定制开发这里我们只需要将外部的parser改为vue-eslint-parser,并且在parserOptions定制开发中添加一个parser:@typescript-eslint/parser属性即可,定制开发而这一步我们之前的配定制开发置文件里面已经有做了。这里可以查看

{    ...    // 新增,解析vue文件    "parser":"vue-eslint-parser",    "parserOptions": {        "ecmaVersion": "latest",        "parser": "@typescript-eslint/parser",        "sourceType": "module"    },    ...}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

两个parser的区别在于,外面的parser用来解析vue文件,使得eslint能解析标签中的内容,而parserOptions中的parser,即@-eslint/parser`用来解析vue文件中``标签中的代码。

接下来我们继续运行 yarn run lint,会发现又报错了:

  • `节点要求有且只有一个根节点
  • 找不到defineProps的定义

我们知道,这两个特性都是vue3引入的,问题可能出在我们的配置不支持vue3项目,翻阅./node_modules/eslint-plugin-vue目录的相关配置,便可发现问题所在,eslint-plugin-vue提供了几个预设的配置集。

没有vue3-前缀的规则集对应vue2项目,vue3-开头的对应vue3项目。而我们默认使用的是 vue/essential这个规则集,由于我们是vue3项目,所以应该使用vue3的规则集,这里使用vue3-recommended

{    "extends": [        "eslint:recommended",        -- "plugin:vue/essential",        ++ "plugin:vue/vue3-recommended",        "plugin:@typescript-eslint/recommended"    ],}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

然后再运行,yarn run lint,发现还是会报错。

因为defineProps是一个全局的预编译宏,eslint不知其定义在哪里,所以需要在global选项中将其标注出来,然而我阅读了eslint-plugin-vue这个文件后,发现它已经预设了。

我们只需要在env中开启这个环境变量即可:

{    "env": {        "browser": true,        "es2021": true,        "node": true,        // 开启setup语法糖环境         ++ "vue/setup-compiler-macros":true    },}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

然后我们再运行yarn run lint,oh 谢天谢地,终于不报错了。

添加vscode-eslint 插件

就目前而言,我们能在命令行中使用eslint了,然而写一行代码就去运行下检测脚本实在太麻烦,好在我们可以结合vscode-eslint插件使用。

vscode中安装好vscode-eslint插件,它便会在我们写代码的时候对我们的脚本进行lint,我们就没必要再运行yarn run lint 了。同时,我们可以新建一个.vscode/settings.json文件,为这个本项目开启自动修复

{  "editor.codeActionsOnSave": {    "source.fixAll": true  }}
  • 1
  • 2
  • 3
  • 4
  • 5

这样一来,当你按下ctrl + s保存的时候,eslint便会智能地为你修复一些代码错误了。

安装依赖说明

  • JavaScript 和 JSX 检查工具
  • 目前比较流行的 JavaScript 代码规范
  • 使用 ESLint 检查 .vue文件 的 ` 和 ``
  • 基于 prettier 代码风格的 eslint 规则
  • 禁用所有与格式相关的 eslint 规则,解决 prettier 与 eslint 规则冲突,确保将其放在 extends 队列最后,这样它将覆盖其他配置

集成

相比 eslint 而言 prettier 就会要温和一些了。 prettier 并没有提供太多的配置选项给我们选择,所以我们在网上随便找一份配置就行。

yarn add prettier -D
  • 1

然后再项目根目录添加一份配置文件

// .prettierrc.jsmodule.exports = {  printWidth: 80, //单行长度  tabWidth: 2, //缩进长度  useTabs: false, //使用空格代替tab缩进  semi: true, //句末使用分号  singleQuote: true, //使用单引号}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

这是我的配置文件,如果需要更多的配置方法,可以参考。

然后再package.json中添加一个脚本

{    "scripts":{        "format": "prettier --write ./**/*.{vue,ts,tsx,js,jsx,css,less,scss,json,md}"    }}
  • 1
  • 2
  • 3
  • 4
  • 5

当运行这个命令时,就会将我们项目中的文件都格式化一次。

一般而言,我们还需要集成 vscode-prettier这个插件来完成自动保存格式化,在插件市场安装好了以后,在我们的.vscode/settings.json中添加如下规则

{   "editor.formatOnSave": true, // 开启自动保存   "editor.defaultFormatter": "esbenp.prettier-vscode", // 默认格式化工具选择prettier}
  • 1
  • 2
  • 3
  • 4

这样一来,当我们在vscode写代码的时候,便会自动格式化了。

解决 eslint 和 prettier 的冲突

理想状态下,到这一步我们写代码的时候,eslintprettier会相互协作,既美化我们的代码,也修复我们质量不过关的代码。然而现实总是不那么完美,我们会发现某些时候,eslint提示错误,我们修改了以后,屏幕会闪一下然后又恢复到报错状态,自动修复失效了。

这是因为eslint 有一部分负责美化代码的规则和 prettier的规则冲突了,这里可以参考我的另外一篇博客,这里我们只给出方案。 用 eslint-config-prettier 提供的规则集来覆盖掉eslint冲突的规则,并用eslint-plugin-prettier来使eslint使用prettier的规则来美化代码。

yarn add eslint-config-prettier eslint-plugin-prettier -D
  • 1

然后在 .eslintrc.jsonextends的最后添加一个配置:

  "extends": [    "eslint:recommended",    "plugin:vue/vue3-recommended",    "plugin:@typescript-eslint/recommended",    "plugin:prettier/recommended" // 新增,必须放在最后面  ],
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

然后我们重启一下vscode,就会发现冲突消失了,我们的自动修复和自动格式化也能相互协作了。

配置 husky + lint-staged

理论上,到上一步我们已经能使得我们的项目获得不错的开发规范约束了。然而仍然有可以改进的地方:

  • 如果是在项目中途才接入eslint + prettier,如果对原来的代码使用yarn run lint 或者 yarn run format势必会带来大范围地改动,甚至会造成冲突。
  • 对于一些不使用vscode编辑器,或者没有安装prettiereslint插件的用户而言,他们不能享受到插件带来的协助,而他们的代码自然大概率是不符合规范的,不该被提交到代码库。

基于上述的顾虑,社区提供了 husky + lint-staged的渐进式方案。 lint-staged 是一个只检测git暂存区的lint工具,husky是一个用来给我们的项目添加git hook的工具,git hook是进行git操作会触发的脚本,例如:提交的时候会触发pre-commit钩子,输入提交信息会触发commit-msg钩子。 我们用husky安装pre-commit钩子,我们就可以在进行git commit操作的时候,运行我们的脚本来检测待提交的代码是否规范,便可以只对暂存区的文件进行检查。

首先安装依赖

yarn add husky lint-staged -D
  • 1

添加一个在package.json中添加一条preinstall脚本

{    "script":{        "prepare": "husky install"    }}
  • 1
  • 2
  • 3
  • 4
  • 5

prepare脚本会在 yarn install 之后自动运行,这样依赖你的小伙伴clone了你的项目之后会自动安装husky,这里由于我们已经运行过 yarn install 了,所以我们需要手动运行一次yarn run prepare,然后我们就会得到一个目录.husky

接下来我们为我们git仓库添加一个pre-commit钩子,运行

npx husky add .husky/pre-commit "npx --no-install lint-staged"
  • 1

这回在我们的.husky目录下生成一个pre-commit的脚本

#!/bin/sh . "$(dirname "$0")/_/husky.sh"npx --no-install lint-staged
  • 1
  • 2
  • 3
  • 4

接下来我们配置lint-staged,在package.json中添加下面的配置信息。

{  "lint-staged": {    "*.{js,vue,ts,jsx,tsx}": [      "prettier --write",      "eslint --fix"    ],    "*.{html,css,less,scss,md}": [      "prettier --write"    ]  }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

这样之后,我们后续提交到暂存区的代码也就会被eslint+prettier格式化和检查,进一步保证我们的代码规范。

配置 husky + lint-staged 后带来了新的eslint+prettier冲突问题

问题背景

Windows笔记本上新拉完代码,在执行pre-commit时,出现如下错误:

Delete `␍`eslint(prettier/prettier) 复制代码
  • 1
  • 2

下面是几种个人尝试过的解决方案:

解决方案

一、Crtl+S保存文件

Crtl+S保存当前报错文件,eslint错误消失,这里我尝试网上提供的这个解决方案没有用,反而是我重启一下vscode编辑器报错没有了,不过总之这个方案是不行的

二、yarn run lint --fix

比上面省事,eslint错误消失,但暂存区多了n个文件改动记录,对比Working tree也没发现任何不同。

缺点:需要commit所有文件,多余。

``

三、配置.prettierrc文件

在项目根目录下的.prettierrc文件中写入即可。其实就是不让prettier检测文件每行结束的格式.

"endOfLine": "auto" 
  • 1
  • 2

缺点:不能兼容跨平台开发,从前端工程化上讲没有做到尽善尽美。

[参考资料:Why do I keep getting Delete ‘cr’

四、通过IDE一键切换

这是评论区掘金同道提供的方法,一般IDE下方状态栏会提供“切换行尾序列”的工具,如上图,一键切换到正确的行尾序列即可。

缺点:只能修复当前文件,不能解决整个项目报错的问题。

五、最佳方案

问题根源:

罪魁祸首是git的一个配置属性:core.autocrlf

由于历史原因,windows下和linux下的文本文件的换行符不一致。

* Windows在换行的时候,同时使用了回车符CR(carriage-return character)和换行符LF(linefeed character) * 而Mac和Linux系统,仅仅使用了换行符LF * 老版本的Mac系统使用的是回车符CR 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
WindowsLinux/MacOld Mac(pre-OSX
CRLFLFCR
‘\ ’‘’‘\r’

因此,文本文件在不同系统下创建和使用时就会出现不兼容的问题。

我的项目仓库中默认是Linux环境下提交的代码,文件默认是以LF结尾的(工程化需要,统一标准)。

当我用windows电脑git clone代码的时候,若我的autocrlf(在windows下安装git,该选项默认为true)为true,那么文件每行会被自动转成以CRLF结尾,若对文件不做任何修改,pre-commit执行eslint的时候就会提示你删除CR

现在可以理解ctrl+syarn run lint --fix方案为何可以修复eslint错误了吧,因为Git自动将CRLF转换成了LF

最佳实践:

现在VScodeNotepad++编辑器都能够自动识别文件的换行符是LF还是CRLF。 如果你用的是windows,文件编码是UTF-8且包含中文,最好全局将autocrlf设置为false

git config --global core.autocrlf false
  • 1
  • 2

注意:git全局配置之后,你需要重新拉取代码。

由于我们组内全部使用的windows,所有直接配置.prettierrc

endOfLine: 'crlf', // Windows
  • 1

配置文件总览

// package.json{  "name": "my-vue-app",  "version": "0.0.0",  "scripts": {    "dev": "vite",    "build": "vue-tsc --noEmit && vite build",    "preview": "vite preview",    "lint": "eslint . --ext .vue,.js,.ts,.jsx,.tsx --fix",    "format": "prettier --write ./**/*.{vue,ts,tsx,js,jsx,css,less,scss,json,md}",    "prepare": "husky install"  },  "dependencies": {    "vue": "^3.2.25"  },   "devDependencies": {    "@types/node": "^16.3.1",    "@typescript-eslint/eslint-plugin": "^5.22.0",    "@typescript-eslint/parser": "^5.22.0",    "@vitejs/plugin-vue": "^1.2.4",    "@vitejs/plugin-vue-jsx": "^1.1.6",    "@vue/compiler-sfc": "^3.0.5",    "eslint": "^8.15.0",    "eslint-config-prettier": "^8.5.0",    "eslint-config-standard": "^17.0.0",    "eslint-plugin-prettier": "^4.0.0",    "eslint-plugin-vue": "^8.7.1",    "husky": "^8.0.1",    "lint-staged": "^12.4.1",    "prettier": "^2.6.2",    "typescript": "^4.3.2",    "vite": "^2.8.6",    "vue-tsc": "^0.33.9"  }  "devDependencies": {    "@typescript-eslint/eslint-plugin": "^5.7.0",    "@typescript-eslint/parser": "^5.7.0",    "@vitejs/plugin-vue": "^2.0.0",    "eslint": "^8.4.1",    "eslint-config-prettier": "^8.3.0",    "eslint-plugin-prettier": "^4.0.0",    "eslint-plugin-vue": "^8.2.0",    "husky": "^7.0.4",    "lint-staged": "^12.1.3",    "prettier": "^2.5.1",    "typescript": "^4.4.4",    "vite": "^2.7.2",    "vue-tsc": "^0.29.8"  },  "lint-staged": {    "*.{js,vue,ts,jsx,tsx}": [      "prettier --write",      "eslint --fix"    ],    "*.{html,css,less,scss,md}": [      "prettier --write"    ]  }}// .eslintrc.jsmodule.exports = {  // 设置我们的运行环境为浏览器 + es2021 + node ,否则eslint在遇到 Promise,window等全局对象时会报错  env: {    browser: true,    es2021: true,    node: true,    // 开启setup语法糖环境    'vue/setup-compiler-macros': true,  },  // 继承eslint推荐的规则集,vue基本的规则集,typescript的规则集  extends: [    'plugin:vue/vue3-recommended',    'plugin:@typescript-eslint/recommended',    'standard', // 格式化规范    'plugin:prettier/recommended', // 新增,必须放在最后面,prettier规则覆盖与eslint冲突的规则    'prettier', // 避免vue 与 prettier冲突    'eslint:recommended',  ],  // 定义ESLint的解析器  parser: 'vue-eslint-parser',  // 支持ts的最新语法  parserOptions: {    ecmaVersion: 'latest',    parser: '@typescript-eslint/parser',    sourceType: 'module',  },  // 添加vue和@typescript-eslint插件,增强eslint的能力  plugins: ['vue', '@typescript-eslint', 'prettier'],  rules: {    // "off"或者0    //关闭规则关闭    // "warn"或者1    //在打开的规则作为警告(不影响退出代码)    // "error"或者2    //把规则作为一个错误(退出代码触发时为1)    'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',    // 解析vue模板错误规则    'vue/no-parsing-error': [      2,      {        'x-invalid-end-tag': false,        'missing-semicolon-after-character-reference': false,      },    ],    'no-unused-expressions': ['error', { allowShortCircuit: true, allowTernary: true }], // 允许使用短路、三目    'no-param-reassign': ['error', { props: false }], // 函数形参可修改    'vue/multi-word-component-names': 'off', // eslint-plugin-vue @8版本中新增了不少的规则,第一条就是 **‘vue/multi-word-component-names’: ‘error’,**所有index.vue 会报错,解决方法:    'no-new-object': 'off', // 关闭不可以new对象的规则    'no-explicit-any': 'off', // 可以使用any,但请尽量不使用any    '@typescript-eslint/no-explicit-any': 'off', // ts可以使用any    'vue/v-on-event-hyphenation': 'off', // 关闭事件命名样式需要用连字符  },};// .prettierrc.js/**   tips:    endOfLine: 'crlf' 因为eslint和prettier就这个问题上不一致互相冲突,我们这里统一使用Windows系统的.    如果是有mac使用需求的请使用git config --global core.autocrlf false解决 */module.exports = {  printWidth: 100, //单行长度  tabWidth: 2, //缩进长度  useTabs: false, //使用空格代替tab缩进  semi: true, //句末使用分号  singleQuote: true, //使用单引号  endOfLine: 'crlf', // Windows};// .vscode/settings.json{  "editor.formatOnSave": true,  "editor.defaultFormatter": "esbenp.prettier-vscode",  "editor.codeActionsOnSave": {    "source.fixAll": true  }}// .husky/pre-commit#!/bin/sh. "$(dirname "$0")/_/husky.sh"npx --no-install lint-staged
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151

鸣谢

参考:





感谢各位开源作者

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发