Vue.js + TypeScript + Webpack環境にESLintとPrettierを入れる

# はじめに
どうも@chan_kakuです
今回はタイトルにもあるようにVue.js+TypeScript+Webpack環境(vue-cliを使わない)でESLint+Prettierを入れる時にハマった部分が多かったのでそのやり方などを説明していこうと思います。

## ESLintとは
ESLint は JavaScript のための静的検証ツールです。コードを実行する前に明らかなバグを見つけたり、括弧やスペースの使い方などのスタイルを統一したりするのに役立ちます

### 特徴*
- すべての検証ルールを自由に on/off できる
- 自分のプロジェクトに合わせたカスタムルールを簡単に作れる
- 豊富なビルトイン ルール (5.0.0 時点で 260 個) に加えて、たくさんのプラグインが公開されている
- ECMAScript 2015 (ES6), 2016, 2017, 2018, 2019 を標準サポートしている
- JSX 記法 をサポートしている
- Babel と連携することで、仕様策定中の新しい構文や Flow 型注釈にも対応できる

*[ESLint 最初の一歩](https://qiita.com/mysticatea/items/f523dab04a25f617c87d)から引用

### なぜLintを使うのか

チーム開発ではそれぞれ独自の書き方でかけてしまう。特にJavaScriptだと、ESの種類によってたくさんの書き方があり、babelなどを使うとどの書き方でもかけてしまいます。
本来はチーム内で整合し、規約を作るのが良いがなかなかそれだけではうまくいかないのが現状である。
そこでLintを使うことで強制的にコードを合わせることでプロダクションコードを綺麗に保つことができます。

## Prettierとは
コードフォーマッターで以下のものに対応している

- JavaScript
- JSX
- Flow
- TypeScript
- Vue
- Angular
- CSS等
- JSON
- GraphQL Schmas
- Markdown

など

## なぜESLintとPrettier

ESLintは名前の通りLintとしての役割が大きく、最近TSLintがDeplicateになりその機能がESLintにマージされた。
また`eslint --fix`を使うことでコードを整形することができる。であればPrettierはいらないのではないかもしれないが、
Prettierはデフォルトでいい感じに整形してくれるところがとても良い(ESLintで同じような整形をしようとすると結構大変らしい)
そこで、Lintとしての機能はESLintにお任せして、コードの整形部分をPrettierに任せればいい感じにできる。(最近のフロント界隈はこの組み合わせでやることが多い)
また、ESLintの整形では１行が長い時に改行するかどうかのようなパターンのものは通常の`eslint --fix`で整形できなかったりする

## 問題点
ESLintやPrettierを別々で使うとそこまで問題は出ないのですが、今回の使い方のようにESLintをLintとして、Prettierでコードフォーマッターとして使うときにいろいろ問題があります。
ESLintはそもそもの機能として上記にもあるように`--fix`オプションを使うことによってコードフォマットをしてくれます。これがPrettierの機能とコンフリクトを起こしエラーが出ることが多々あります。
これを避けるためにESLint側のルールなどをoffにしたりするプラグインなどをいろいろ入れないといけないのですが、Prettier,Vue.js,TypeScriptの関連したプラグインが多すぎて何を使えば良いのかわからないと行った問題に直面しました。

## 導入方法
ESLint,Prettier関連のライブラリなどはたくさんありますが、ひとまずはコンフリクトを起こさず、Lintとコードフォマットができる最小限構成を目指しました。
こちらはVue.js + TypeScript環境にESLint + Prettierを入れたい場合です。TSではなく、JSなどでは結構入れるモジュールが変わってくるので注意してください
yarnを使っている方は`npm i`を`yarn add`に置き換えてください
`npm i -D eslint prettier eslint-config-prettier eslint-plugin-prettier eslint-plugin-vue　@typescript-eslint/eslint-plugin @typescript-eslint/parser`

ここでparserやplugin、ruleなどを追加していきます

```json:.eslintrc
{
    "env": {
        "es6": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:prettier/recommended",
        "plugin:vue/essential",
        "plugin:@typescript-eslint/eslint-recommended",
        "plugin:@typescript-eslint/recommended",
        "prettier/@typescript-eslint"
    ],
    "plugins": [
        "vue",
        "@typescript-eslint"
    ],
    "parser": "vue-eslint-parser",
    "parserOptions": {
        "parser": "@typescript-eslint/parser"
    },
    "rules": {
        // ここはよしなにルールを設定してください
        "prettier/prettier": [
            "error",
            {
                "singleQuote": true,
                "trailingComma": "es5"
            }
        ]
    }
}
```

ここに追加したものはlintから除外されます

```text:.eslintignore
    node_modules/
```

```json:package.json
    "scripts": {
        ・・・
        "lint": "eslint --fix 'src/**'" //src以下のファイルを読み込んでlint+コードフォーマットしてくれます
    }
```

`npm run lint`することでlint+コードフォーマットしてくれます

### 追加したライブラリの説明
ESLintとPrettier以外を説明していきます

#### eslint-config-prettier
Prettierとのコンフリクトを起こすような不要なESLintのルールを解除するもの

#### eslint-plugin-prettier

ESLintのルールでPrettierを実行してくれる

#### eslint-plugin-vue

Vue.js用のESLintのプラグインである。Vue.jsのコミュニティによってメンテナンスされている。
`.vue`　ファイルの `<template>`と`<script>`をチェックしてくれる。

使い方は[こちら](https://eslint.vuejs.org/)

#### @typescript-eslint/eslint-plugin

ESLintでTypeScriptのサポートをしてくれるプラグインである。

#### @typescript-eslint/parser

上記の@typescript-eslint/eslint-pluginと一緒につかう。ESLint用のパーサー

# 最後に

Lintとコードフォーマットしたいだけなのに結構複雑で、多くのライブラリを入れないといけなく、またその環境によって入れなければならないものが結構変わってくるのでESLintとPrettierの組み合わせは結構難しいように感じました。
この記事を書いた動機としてはTSLintがDeplicatedになってからVue.js + TypeScriptでかつ、vue-cliを使っていないという環境でのESLint+Prettierをいい感じに使う情報がまとまっていなかったため(自分調べ)書くに至りました。個人的な観測ではvue-cliを使ったサンプルが多く普通にwebpackを使うようなproduction環境を想定したものがなかったように感じたので、この記事によって同じ境遇の方の助けになればと思っております。

## 参考

- [ESLint 最初の一歩](https://qiita.com/mysticatea/items/f523dab04a25f617c87d)
- [Prettier 入門 ～ESLintとの違いを理解して併用する～](https://qiita.com/soarflat/items/06377f3b96964964a65d)
- [Nuxt.jsをはじめよう - ESLint+Prettierでコードをフォーマットする](https://www.soudegesu.com/post/javascript/format-nuxt-typescript-on-save/)