为 Vue 和 Nuxt 应用使用 ESLint 和 Prettier

eslint-plugin-vue 插件是 VueNuxt 应用程序的官方 ESLint 插件。它允许我们使用 ESLint 检查 .vue 文件中 <template><script> 块中的代码,以查找任何语法错误、Vue 指令的错误使用以及违反 Vue 风格指南的 Vue 样式。此外,我们使用 Prettier 来强制执行代码格式,因此就像我们在上一节中为基本特定配置所做的那样,安装 eslint-plugin-prettiereslint-config-prettier。让我们在以下步骤中整理好所有这些:

  1. 使用 npm 安装 eslint-plugin-vue 插件:

    $ npm i eslint-plugin-vue --save-dev
    bash

    你可能会收到一些警告:

    npm WARN eslint-plugin-vue@5.2.3 requires a peer of eslint@^5.0.0
    but none is installed. You must install peer dependencies
    yourself.
    npm WARN vue-eslint-parser@5.0.0 requires a peer of eslint@^5.0.0
    but none is installed. You must install peer dependencies
    yourself.
    text

    忽略它们,因为 eslint-plugin-vue 的最低要求是 ESLint v5.0.0 或更高版本以及 Node.js v6.5.0 或更高版本,而你应该已经拥有最新版本。

    你可以在 https://eslint.vuejs.org/user-guide/installation 查看最低要求。除了 Vue 风格指南之外,你还应该查看 https://eslint.vuejs.org/rules/Vue 规则。

  2. ESLint 配置文件中添加 eslint-plugin-vue 插件及其通用规则集:

    // .eslintrc.js
    module.exports = {
      extends: [
        'plugin:vue/recommended'
      ]
    }
    javascript
  3. 安装 eslint-plugin-prettier eslint-config-prettier 并将它们也添加到 ESLint 配置文件中:

    // .eslintrc.js
    module.exports = {
      'extends': [
        'plugin:vue/recommended',
        'plugin:prettier/recommended'
      ],
      'plugins': [
        'prettier'
      ]
    }
    javascript

但这仍然不够。你可能希望配置一些 Vue 规则以适合你的偏好。让我们在下一节中了解一些我们可能想要配置的默认 Vue 键规则。

有关 eslint-plugin-vue 插件的更多信息,请访问 https://eslint.vuejs.org/。有关 Vue 指令,请访问 https://www.google.com/search?q=https://vuejs.org/v2/api/Directives,有关 Vue 风格指南,请访问 https://vuejs.org/v2/style-guide/。

配置 Vue 规则

本书中我们只想覆盖四个默认的 Vue 规则。你只需要像在上一节中为 eslint-plugin-prettier 插件所做的那样,在 .eslintrc.js 文件的 rules 选项中添加你偏好的规则。让我们在以下步骤中进行操作:

  1. vue/v-on-style 规则配置为 "longform",如下所示:

    // .eslintrc.js
    'rules': {
      'vue/v-on-style': ['error', 'longform']
    }
    javascript

    vue/v-on-style 规则强制 v-on 指令样式使用简写或完整形式。默认设置为简写,例如:

    <template>
      <div @click="foo"/>
      <div v-on:click="foo"/>
    </template>
    html

    但在本书中,我们更偏爱完整形式,如下例所示:

    <template>
      <div v-on:click="foo"/>
      <div @click="foo"/>
    </template>
    html
  2. 配置 vue/html-self-closing 规则以允许在 void 元素上使用自闭合标签,如下所示:

    // .eslintrc.js
    'rules': {
      'vue/html-self-closing': ['error', {
        'html': {
          'void': 'always'
        }
      }]
    }
    javascript

    void 元素是指在任何情况下都不允许包含内容的 HTML 元素,例如 <br>、<hr>、<img>、<input>、<link> 和 <meta>。在编写 XHTML 时,强制要求自闭合这些元素,例如 <br/> 和 <img src="…​" />。在本书中,我们希望允许这样做,即使在 HTML5 中 / 字符被认为是可选的。

    vue/html-self-closing 规则下,即使它的目的是强制 HTML 元素中的自闭合标签,你也会因为自闭合这些 void 元素而收到错误。这有点令人困惑,对吧?在 Vue.js 模板中,对于没有内容的元素,我们可以使用以下两种样式之一:

    <YourComponent></YourComponent>
    <YourComponent/> (自闭合)
    html

    在此规则下,第一种选择将被拒绝,如下例所示:

    <template>
      <MyComponent/>
      <MyComponent></MyComponent>
    </template>
    html

    但是,它也会拒绝自闭合的 void 元素:

    <template>
      <img src="...">
      <img src="..." />
    </template>
    html

    换句话说,在 Vue 规则中,不允许 void 元素使用自闭合标签。因此,html.void 选项的默认值设置为 'never'。因此,如果你想像本书中那样允许在这些 void 元素上使用自闭合标签,则将该值设置为 'always'。

  3. 配置 vue/max-attributes-per-line 规则以关闭此规则,如下所示:

    // .eslintrc.js
    'rules': {
      'vue/max-attributes-per-line': 'off'
    }
    javascript

    vue/max-attributes-per-line 规则旨在强制每行一个属性。默认情况下,当两个属性之间存在换行符时,该属性被认为在新的一行中。以下是此规则下的示例:

    <template>
      <MyComponent lorem="1"/>
      <MyComponent lorem="1"
                   ipsum="2"
      />
      <MyComponent
        lorem="1"
        ipsum="2"
        dolor="3"
      />
      <MyComponent lorem="1" ipsum="2"/>
      <MyComponent
        lorem="1" ipsum="2"
      />
      <MyComponent
        lorem="1" ipsum="2"
        dolor="3"
      />
    </template>
    html

    然而,此规则与 Prettier 冲突。我们应该让 Prettier 处理这种情况,这就是为什么我们要关闭此规则。

  4. 配置 eslint/space-before-function-paren 规则:

    // .eslintrc.js
    'rules': {
      'space-before-function-paren': ['error', 'always']
    }
    javascript

    eslint/space-before-function-paren 规则旨在强制在函数声明的括号前加一个空格。ESLint 的默认行为是添加空格,这也是 StandardJS 中定义的规则。请参见以下示例:

    function message (text) { ... } // ✓ ok
    function message(text) { ... } // ✗ avoid
    message(function (text) { ... }) // ✓ ok
    message(function(text) { ... }) // ✗ avoid
    javascript

    然而,在上述规则下,当你使用 Prettier 时,你会收到如下错误:

    /middleware/auth.js
    1:24 error Delete · prettier/prettier
    text

    我们将忽略来自 Prettier 的错误,因为我们想遵循 Vue 中的规则。但是,目前 Prettier 还没有禁用该功能的选项,详见 https://prettier.io/docs/en/options.html。如果你因为 Prettier 而删除了该空格,你可以通过在此 Vue 规则下将值设置为 'always' 来重新添加它。

  5. 因为 ESLint 默认只针对 .js 文件,所以在 ESLint 命令中使用 --ext 选项(或 glob 模式)包含 .vue 扩展名,以便在终端上使用上述配置运行 ESLint

    $ eslint --ext .js,.vue src
    $ eslint "src/**/*.{js,vue}"
    bash

    你也可以在 package.json 文件中使用 .gitignore 中的自定义命令在 scripts 选项中运行它,如下所示:

    // package.json
    "scripts": {
      "lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
      "lint-fix": "eslint --fix --ext .js,.vue --ignore-path .gitignore ."
    }
    json
    // .gitignore
    node_modules
    build
    nuxt.config.js
    prettier.config.js
    text

    ESLint 将在检查所有 JavaScriptVue 文件时忽略上述 .gitignore 片段中定义的文件。在通过 webpack 进行热重载时检查文件是一个好主意。只需将以下代码片段添加到 Nuxt 配置文件中,以便在每次保存代码时运行 ESLint

    // nuxt.config.js
    ...
    build: {
      extend(config, ctx) {
        if (ctx.isDev && ctx.isClient) {
          config.module.rules.push({
            enforce: "pre",
            test: /\.(js|vue)$/,
            loader: "eslint-loader",
            exclude: /(node_modules)/
          })
        }
      }
    }
    javascript

    你可以在我们的 GitHub 仓库中的 /chapter-14/eslint-plugin-vue/integrate/ 找到一个将此插件与 ESLint 集成的示例。

