【Vue】はじめてのeslintとprettier設定

## この記事の概要

eslintとprettier設定でとりあえず保存時にオートフォーマットできて、エラーなしの状態になったので備忘録

## 追記

~~結局こちらの記事とほとんど同じ設定にしたので削除します。
[もうprettierで消耗したくない人へのvueでのeslint設定](https://qiita.com/diggy-mo/items/bb01bcb54237f16bb008)~~

##### ※さらに追記

prettier入れないとstyleが自動整形できず、とても不便なので結局入れました。

※不要な設定も含まれていると思います。不要と判明した都度、消していきます。
※別途競合の発見、より快適になる設定を見つけたら記事更新します。

## package.json(抜粋)

```zsh
% npm i -D babel-eslint eslint-config-prettier eslint-plugin-prettier eslint eslint-plugin-vue prettier prettier-eslint vue-eslint-parser
```

```package.json
{
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-eslint": "^10.1.0",
    "babel-loader": "^7.1.2",
    "babel-preset-env": "^1.6.0",
    "babel-preset-stage-3": "^6.24.1",
    "eslint": "^6.8.0",
    "eslint-config-prettier": "^6.10.1",
    "eslint-plugin-prettier": "^3.1.2",
    "eslint-plugin-vue": "^6.2.2",
    "prettier": "^2.0.4",
    "prettier-eslint": "^9.0.1"
  }
}
```

## settings.json(抜粋)

```settings.json
{
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true,
    "source.organizeImports": true,
    "source.fixAll": true
  },
  "editor.formatOnPaste": false,
  "editor.formatOnSave": false,
  "editor.formatOnType": true,

  "eslint.validate": [
    "javascript",
    "javascriptreact",
    "vue",
    "typescript"
  ],

  "vetur.format.defaultFormatter.css": "prettier",
  "vetur.format.defaultFormatter.scss": "prettier",
  "vetur.format.defaultFormatter.html": "prettier",
  "vetur.format.defaultFormatter.js": "prettier-eslint",
  "vetur.format.defaultFormatter.ts": "vscode-typescript",
  "vetur.validation.template": false
}
```

## .eslintrc.json

rulesはお好み
※indent系の設定はprettierと競合します。
vue/script-indentのbaseIndentをどうしても入れたかったのですが、諦めました。

https://github.com/vuejs/eslint-plugin-vue/issues/369
→prettierはフォーマットの為に存在しているのだからフォーマットはprettierに従いなさい、ということみたいです

```..eslintrc.json
{
  "env": {
    "browser": true
  },
  "parser": "vue-eslint-parser",
  "parserOptions": {
    "parser": "babel-eslint"
  },
  "plugins": [
    "vue"
  ],
  "extends": [
    "eslint:recommended",
    "plugin:prettier/recommended",
    "plugin:vue/recommended",
    "prettier/vue"
  ],
  "rules": {
    "vue/component-name-in-template-casing": ["error", "PascalCase"],
    "vue/singleline-html-element-content-newline": "off",
    "vue/html-self-closing": "off",
    "vue/valid-template-root": "off",
    "vue/no-unused-vars": "off",
    "vue/valid-v-for": "off",
    "vue/no-multi-spaces": ["error", { "ignoreProperties": false }],
    "no-extra-parens": "warn",
    "no-multi-spaces": "error",
    "eqeqeq": ["error", "smart"],
    "semi": ["error", "always"],
    "quotes": ["error", "single"],
    "block-spacing": ["error", "always"],
    "comma-spacing": "error",
    "computed-property-spacing": "error",
    "arrow-spacing": ["error", {
      "before": true,
      "after": true
    }],
    "key-spacing": ["error", {
      "beforeColon": false,
      "afterColon": true,
      "mode": "minimum"
    }],
    "func-call-spacing": ["error", "never"],
    "no-spaced-func": "error",
    "space-infix-ops": ["error", { "int32Hint": false }],
    "no-multiple-empty-lines": ["error", { "max": 1 }],
    "spaced-comment": ["error", "always", {
      "line": {
        "markers": ["/"],
        "exceptions": ["-", "+"]
      },
      "block": {
        "markers": ["!"],
        "exceptions": ["*"],
        "balanced": true
      }
    }],
    "no-console": "off",
    "space-in-parens": ["error", "never"],
    "no-var": "error",
    "space-before-function-paren": "off",
    "space-before-blocks": ["error", {
        "functions": "always",
        "keywords": "always",
        "classes": "always"
    }],
    "brace-style": ["error", "1tbs", { "allowSingleLine": true }],
    "no-unused-vars": ["warn", { "vars": "all", "args": "after-used", "ignoreRestSiblings": false }],
    "no-lonely-if": "error",
    "no-trailing-spaces": "error",
    "operator-linebreak": ["error", "before"],
    "semi-spacing": "error",
    "keyword-spacing": "error",
    "arrow-parens": "off"
  }
}
```

## prettierと競合するルール

```..eslintrc.json
{
  "rules": {
    "vue/html-closing-bracket-newline": ["error", { "multiline": "never" }],
    "vue/script-indent": ["error", 2, { "baseIndent": 2 }],
    "arrow-parens": ["error", "always"]
  }
}
```

## .prettierrc.js

```..prettierrc.js
module.exports = {
  printWidth: 80,
  tabWidth: 2,
  singleQuote: true,
  semi: true,
  trailingComma: 'none',
  bracketSpacing: true,
  arrowParens: 'avoid',
};
```

## 参考

[How to properly set up Nuxt with ESLint and Prettier in VSCode](https://medium.com/@gogl.alex/how-to-properly-set-up-eslint-with-prettier-for-vue-or-nuxt-in-vscode-e42532099a9c)
[フロントエンドにESLint、Prettier、stylelintを導入して快適な開発環境を整えました](http://cluex-developers.hateblo.jp/entry/2019/01/10/171237)
[ESLint - Prettier連携のやり方と仕組み](https://qiita.com/ikngtty/items/4df2e13d2fa1c4c47528)
[VSCode上でvueファイルに対してESLintが快適に動作する設定](https://qiita.com/fukasawah/items/cfff8957f3956850dc7e)
[Vue.jsスタイルガイドとeslint-plugin-vue検証ルールのマッピング](https://qiita.com/ota-meshi/items/85bf17494c8ea0be05d7)