Vue开发时让Prettier与Eslint和谐相处

1,730 阅读8分钟

当我们用脚手架初始化一个Vue项目后,如果我们同时安装了PrettierEslint后,用Vscode打开编辑器就会出现一堆关于代码风格的错误信息,经过一番折腾终于让两者和谐相处了,还添加了一些额外功能。

1. 安装依赖

一般来说脚手架会将PrettierEslint和其依赖的插件都安装上,下面列出我的package.json用到的

"devDependencies": {
    "@babel/core": "^7.12.16",
    "@babel/eslint-parser": "^7.12.16",
    "@vue/cli-plugin-babel": "~5.0.0",
    "@vue/cli-plugin-eslint": "~5.0.0",
    "@vue/cli-plugin-router": "~5.0.0",
    "@vue/cli-plugin-vuex": "~5.0.0",
    "@vue/cli-service": "~5.0.0",
    "eslint": "^7.32.0",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-prettier": "^4.0.0",
    "eslint-plugin-vue": "^8.0.3",
    "prettier": "^2.4.1",
    "sass": "^1.32.7",
    "sass-loader": "^12.0.0",
    "vue-template-compiler": "^2.6.14"
}

2. 定义Prettier代码风格

我建议将配置项作为独立的文件保存,这样便于配置项共享,提高代码复用,下面列出.prettierrc的配置项,你可以根据自己的喜好修改

{
  "printWidth": 1200, // 每行的最大长度,超出则会换行。这里设置为1200
  "tabWidth": 4, // 每个tab缩进占用的空格数
  "useTabs": true, // 使用tab缩进,而不是空格
  "singleQuote": true, // 使用单引号而不是双引号
  "semi": true, // 语句末尾是否加分号
  "trailingComma": "none", // 不用尾随逗号
  "bracketSpacing": true, // 花括号内的前后保持一个空格
  "arrowParens": "avoid", // 当箭头函数只有一个参数时省略括号
  "parser": "babel", // 代码解析器设置为babel
  "vueIndentScriptAndStyle": true, // 在Vue文件中缩进<script>和<style>标签内的代码
  "endOfLine": "auto", // 行尾换行符自动检测
  "overrides": [ // 针对特定文件类型的特殊设置
    {
      "files": "*.vue", // 针对.vue文件
      "options": {
        "parser": "vue" // 使用vue解析器
      }
    },
    {
      "files": "*.css", // 针对.css文件
      "options": {
        "parser": "css" // 使用css解析器
      }
    },
    {
      "files": "*.json", // 针对.json文件
      "options": {
        "parser": "json" // 使用json解析器
      }
    }
  ]
}

3. 确定Eslint配置项

为了让Eslint配置项不与Prettier冲突,那么就必须让Eslint的校验风格与Prettier保持一致,就需要对.eslintrc.js进行修改

  • 首先要引入插件
extends: ['plugin:vue/recommended', 'eslint:recommended', 'plugin:prettier/recommended', '@vue/prettier'],
  • 其次要应用Prettier配置
rules: {
    'prettier/prettier': [
        'error',
        {
            usePrettierrc: true
        }
    ],
}
  • 我还期望在对vue格式化时,对Vue的属性进行一定的排序
{ 
    rules: {
        'vue/attributes-order': [
            'error',
            {
                order: ['DEFINITION', 'LIST_RENDERING', 'CONDITIONALS', 'RENDER_MODIFIERS', 'GLOBAL', 'UNIQUE', 'TWO_WAY_BINDING', 'OTHER_DIRECTIVES', 'OTHER_ATTR', 'EVENTS', 'CONTENT'],
                alphabetical: true
            }
        ],
    }
}

下面列出.eslintrc.js所有配置项,以供参考