正如你在本节和前几节中看到的,在单个配置文件中混合使用 ESLintPrettier 可能会有问题。为了使它们 “作为一个团队” 协同工作,你可能需要付出的努力可能不值得。为什么不尝试分别运行它们而不将它们耦合在一起呢?让我们在下一节中了解如何为 Nuxt 应用程序执行此操作。

在 Nuxt 应用中分别运行 ESLint 和 Prettier

解决 ESLintPrettier 之间冲突(尤其是在 space-before-function-paren 方面)的另一种可能方案是完全不集成它们,而是分别运行它们来格式化和检查我们的代码。让我们在以下步骤中实现这一点:

  1. package.json 文件中为 PrettierESLint 分别创建脚本,如下所示:

    // package.json
    "scripts": {
      "prettier": "prettier --check \"{components,layouts,pages,store,middleware,plugins}/**/*.{vue,js}\"",
      "prettier-fix": "prettier --write {components,layouts,pages,store,middleware,plugins}/**/*.{vue,js}\"",
      "lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
      "lint-fix": "eslint --fix --ext .js,.vue --ignore-path .gitignore ."
    }
    json

    这样,我们就可以完全忘记工作流程中的 eslint-plugin-prettiereslint-config-prettier 配置。我们仍然保留 eslint-plugin-vue 和我们在本章中已经配置的规则,但从 .eslintrc.js 文件中完全删除 Prettier

    // .eslintrc.js
    module.exports = {
      //...
      'extends': [
        'standard',
        'plugin:vue/recommended',
        // 'prettier' // <- 删除了这一行
      ]
    }
    javascript
  2. 当我们想要分析我们的代码时,先运行 Prettier,然后运行 ESLint

    $ npm run prettier
    $ npm run lint
    bash
  3. 同样,当我们想要修复格式并检查我们的代码时,先运行 Prettier,然后运行 ESLint

    $ npm run prettier-fix
    $ npm run lint-fix
    bash

你可以看到,这种解决方案以这种方式使我们的工作流程更清晰、更简洁。不再有冲突——轻而易举。太棒了。

你可以在我们的 GitHub 仓库中的 /chapter-14/eslint-plugin-vue/separate/ 找到一个分别运行 ESLintPrettier 的示例。

做得好。你已经完成了本章的第一个主要部分。我们希望你将开始(或已经开始)为你的 VueNuxt 应用程序编写漂亮且可读的代码,并利用这些出色的格式化程序和检查器。随着你在本书中对 Nuxt 的学习接近尾声,我们将在下一节中引导你完成如何部署 Nuxt 应用程序的过程。所以请继续阅读。