【古い情報】eslint  & prettier を整備したので設定についてまとめた

# ※2021/5/14 更新※

この記事は古い内容で書かれています。
この記事で使用している `eslint-plugin-prettier` は 2021/5/14現在 Prettierから推奨されていません。
https://prettier.io/docs/en/integrating-with-linters.html#notes

最新の情報は https://prettier.io/ や https://eslint.org/ から収集してください。

<hr>
<hr>

# はじめに
<img height="100" src="https://qiita-image-store.s3.amazonaws.com/0/319527/4c81199b-f2a8-4298-1610-52302c573d3a.png"> :heavy_plus_sign: <img height="90" src="https://qiita-image-store.s3.amazonaws.com/0/319527/201ca6c0-ac79-30c3-6e3b-11a0d5ba1cd3.png">


とあるプロジェクトで、初めて eslint と prettier による静的検証とコードを整備したのですが、全容を理解するまで難しかったので、その内容をまとめます。
主にVue.js向けの内容ですが、知識としては汎用的な内容だと思います。

## 対象者

eslintとprettierそれぞれが何者で、何をしているかわかっているんだけど、自分で整備したことはない人。
(個々の説明はQiitaの他記事に詳しいです)


# 難しかった理由

整備が難しかったのは以下のような点です。

- 設定に関して登場人物が多く、相互にからみあっており、自分がやりたいことを実現する為に何が必要かすぐに分からない。
- eslintとprettierの修正内容が競合することがあり、設定を誤ると常にどっちかのエラーが出ている状態になったり、フォーマットをかける度にコードが書き変わったりする。

何かを学ぶときはだいたいトライアルアンドエラーする派なのですが、今回はにっちもさっちもいかなかったので、しっかり構造を理解するために調べてみました。

# eslint & prettier に関わる登場人物

eslintやpretteirの関係者を以下に説明します。

## エディタ

VSCode, Atom, Vim, IntelliJ, などなど、世の中には様々なエディタがありますが、大抵は標準、もしくはプラグインでeslint/prettierに対応しています。
しかし、場合によっては一部の機能が非対応であったり、逆に便利なプラグインがあるけど他のエディタでは使えないということがあります。