module.exports = {
    root: true, // 表明这是根配置文件,ESLint在找到配置文件后不会再向上查找
    env: {
        node: true // 配置环境为Node.js,全局变量和作用域默认是Node.js环境
    },
    extends: [
        'plugin:vue/recommended', // 使用Vue官方推荐的ESLint配置
        'eslint:recommended', // 使用ESLint推荐的默认规则
        'plugin:prettier/recommended', // 使用Prettier插件的推荐配置
        '@vue/prettier' // 使用Vue和Prettier兼容的配置
    ],
    rules: {
        'prettier/prettier': [
            'error',
            {
                usePrettierrc: true, // 使用项目根目录下的.prettierrc配置
                // "printWidth": 1200, //如果没有Prettierrc配置,也可以手写规则
            }
        ],
        'vue/attributes-order': [
            'error',
            {
                order: [
                    'DEFINITION', // 定义性属性,如 'is'
                    'LIST_RENDERING', // 列表渲染属性,如 'v-for'
                    'CONDITIONALS', // 条件渲染属性,如 'v-if', 'v-else-if', 'v-else', 'v-show', 'v-cloak'
                    'RENDER_MODIFIERS', // 渲染修饰符,如 'v-pre', 'v-once'
                    'GLOBAL', // 全局属性/id
                    'UNIQUE', // 唯一属性,如 'ref', 'key', 'slot'
                    'TWO_WAY_BINDING', // 双向绑定属性,如 'v-model'
                    'OTHER_DIRECTIVES', // 其他指令,如 'v-custom-directive'
                    'OTHER_ATTR', // 其他普通属性,如 'custom-prop="foo"'
                    'EVENTS', // 事件绑定属性,如 '@click="functionCall"'
                    'CONTENT' // 原始内容,如 'v-text' 或 'v-html'
                ],
                alphabetical: true // 按字母顺序排列
            }
        ],
        'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', // 生产环境中禁止console.log,开发环境允许
        'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' // 生产环境中禁止debugger,开发环境允许
    },
    parserOptions: {
        parser: 'babel-eslint' // 使用babel-eslint解析器
    }
};

4. 配置格式化脚本

4.1 Prettier脚本(性能较好,可以对各种文件类型进行格式化)

该脚本会按照.prettierrc的配置项进行整个项目的格式化

"scripts": {
    "format": "prettier --write src/**/*.{vue,js,css} ./*.{js,json} !./package-lock.json",
},

下面逐一解析这段命令中每个部分的含义:

  • "format": 这是一个npm脚本命令的名称,表示对 src 目录和当前目录中的某些文件进行格式化。
  • "prettier": 这是格式化工具的名称,指明使用 Prettier 来格式化代码。
  • "--write": 这是 Prettier 的一个选项,表示将格式化后的结果直接写入文件。
  • "src/**/*.{vue,js,css}":
    • "src/":表示在 src 目录下进行查找。
    • "**/*.{vue,js,css}":表示递归查找 src 目录下的所有子目录,并格式化扩展名为 .vue.js.css 的文件。
  • "./*.{js,json}":
    • "./":表示当前目录。
    • "*.{js,json}":表示格式化当前目录下扩展名为 .js.json 的文件。
  • "!./package-lock.json":
    • "!":表示排除的路径。
    • "./package-lock.json":表示不格式化当前目录下的 package-lock.json 文件。

接下来这样就可以执行下面命令对整个项目进行格式化了

npm run format

4.2 Eslint脚本(性能较差,强项是对js文件类型的处理)

经过上面的格式化后,发现vue文件关于属性排序的问题,vscode只会给予提示,并不会修复该问题,此时我们还需要做进一步工作。

执行如下命令,eslint会对相应的文件进行代码检查及修复,修复不了的错误会在控制台提示。当然我们也可以将一些不重要的错误校验规则放到.eslintrc.js中的rules里面,来避免警告和提示。

npx eslint --fix src/**/*.{vue,js}

或配置到package.json

"format:eslint": "eslint --fix src/**/*.{vue,js}",

