運用中のVue.jsプロジェクトにESLintを入れるためにやったこと

こんばんは、アドベントカレンダーも5日目になりましたね！
クリスマスまではまだまだという感じがしています。

今日は、**「運用中のVue.jsプロジェクトにESLintを入れるためにやったこと」**について書きたいと思います。

前半：ESLintのインストール〜実行
後半：運用中のプロジェクトに導入するまでの流れ・注意したこと

インストールしてとりあえず実行したいという方は前半まで読めばOKです！

# ESLintとは
JavaScriptの記述スタイルチェックツールです。ESLintを使うと、設定した記述ルールにソースコードが沿っているかをチェックすることができます。これによりバグを減らせたり、複数人で開発をしているときも書き方を揃えることができたりするメリットがあります。ESLintで用意されているおすすめの設定や、Vue.jsやReact.jsなどの各フレームワーク用のプラグインもあるので特にルールなどを覚えなくても使いはじめることができます。

**「簡単に入れられてコードがきれいになる」**ものと思ってもらえればOKです。

# ESLintのインストール〜実行
## インストール
ESLintと一緒に、Vue.js用の公式のプラグイン（ https://github.com/vuejs/eslint-plugin-vue ）もインストールします。

```
$ npm install --save eslint eslint-plugin-vue@next eslint-config-vue
```

プラグインはnextをつけて最新版をインストールしています。

## .eslintrc.jsonを作成する
.eslintrc.jsonという設定ファイルを作成します。

`eslint --init`でも作成できるらしいですが、今回はプロジェクト直下に手動でファイルをつくりました。

```
$ touch .eslintrc.json
```

以下のように記述します。プラグインのおかげでほとんど記述しなくていいことがわかります。

```:.eslintrc.json
{
  "extends": ['vue', 'plugin:vue/recommended'],
  "env": {
    "browser": true,
  }
}
```

## 実行
これで準備は整ったので実行することができます。簡単ですね！
以下のコマンドで実行します。

```
$ ./node_modules/.bin/eslint public/js/**/*
```

右側のESLint対象とするjsの指定はそれぞれで変更してください。jsの指定にはファイルやフォルダだけでなく、上記のようにglob形式を指定することができます。

```
114:44   error  Extra semicolon                                              semi
115:46   error  Extra semicolon                                              semi
116:7    error  Expected space(s) after "if"                                 keyword-spacing
117:20   error  Extra semicolon                                              semi
119:21   error  Extra semicolon                                              semi
122:23   error  Missing space before function parentheses                    space-before-function-paren
122:25   error  Missing space before opening brace                           space-before-blocks

✖ 521 problems (521 errors, 0 warnings)
```

実行することができ、上記のようにエラーが表示されました。

# 運用中のプロジェクトに導入するまでの流れ・注意したこと
## 1. エラーが出たルールを一旦全て無視する
全てのエラーを一度に修正すると、差分が多くなりレビューも大変なので、エラーが出たルールを一旦全て無視するように設定してから、少しずつルールを適用していくことにしました。

.eslintrc.jsonのrulesをoffに指定するとルールを無視します。出たエラーを網羅すると以下のようになりました。

```json:.eslintrc.json
{
  "extends": ['vue', 'plugin:vue/recommended'],
  "env": {
    "browser": true,
  }
  "rules": {
    "camelcase": "off",
    "comma-dangle": "off",
    "comma-spacing": "off",
    "eqeqeq": "off",
    "handle-callback-err": "off",
    "indent": "off",
    "key-spacing": "off",
    "keyword-spacing": "off",
    "no-multi-spaces": "off",
    "no-undef": "off",
    "no-unused-vars": "off",
    "object-curly-spacing": "off",
    "quotes": "off",
    "semi": "off",
    "space-before-function-paren": "off",
    "space-before-blocks": "off",
    "space-in-parens": "off",
    "spaced-comment": "off",
    "space-infix-ops": "off",
    "no-dupe-keys": "off",
    "no-fallthrough": "off",
    "no-spaced-func": "off",
    "no-multiple-empty-lines": "off",
    "no-trailing-spaces": "off",
    "padded-blocks": "off"
  }
}
```

エラーが0になるまで書いていきましたが、ちょっと面倒でした。もっといい方法があったのではと思います。

## 2. ルールを適用する
エラーが出る全てのルールが無視された状態になっているので、一つづつ適用して修正していきます。rulesでoffに設定したルールを一つだけ適用します（つまり一行削除します）。

## 3. 修正する
修正は先程の実行コマンドに`--fix`オプションをつけるだけです。

```
$ ./node_modules/.bin/eslint public/js/**/* --fix
```

これだけで適用したルールに沿うようにESLintが自動で修正してくれます。これがかなり優秀で、ほぼ完璧に修正してくれます。

## 4. 全てのルールを適用するまで繰り返す
上記の、2.ルールを適用する〜3.修正を、全てのルールが適用されるまで繰り返しました。

# まとめ
## よかったこと
- ソースコードの記述ルールが一定の基準で統一された！
- 少しずつルールを適用したことにより、コンフリクトを軽減できたし、コンフリクトが起きても修正が容易だった。

## 大変だったこと
- リファクタリングはとにかくコンフリクトが起きやすいので、一度にたくさんのファイルを編集するような大きな実装がないタイミングを狙って導入するのが大変だった。
- それでも多少コンフリクトが起きてしまった。コンフリクトを抑えるために差分がすくない状態でささっとレビューしてもらってマージする、というのが大変だった。

# おまけ
## インデント修正
Vue.jsでは\<component>中にHTMLが書けますが、一般的にJavaScriptはインデントが2で、HTMLはインデントが4なことが多く、Vue.jsのデフォルトの設定では同じファイル内に違うインデントが混在するようになってしまいます。好みにもよりますが、インデントを揃える方法を書いておきます。

### インデントを2に揃える
\<component>内のインデントを2にします。

```json:.eslintrc.json
{
  "extends": ['vue', 'plugin:vue/recommended'],
  "env": {
    "browser": true,
  },
  "globals": {
    "Vue": true
  },
  "rules": {
    "vue/html-indent": ["error", 2]
  }
}
```

### インデントを4に揃える
\<script>内のインデントを4にします。

```json:.eslintrc.json
{
  "extends": ['vue', 'plugin:vue/recommended'],
  "env": {
    "browser": true,
  },
  "globals": {
    "Vue": true
  },
  "rules": {
    "indent": ["error", 4]
  }
}
```

## Laravel Elixir用のライブラリ
弊社ではLaravel使っているので、Elixir用のライブラリ (https://github.com/ponko2/laravel-elixir-eslint) も使ってみました。

```
$ npm install　--save laravel-elixir-eslint 
```

```gulpfile.js
const elixir = require('laravel-elixir');

require('laravel-elixir-vue-2');
require('laravel-elixir-eslint');　//←ココ追加

elixir(mix => {
    mix.sass('app.scss')
       .eslint('resources/assets/**/*.js') //←ココ追加
       .webpack('app.js');
});
```

これだけでgulp watch時にコンパイルと同じタイミングでESLintが走るようになって便利でした。LaravelとElixirを使っている方はぜひおすすめです。

# 参考
https://ginpen.com/2016/12/08/vue-lint/
http://tech.mercari.com/entry/2017/07/31/170125