JS周りのコードフォーマットをどうするか？

この記事は、[ニフティグループ Advent Calendar 2020](https://qiita.com/advent-calendar/2020/nifty)の23日目の記事です。

# はじめに
今年、弊社ではフロントエンドの刷新業務として、Reactの開発を行う機会があり、そこで私も同じプロジェクトの開発メンバー(2~3人程度)と同時にコード開発を行っていました。

自分自身、本格的なチームでの開発というものが初めてだったため、**「Gitのブランチの扱いが良く分からない...」**だったり、**「プルリク時のコンフリクトが頻繁に起こる...」**など、共同開発で迷う場面が多かった気がします。。

そんな中、在宅期間中で**「これができたら便利そう...とか、もっと効率良い開発方法はがあるのでは？」**など、あれこれ考えることが多く、何かと便利機能を調べてみては試してみる、といったこともそれなりに出来たので学びとしては多かったです。

また、開発の面倒な部分を効率化出来れば、きっとエンジニアのモチベーションも上がるはず(!?)です。

そこで、チーム開発で一部導入してみた機能や、最初からもっとこうしておけばよかったな、といったことを書いていこうと思います。

# Git開発
Git開発の流れとしては、以下のような手法で開発していました。

- 機能ごとにfeatureブランチを切る
- 各ブランチ毎にプルリクを出す

# コンフリクトにどう対処するか問題
基本的に各自で開発した機能は被ることがないので、その場合はプルリクでコンフリクトが起こることはありません。
ただし、ちょっとした機能修正などコードを修正したタイミングでは、コンフリクトが起きることがあります。

## コンフリクト修正機能
エディター自体にもコンフリクトを修正するような機能は用意されており、後からコンフリクトを修正することもできるのですが、
そもそもが「インデントが違う」などフォーマットが統一されていないがためにコンフリクトが起こっている場合、それを一々修正するのは面倒だと思います。

こういった問題を解消するために、JS用のコードフォーマッターを導入しました。

# コードフォーマッターを入れたい
React(JS)での開発では、フォーマッターを入れると便利という事を知り、以下の２つを導入しました。

## 導入したもの
- Prettier（フォーマッター）
    - ソースコードをルールに沿った形に良い感じに整形してくれるツール
- ESLint（リンター）
    - ソースコードを読み込んで内容を分析し、問題点を指摘してくれる

## Prettier
.prettierrcというファイルを用意し以下のようにフォーマットのルールを設定します。セミコロン有無や、インデント幅などを設定可能です。

```js:.prettierrc
{
  "printWidth": 120,
  "tabWidth": 2,
  "useTabs": false,
  "semi": true,
  "singleQuote": false,
  "trailingComma": "es5",
  "bracketSpacing": true,
  "jsxBracketSameLine": false
}
```

例えば、`app.js`に対してprettierを実行したい場合、`prettier app.js --write`とコマンドを実行すれば、整形されたファイルが出力されます。

ここまででは、一先ずはコードフォーマットは出来るようになりましたが、一々コマンドを打たないとフォーマットができないのはかなり面倒です。

そこで、"ファイル保存をする毎にprettierを実行できるよう"、VSCodeのsetting.jsonに以下の一行を追加します

```
 "editor.formatOnSave": true
```

これで、かなりの手間が解消されました。


## ESLint
prettierはコードフォーマッタのため、ESLintのような構文のチェックはできません。そのため、ESLintも併用で導入します。

同様に、`.eslintrc`にも設定内容を記述していきます。
（以下が設定例となります。）

```js:.eslintrc
{
  "env": {
    "es6": true,
    "node": true,
    "browser": true,
    "jquery": true,
    "jest": true
  },
  "parser": "babel-eslint",
  "plugins": ["react", "prettier"],
  "parserOptions": {
    "version": 2018,
    "sourceType": "module",
    "ecmaFeatures": {
      "jsx": true
    }
  },
  "extends": ["eslint:recommended", "plugin:react/recommended", "plugin:prettier/recommended", "prettier/react"],
  "rules": {
    "prettier/prettier": "error"
  },
  "settings": {
    "react": {
      "version": "detect"
    }
  }
}
```

ESLint と Prettier を共存させる場合、
`"extends": ["plugin:prettier/recommended"]`を書くだけで、併用ができます。


## "git commit"実行時にlinterテストを走らせる

さらに、linterテストが自動で走るようにしたいので、ESLintのテストが失敗した場合は"git commit"が通らないようにします。

使うものとしては以下です。

- lint-staged
- husky

```
yarn add -D eslint lint-staged husky
```

追加方法としては、以下をpackage.jsonに追記するだけでできます。

```js:package.json
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    ".{js,jsx}": [
      "eslint --fix",
      "git add"
    ]
  },
```

実際に動かすと...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508077/ea5f0ba7-2521-7124-faef-c557e9e6624f.png)

このように、`git commit`時に`eslint --fix`が実行され、該当するエラーを解消しないとコミットができなくなりました。

## 導入した結果
ここまでで以下のような事が出来るようになりました

- "git commit"実行時に自動でlinterテストが走る
- ファイル保存時にPrettierが実行される

コードフォーマットを自動化することで、無駄なことに人力で注視しなくなるので楽になりました。

なお、VSCode等でJSやHTMLなど専用のフォーマッターツールを別途入れている場合、Prettier、ESLintの設定を上手く変えてあげないと動作しないことがあるので注意が必要です。
今回は実装を簡単にするため最低限の設定にしてありますが、実際のチーム開発を行う場合には、エディターに入れる拡張機能などの環境を、事前に揃えておくなどの工夫が必要かと思います。

# 感想
初めてコードフォーマッターを導入してみたのですが、調べてみるとこれ以外にもかなり多くの事ができるようで、良い勉強になりました。

個人的には、プルリクなりコードを書くなりでも、きれいな状態（整理された状態）でいることはコードの品質面でもそうですが、自分が見ていても分かりやすいし実際にチームでも使ってもらえたりと、それだけでモチベが上がる気がします。

VSCodeのエディターの機能や、プルリクの自動化機能（GitHub Actions）など、既存ものを自動化して改善できる部分は意外とあるものの、一度面倒な部分を実感してからじゃないと中々思いつかない部分もあるのかなと感じました。

１から調べて実装して導入までやってみると、かなり知識も身に付くと感じたので、プライベートでもこういった経験を増やしていきたいです。


# 終わりに
次回は@RPcatさんの記事になります！お楽しみに！

# 参考
[Prettier 入門 ～ESLintとの違いを理解して併用する～](https://qiita.com/soarflat/items/06377f3b96964964a65d)
[【JavaScript】コミットする前にlint-stagedでeslintのチェックをする](https://kic-yuuki.hatenablog.com/entry/2019/05/27/090515)
[VS Code上でファイル保存時にPrettierを走らせる](https://qiita.com/Naturalclar/items/690be378984b3a24a138)