执行之后,排序的问题就会按照我们配置的顺序进行自动排列

4.3 Stylelint脚本(css属性规则排序)

如果想要对css,scss,vue等css相关文件按照一定规则排序,可以参考《Vue开发时让CSS属性按规则排序》

5. Vscode集成格式化插件

5.1 Vscode安装Prettier插件

安装该插件,并将该插件作为默认格式化工具,该插件会自动读取项目根目录的.prettierrc文件进行格式化,非常方便。

5.2 Vscode安装ESLint插件

安装该插件,并将该插件作为默认格式化工具,该插件会自动读取项目根目录的.eslintrc.js文件进行格式化,非常方便。

5.2.1 Vscode保存后,自动格式化并对属性排序

由于要维护的项目不同,可能代码格式化风格也不太一样,自己维护的项目还好,改别人的代码也自动格式化不太好,配置项改来改去也不方便,我这里是针对该项目进行vscode配置。

在使用VS Code编辑器时,你可以通过以下方式来管理只针对特定项目的配置项,而不影响全局的VS Code配置项:

5.2.1 使用工作区设置(Workspace Settings)

  • 在你的项目目录中,VS Code会自动创建一个名为.vscode的文件夹(如果没有,可以手动创建
  • .vscode文件夹中创建一个名为settings.json的文件,用来存放该项目的特定配置项
  • 将你想要针对该项目设置的配置项(如编辑器行为、格式化规则、插件设置等)写入到settings.json文件中

5.2.3 如何操作:

  • 打开VS Code,并打开你的项目文件夹。
  • 使用快捷键 Ctrl + Shift + P(在 macOS 上是 Cmd + Shift + P)打开命令面板。
  • 输入并选择 Preferences: Open Workspace Settings (JSON),这会打开你当前项目的工作区设置文件 settings.json
  • 在 settings.json 文件中添加或修改你需要的项目特定配置项。例如:
{
    "editor.formatOnSave": true,
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": "explicit"
    },
    "eslint.format.enable": true
}

image.png

这样即便全局没有开启保存格式化,只要打开这个项目,保存也会自动格式化和修复错误。

5.2.4 工作区设置的优势:

  • 隔离性强:  工作区设置仅影响当前打开的项目,不会影响其他项目或全局设置。
  • 版本控制友好:  工作区设置文件(如 .vscode/settings.json)可以和项目代码一起进行版本控制,方便团队协作和跨设备同步配置。

通过使用工作区设置,你可以有效地管理和维护针对特定项目的配置项,而不必担心影响到其他项目或全局的VS Code配置。

6. git提交前自动对修改的文件进行格式化

6.1 安装必要的依赖

首先,安装 huskylint-staged

npm i husky lint-staged -D

6.2 配置 Husky 和 Lint-staged

在项目的 package.json 文件中,添加以下配置:

{
    "husky": {
        "hooks": {
                "pre-commit": "lint-staged"
        }
    },
    "lint-staged": {
        "src/**/*.{vue,js,css}": ["prettier --write"],
        "./*.{js,json} !./package-lock.json": ["prettier --write"]
    }
}

到了这一步,可以让修改后的文件放到暂存区,手动执行命令验证配置项是否可以正确执行

npx lint-staged

6.3 初始化 Husky

在项目根目录下运行以下命令来初始化 Husky:

npx husky install

这会在项目根目录下创建 .husky 目录。

6.4 添加 Pre-commit Hook

image.png 在 .husky 目录下创建一个名为 pre-commit 的文件,并添加以下内容:

#!/bin/sh 
. "$(dirname "$0")/_/husky.sh" 

npx lint-staged

确保脚本文件是可执行的(windows系统非必须):

chmod +x .husky/pre-commit

6.5 验证配置是否生效

通过git命令或者Vscode的图像界面都可以触发

image.png

git add . 
git commit -m "ci:测试"

执行后

image.png