コミット時にtslintとstylelintを回してコードの品質を保証する

1人でコードを書いていると何も気にせずに書き散らしてしまい、統一感がなくなってしまうことが多いので、lintを導入してルールを作るようにしています。

ただ、いちいちlintを回すのも大変なので、コミット時に回すようにして、誤ったコードのプッシュを防げれば良さそう。

実装するために色々と設定したので、備忘録がわりに書いていきます。

# サンプルコード

一応、サンプルをGithubに作りました。
https://github.com/hiraike32/commit-and-lint

reactとwebpackも入れていますが、基本的にはシンプルなものです。
手元にクローンして、 `index.tsx` や `style.scss` を触って、誤ったコードがコミット時に修正・失敗することを試してみてください。

以下では、既存のプロジェクトに対して導入していくための手順をまとめていきます。

# 導入の手順

## 1. TSLintを設定する

まず[TSLint](https://palantir.github.io/tslint/)の設定をして、コーディングのルールを決めます。メモとして、TSLintを導入するところから。

```sh
$ yarn add -D tslint
$ yarn add -D tslint-react // reactのルールを取り入れるためのプラグイン
$ yarn tslint --init
```

これでプロジェクトに `tslint.json` が作成されるので、Typescriptに関するコーディングルールが書けるように。

いつもこんな感じで設定しています。

```tslint.json
{
  "defaultSeverity": "error", // "error" | "warning" | "off" からtslintの重要度を決める
  "extends": ["tslint:recommended", "tslint-react"], // 設定をライブラリから読み込んで拡張できる
  "rules": {
    "interface-name": false,  // interfaceの名前を全て'i'から始めるルール。自由に命名したいのでfalse
    "object-literal-sort-keys": false, // オブジェクトのkeyをアルファベット順にするルール。逆に混乱するのでfalse
    "no-shadowed-variable": false, // 異なるスコープにおいて同じ変数名を定義するのを禁止するルール。同じ変数名を使いまわした方がわかりやすい時があるのでfalse
    "member-access": false // 全ての関数にpublicまたはprivateをつけるルール。publicがつくと文字が増えるのでfalse
  }
}
```

※ルールについては覚え書きなので、詳しくは 「TSLint ルール名」 などで調べてみてください。

あとは、 `$ tslint './src/**/*.{ts,tsx}'` を実行すれば、src以下の ts / tsx ファイルを検査して、ルールに沿わないコードを特定してくれます。

ただ、ファイルを1つずつ直していくのも大変なので、 `$ tslint --fix './src/**/*.{ts,tsx}` を実行すれば、TSLintが可能な限り自動でファイルを修正してくれるので便利です。

importの順番を整理してくれたり、1箇所しか使われていないletをconstに変換してくれたり、関数などの書き方を統一してくれるのでとても助かる。

特に複数人でコードを書くときは、それぞれの書き方が出てしまうので、lintを入れて統一できると良さそう。



## 2. stylelintを設定する

cssやsassなどのコーディングルールを決めることができるのが[stylelint](https://stylelint.io/)。改行や{}の書き方などの悩みがなくなります。stylelintの導入から設定まで。

```sh
$ yarn add -D stylelint
$ yarn add -D stylelint-config-standard // 基本的な設定を入れるためのプラグイン
```

正常にインストールできたら、 `.stylelintrc.json` を作成して、設定を書いていきます。

```.stylelintrc.json
{
  "extends": ["stylelint-config-recommended", "stylelint-config-standard"], // 設定を拡張する
  "rules": {
    "indentation": 2, // インデントのサイズをスペース2つに設定
    "declaration-colon-newline-after": null, // コロンのあとに改行が入ってしまうと見づらいのでnull
    "value-list-comma-newline-after": "never-multi-line", // カンマのあとに改行が入ってしまうと見づらいので入れないように
    "at-rule-no-unknown": [
      true,
      {
        "ignoreAtRules": ["function", "if", "each", "include", "mixin", "for"] // scssで@ifなどを使用した時にエラーが出ないように
      }
    ]
  }
}

```

※ルールについては覚え書きなので、詳しくは「stylelint ルール名」などで調べてみてください。

あとは同じく、 `$ stylelint './src/**/*.{css,scss}'` を実行すれば、src以下の css / scss ファイルを検査して、ルールに沿わないコードを特定してくれます。 `$ stylelint --fix './src/**/*.{css,scss}` を実行すれば、同じく自動でファイルを修正してくれます。

個人的には、cssの書き方が整っているととても心地よい。



## 3. lint-stagedの設定

それぞれのlintの設定はできたので、それらをcommit時に回して、エラーがあった場合にはcommitを止めるようにします。

[lint-staged](https://github.com/okonet/lint-staged)というライブラリを使うと簡単に設定できます。まずは、lint-stagedと、それを使うために必要なhuskyというライブラリを入れます。

```sh
$ yarn add -D lint-staged husky
```

あとは、 `package.json` に設定を記述して完了。

```json
"husky": {
    "hooks": {
      "pre-commit": "lint-staged" // コミット前に以下のコマンドが実行される
    }
  }, 
"lint-staged": {
    "*.{ts,tsx}": [
      "tslint --fix",
      "git add"
    ],
    "*.{css,scss}": [
      "stylelint --fix",
      "git add"
    ]
  }
```

これで、コミット前に `TSLint` と `stylelint` が実行されて、自動で修正できることは修正してくれつつ、エラーがあった場合はコミットせずにエラー部分を指摘してくれます。

他にもコミット前に様々な処理を設定することができるので、より便利にできるかもしれません。