【古い情報】Vue+TypeScriptをESLint+Prettierでなるべくコンパクトな設定でLint+整形する

## 概要

:::note warn
警告
この記事の情報は現時点では古くなっています。
ESLintとPrettierを組み合わせる場合、別の記事を参考にしてください。

例：
- [Prettierの導入とESLintとの併用について](https://qiita.com/yudwig/items/4a75de5b2238106f1bf4)

経緯については以下を参考にしてください。

- [Prettier と ESLint の組み合わせの公式推奨が変わり plugin が不要になった](https://blog.ojisan.io/prettier-eslint-cli)
:::

Vue+TypeScriptを使用したソースコードに対しESLintとPrettierを適用するにあたり、ESLint関連のパッケージそれぞれがどのような役割を持っているか調べてみると思ったよりもコンパクトな内容(plugins,parser,parserOptionsなどは指定しなくても大丈夫)でLint+整形が出来ることを確認できたため、最終的に確認できた設定と調べた内容を共有します。

動作確認はVSCodeで行っています。

## 事前に準備が必要なもの

* Vue3+TypeScriptで動作するソースコード
    (Vue+TypeScriptの組み合わせを試したのがVue3だったため。Vue2でもこの記事の内容はほとんど変わらないと思います)
    * 私は以下の記事を参考に用意しました。
        * [vue-next（Vue.js 3.0 wip）+ TypeScript + webpackでの開発環境を構築する](https://qiita.com/ryo2132/items/2b10f03e3d4ea04be649)
* VSCode
    * ESLintプラグイン(`dbaeumer.vscode-eslint` v2.1.8)
    * 以下の設定が行われていること (`eslint.validate`は拡張子tsに適用するために必要でした)

        ``` json
        {
            "editor.codeActionsOnSave": {
                "source.fixAll.eslint": true
            },
            "eslint.validate": [
                "typescript"
            ],
        }
        ```

## 最終的に必要だったパッケージと.eslintrc.js
最終的な`.eslintrc.js`とインストールしたパッケージの情報は以下の通りです。
(ルール設定は別途必要になると思いますが、この記事では省略しています)

.eslintrc.js

```javascript
module.exports = {
  extends: [
    "eslint:recommended",
    "plugin:vue/vue3-recommended",  // "plugin:vue/vue3-strongly-recommended"もあります
    "@vue/typescript",
    "plugin:prettier/recommended",
    "prettier/vue",  // 必須ではありません(ルールを書き換えるだけのため)
    "prettier/@typescript-eslint", // 必須ではありません(ルールを書き換えるだけのため)
  ],
  env: {
    node: true,
  },
  rules: {},
};
```

yarnでインストールしたパッケージ

```
yarn add -D eslint prettier eslint-config-prettier eslint-plugin-prettier
yarn add -D @typescript-eslint/parser @typescript-eslint/eslint-plugin
yarn add -D eslint-plugin-vue@next @vue/eslint-config-typescript
```

<details><summary>参考： 今回の作業後のpackage.json(クリックで展開)</summary><div>

```json
{
  "private": true,
  "scripts": {
    "dev": "webpack-dev-server --host 0.0.0.0",
    "build": "webpack --env.prod"
  },
  "dependencies": {},
  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^4.1.1",
    "@typescript-eslint/parser": "^4.1.1",
    "@vue/compiler-sfc": "^3.0.0",
    "@vue/eslint-config-typescript": "^5.1.0",
    "css-loader": "^4.2.2",
    "eslint": "^7.9.0",
    "eslint-config-prettier": "^6.11.0",
    "eslint-plugin-prettier": "^3.1.4",
    "eslint-plugin-vue": "^7.0.0-beta.3",
    "file-loader": "^6.0.0",
    "mini-css-extract-plugin": "^0.11.0",
    "postcss-loader": "^4.0.2",
    "prettier": "^2.1.2",
    "tailwindcss": "^1.8.10",
    "ts-loader": "^8.0.3",
    "typescript": "^4.0.2",
    "url-loader": "^4.0.0",
    "vue": "^3.0.0",
    "vue-loader": "^16.0.0-beta.7",
    "vue-router": "^4.0.0-beta.10",
    "webpack": "^4.42.1",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.10.3"
  }
}

```
</div>
</details>

## 詳細
以下は、上記の結果に至るまでの過程をまとめたものです。

## ESLint+Prettierのインストール
以下でESLintとPrettierをインストールします。

``` bash
yarn add -D eslint prettier eslint-config-prettier eslint-plugin-prettier
```

この時点での`.eslintrc.js`は以下のような内容にします。
この設定でESLint+Prettierが動作することの説明は、「[ESLint と Prettier の共存設定とその根拠について - Ojisan](https://blog.ojisan.io/eslint-prettier)」が参考になりました。

``` javascript
module.exports = {
  extends: ["eslint:recommended", "plugin:prettier/recommended"],
  env: {
    node: true,
  },
  rules: {},
};
```


## TypeScriptに対するESLintを有効にする
TypeScriptのLintと整形を有効にするために以下をインストールします。
この点は「[Getting Started - Linting your TypeScript Codebase](https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/README.md)」を参考にしています。

``` bash
yarn add -D @typescript-eslint/parser @typescript-eslint/eslint-plugin
```

この時点での`.eslintrc.js`は以下のような内容にします。
(後述しますが、ここで追加している内容は`@vue/eslint-config-typescript`で同様の設定が行われるため、Vue3+TypeScriptの組み合わせでは最終的に削除できます)

``` diff
 module.exports = {
   extends: [
     "eslint:recommended",
+    "plugin:@typescript-eslint/eslint-recommended",
     "plugin:prettier/recommended",
   ],
+   plugins: ["@typescript-eslint"],
+   parser: "@typescript-eslint/parser",
+   parserOptions: {
+     sourceType: "module",
+   },
   env: {
     node: true,
   },
   rules: {},
 };
```

ここまでで、`.ts`ファイルに対するLintと整形は出来るようになると思います。


## Vue3のSFCに対してLintが行えるようにする
上記の段階では`.vue`のSFCに対してはLINT等が行われないため、以下を追加でインストールします。

``` bash
yarn add -D eslint-plugin-vue@next @vue/eslint-config-typescript
```

ここで追加した2つのパッケージですが、node_modulesフォルダの下のパッケージのソースコードを確認する限り、以下のようなことを行っています。

パッケージ | 内容
--------- | -----------------------------------
eslint-plugin-vue | [公式サイト](https://eslint.vuejs.org/#:~:text=This%20plugin%20allows%20us%20to%20check%20the%20%3Ctemplate%3E%20and%20%3Cscript%3E%20of%20.vue%20files%20with%20ESLint)にも書かれていますが、このパッケージにより.vueのSFC内にある&lt;template&gt;,&lt;script&gt;タグがESLintによって解析可能になるようです。ソースコードは`node_modules/eslint-plugin-vue/lib`配下にあってここからも確認できますが、**parserをvue-eslint-parserに変更する**、vue向けのルールの追加、`plugin:vue/vue3-recommended`のようなconfigをエクスポートする記述が含まれています。
@vue/eslint-config-typescript | 実装を確認すると分かり易いですが、@typescript-eslint/parser, @typescript-eslint/eslint-pluginを使いつつ、拡張子.vueも対象にするための設定が含まれています。ソースコードはnode_modules/@vue/eslint-config-typescriptフォルダ配下です。このパッケージを導入すると、最終的な.eslintrc.jsに@typescript-eslintに関する宣言は記述不要になりそうです。また、内部で**parserOptions.parserに@typescript-eslint/parserを指定しています**。

この2つを追加した後の`.eslintrc.js`の内容は、
`eslint-plugin-vue`と`@vue/eslint-config-typescript`のそれぞれで`parser`や`parserOption`が指定されているため、以下のように書き換えます。
(最終的な内容は本記事の上段の内容を参照)

``` diff
 module.exports = {
   extends: [
     "eslint:recommended",
+    "plugin:vue/vue3-recommended",
+    "@vue/typescript",  //仕組みは分かっていませんが、これで"@vue/eslint-config-typescript"が読まれるようです。
-    "plugin:@typescript-eslint/eslint-recommended", //@vue/eslint-config-typescriptが同じものを追加するので削除
     "plugin:prettier/recommended",
   ],
-   plugins: ["@typescript-eslint"], // @vue/eslint-config-typescriptが同じものを追加するので削除
-   parser: "@typescript-eslint/parser", // eslint-plugin-vueがvue-eslint-parserに変更するので削除
-   parserOptions: { // @vue/eslint-config-typescriptがparserOptions.parserなど幾つかののオプションを変更するので削除
-     sourceType: "module", // eslint-plugin-vueなどが同じものを定義するので削除
-   },
   env: {
     node: true,
   },
   rules: {},
 };

```

この設定を行うと、`.vue`配下の`<template>`や`<script lang="ts">`にもLintと整形が行われるはずです。

## Prettierに関するルールの調整
PrettierにはVueやTypescriptに関するデフォルトの設定が定義されているため、その設定を追加します。
こちらは実装を確認すると、どちらもルール定義を上書きする内容になっていました。
各設定を細かく確認は出来ていないですが、自分の手元では`prettier/vue`は入れておかないと、`<template>`内で短すぎる範囲で改行されるなどの影響があったので追加しています。

``` diff
 module.exports = {
   extends: [
     "eslint:recommended",
     "plugin:vue/vue3-recommended",
     "@vue/typescript",
     "plugin:prettier/recommended",
+    "prettier/vue",
+    "prettier/@typescript-eslint",
   ],
   env: {
     node: true,
   },
   rules: {
   },
 };
```