例えば、VSCodeには[Vetur](https://github.com/vuejs/vetur)という Vue用のプラグインがあります。
Vueの単一コンポーネント(.vue)のシンタックスハイライトや補完、フォーマットなどの機能があり、VSCodeでVueを開発する場合は必須なのですが、他のエディタでは使えません。
そのため、Veturでフォーマットされたコードを他の環境でフォーマットすると変化してしまう可能性があります。
チームがVSCodeで統一されていれば問題ないかもしれませんが、将来的なことも考えると、いつ誰が編集しても良いようにしておきたいものです。

## eslint-prettier連携プラグイン

eslintとprettierを併用する理由は、お互いの良いとこ取りをしたいからです。
しかし、eslint による コード修正と prettier によるコード整形は、うまく連携させてあげないとお互いの変更を誤りと見なしてしまいます。

その仲を取り持つプラグインが [**prettier-eslint**](https://github.com/prettier/prettier-eslint) と [**eslint-plugin-prettier**](https://github.com/prettier/eslint-plugin-prettier)です。
この2つは名前は似ていますが全く違うものです。

**prettier-eslint**は、prettierよるコード整形をかけたあとにeslintによるfixをかけます。
このため、prettierの出力結果の一部はeslintによって再修正されます。

**eslint-plugin-prettier**は、prettierによるコード修正を、あたかもeslintのルールのように扱えるようになります。
各エディタのeslint機能では、ルールに従っていないコードに赤線が引かれるなどの機能ががありますが、このprettierの整形ルールに従っていない部分に関してもエラーが表示されます。

性質や適用したいフレームワークによって、どちらを使うかを決める必要があります。

## eslintパーサー

コードを解析するためのパーサーです。

ES6の.jsファイルだけならば [**babel-eslint**](https://github.com/babel/babel-eslint) でいいのですが、Vueファイルのパースをするためには、[Vue用のパーサー](https://github.com/mysticatea/vue-eslint-parser)が必要なようです。

## eslint設定プラグイン

eslintにフレームワーク毎に必要な機能を追加したり、無効にしたりします。
大抵は **eslint-plugin-hoge** か **eslint-config-hoge** という名前になっているようです。
hogeにはフレームワークなどのライブラリ名やルール名が入ります。

### eslint-plugin-hoge

eslintにデフォルトでは存在しないルールを追加したり、既存のルールを有効・無効にします。

#### 例
[eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue)
[eslint-plugin-react](https://github.com/yannickcr/eslint-plugin-react)
etc.

### eslint-config-hoge

eslintのルールセットです。以下のようなPrettierやVue用のルールセットでは、それぞれの環境で衝突してしまう不要なルールがオフにされているようです。

[eslint-config-prettier](https://github.com/prettier/eslint-config-prettier)
[eslint-config-vue](https://github.com/vuejs/eslint-config-vue)
etc.

# 具体的な設定

整備を行うためには、上記のような登場人物の役割をしっかり理解する必要があります。
以下に、プロジェクトで実際に行った設定の内容を記します。

## 必要な状態

- コード修正・整形について、特定のエディタのみの機能やプラグインを使用しない。
- eslintやprettierが使えるエディタで、全く同じコード修正・整形がかけられる。
- 単一コンポーネントファイル(.vue)とES6が修正・整形できる。
- 単一コンポーネントファイルについて、`<script>`などの固有タグについてもフォーマットの対象にする。
- コード整形に関する設定はできるかぎり Prettier に寄せる。

## 方針

- 「Prettierによる整形ができていない」ことを視覚化できると考え、**eslint-plugin-prettier** を選択。

## 実際の設定

### 環境

- node.js v11.2.0
- npm     v6.4.1

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

- babel-eslint : 8.2.6
- eslint : 4.19.1
- eslint-config-airbnb-base : 13.1.0
- eslint-config-prettier : 3.3.0
- eslint-plugin-prettier : 3.0.0
- eslint-plugin-vue : 5.0.0
- prettier : 1.15.3 
- vue-eslint-parser : 3.3.0

### eslintrc.js

```js
module.exports = {
  root: true,
  parser: 'vue-eslint-parser', // parserをvue用に指定
  parserOptions: {
    parser: 'babel-eslint',    // es6用のparserはoptionsの仲へ
    sourceType: 'module',
  },
  env: {
    browser: true,
    node: true,
  },
  extends: [
    'eslint:recommended',           // eslintの推奨ルール
    'airbnb-base',                  // airbnbルール(厳しめ)
    'plugin:prettier/recommended',  // 1.eslint-plugin-prettierをenable
                                    // 2.eslint-config-prettierをenable
                                    // 3.prettierの整形に問題がある場合にerrorを出す設定
    'plugin:vue/recommended',       // eslint-plugin-vueを推奨設定でenable
    'prettier/vue',                 // eslint-config-prettierのvue用ルールを適用(2019/1/16修正)
  ],

  // add your custom type here
  rules: {
    'no-plusplus': 'off',           // for文だけでなく、++は使いたかった
    'func-names': 'off',            // 無名関数を許可 
                                    // Vueだとスコープの問題で偶につかう
    'vue/component-name-in-template-casing': 'off', 
    // ↑ html部分をPascalにするかkebabにするかの選択です。
  },
};

```

### prettierrc.js

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

## 補足

[eslintrc.js](#eslintrcjs)のextends配列は、**指定する順序によってルールが変わる**ことに注意して下さい。
後で設定したほうが前で設定されたルールを上書きします。

ルールの詳細の変化について確認したい場合は [eslint --print-config](https://eslint.org/docs/user-guide/command-line-interface#--print-config)でルール一覧が出力できるので、確認してみて下さい。

# 終わりに

整備する立場になったからには、しっかり理解しておく必要があるな!
と、思っていろいろ調べたのですが、eslintやprettierを理解していることを前提として書かれているものが多かったり、断片的内容だったりと、ちゃんと理解するまでに時間がかかってしまいました。
まだまだ勘違いしているところなどあるかもしれませんが、一旦ここまででアウトプットしてみます。

# 補記

最近 Prettierがバージョンアップによって、単一コンポーネントファイルのhtml部分も整形してくれるようになりました。
しかし、eslintの設定でhtmlのインデントを調整していた為、上記の機能と衝突し、VSCode上で修正合戦が始まってしまいました。(fixを走らせる度にコードが変更されてしまう)

両立させる方法が分からず、結局Prettierのフォーマットを採用し、eslintの追加設定を削除しました。(上記のeslintrc.jsは削除済みのもの)

どうすれば良かったのか、今後もうちょっと調べます。

# 蛇足
まとめ書いてて、「あれ、eslint-plugin-prettierより、prettier-eslintのほうが大枠の修正→細かい修正ができそうで良いんじゃねぇかこれ...?」などと思ったので、後で試してみます。