git commit時にprettierによるコード整形・ESLintルールチェック・flow型チェックを行って精神の安定を得る

# 前説

ES2015でのフロントエンド開発時に以下のような経験をしたことはないでしょうか？

- その場でルールを決めているため、一人開発時でも書き方に開発が進むに連れてズレがでる
- 雰囲気でJavascriptを書いているため書き方が揃っていない
- 型安全がない無法地帯
- 各種ツールを導入したのはいいが、チーム内で使われずにクズコミットが行われる

上記の山積した問題についてツール導入＋自動化をおこなったので、その手順をまとめました。


# 使用するパッケージ(2017年9月20日時点)
- [ESLint](https://github.com/eslint/eslint)
- [prettier](https://github.com/prettier/prettier)
- [flow](https://github.com/facebook/flow)
- [babel](https://github.com/babel/babel)
- [babel-preset-env](https://github.com/babel/babel-preset-env)
- [husky](https://github.com/typicode/husky)
- [lint-staged](https://github.com/okonet/lint-staged)
- [pre-commit](https://github.com/observing/pre-commit)

※、各パッケージの仕様についてはリンク先参照

# 今回のプロジェクトについて
今回はReactは使用せず、シンプルなExpressサーバをターゲットとしています。
React導入時にはBabel及びESLintの設定・導入パッケージについて適宜変更して下さい。

# 実行環境
OS: Windows10
Node: 8.5.0
開発ツール: VS Code 1.16.1 (拡張機能： ESLint、prettier-vscode)

# 導入方法
以下の手順にてパッケージ導入・設定ファイルを作成

### 1. Babel

プロジェクト作成後、以下のコマンドにてパッケージを追加

```
yarn add -D babel-cli babel-core babel-eslint babel-plugin-transform-flow-strip-types babel-preset-env babel-preset-es2015
```

パッケージを追加後、プロジェクト直下に「.babelrc」ファイルを作成。以下の設定を追加。

```.babelrc
{
  "presets": [
    [
    "env",
      {
        "targets": {
          "node": "current",
          "modules": false,
          "loose": true
        }
      }
    ],
    "es2015"
  ],
  "plugins": ["transform-flow-strip-types"]
}
```
※、トランスパイル対象がnodeのみになっているので、ブラウザをターゲットとする場合は適宜追加してください

### 2. ESLint

以下のコマンドにてパッケージを追加

```
yarn add -D eslint eslint-config-airbnb-base eslint-config-prettier eslint-plugin-flowtype eslint-plugin-import 
```

npmの場合、「eslint --init」が使えますが、yarnだと追加パッケージにインストール時に不具合がでるため、手動で設定ファイルを作成します。
プロジェクト直下に「.eslintrc.json」作成後、以下の設定を追加

```.eslintrc.json
{
  "parser": "babel-eslint",
  "extends": [
    "airbnb",
    "prettier",
    "prettier/react"
  ],
  "plugins": [
    "prettier"
  ]
}
```


### 3. flow

以下のコマンドにてパッケージを追加

```
yarn add -D flow-bin flow-typed
```

パッケージ追加後、以下のコマンドにてflow-typedの定義ファイル取得

```
yarn flow init
yarn flow-typed install
```

init時に作成された「.flowconfig」に以下の設定を追加

```.flowconfig
[ignore]
.*/node_modules/.*

[include]

[libs]
./flow-typed

[options]

```


### 4. git関連

以下のコマンドにてパッケージを追加

```
yarn add -D husky lint-staged pre-commit
```

パッケージ追加後、「package.json」に以下の項目を追加

```package.json
  "lint-staged": {
    "subTaskConcurrency": 1,
    "linters": {
      "*.js": [
        "prettier-eslint --write",
        "eslint",
        "git add"
      ]
    }
  },
```

プロジェクト直下に「.gitignore」作成後、以下の設定を追加

```.gitignore
# See http://help.github.com/ignore-files/ for more about ignoring files.

# dependencies
node_modules
flow-typed

# testing

# production
dist

# misc
.DS_Store

```

### 5. express

以下のコマンドにてパッケージを追加

```
yarn add -D nodemon
yarn add express compression morgan serve-static
```

プロジェクト直下に「lib」、「public」フォルダ作成後、以下のファイルを追加

```lib/index.js
// @flow
import express from 'express';
import expressWs from 'express-ws';
import morgan from 'morgan';
import compression from 'compression';
import serveStatic from 'serve-static';

const app = express();

app.set('port', process.env.PORT || 3000);

app.use(morgan('dev'));
app.use(compression());
app.use(serveStatic(`${__dirname}/public`));

app.get('/', (req, res, next) => {
  console.log('get route', req.testing);
  next();
});

app.listen(app.get('port'), () => {
  console.log('Server listening on port %s', app.get('port'));
});
```

```public/.gitkeep
add git
```

### 6. npm script追記

1～5の設定完了後、「package.json」に以下の項目を追加

```package.json
  "scripts": {
    "build": "babel lib -d dist",
    "dev:srv": "nodemon lib/index.js --exec babel-node --presets=env",
    "prd:srv": "node dist/index.js",
    "precommit": "lint-staged && flow check"
  },
```

※、各コマンド補足

| コマンド          | 実行内容           |
|:-----------------|:------------------|
| build            | libフォルダのjavascriptをdistにトランスパイル |
| dev:srv          |  開発用サーバ起動。nodemonで変更時にトランスパイルして再起動 |
| prd:srv          | 本番用サーバ起動。トランスパイルしたファイルで実行 |
| precommit        | パッケージ「pre-commit」用コマンド。コミット時に記載されたコマンドが実行される。今回ではpackage.jsonに記載された「lint-staged」と「flow check」が実行され、どちらかでエラーが有った場合、コミットが行われない |

# まとめ
とりあえず、書き出したが指摘があれば追記を行う予定

# 参照サイト
- [ESLint導入環境にprettierを追加して運用する](https://www.kken.io/posts/prettier-eslint/)
- [prettierの使い方](http://qiita.com/kiida/items/405bb07c4b52bfee0219)
- [flowの始め方](http://qiita.com/kiida/items/ea758e4d80053663e12a)