[GitHub 奮闘記] gulp で eslint 設定とコード チェック環境の共有

みなさん、gulp で eslint によるコード チェックの自動化やってますか？

プロジェクトで開発者によってコードの書き方にばらつきが出るからスタイルを共通化しようという話がありますよね。
私の場合は、gulp とか grunt とかでの環境づくりに積極的になれてなかったのですが、自分が抱えている GitHub の[オープンソース プロジェクト](https://github.com/muxlab/map-effects-100)にて、__「スタイルを共通化するなら grunt か gulp を使おうよ！」__と海外からテンション高めに有志のコメントをもらったので、焦って早速やってみた雑記です。
まさに GitHub の醍醐味ですね。

※ちょうど最近 JSX のコンパイルのために gulp を使い出したので、今回も gulp で環境を作ってみました。

以下が本記事のゴールです。

* 貢献してくれる開発者がスタイルガイドを見なくてもきれいな JavaScript が書ける環境を共有する（`package.json` の `DevDependencies` に書き込む）
* GitHub のプロジェクトで JavaScript の eslint 設定（`.eslintrc`）を共有する
* gulp を使ってコード チェックのタスクを自動化してコマンドを叩くだけで OK にする（`gulpfile.js`）

## 開発環境をインストール

まずは `npm install --save-dev [パッケージ名]` でコード チェック自動化に必要なパッケージのインストールと `package.json` への開発環境依存モジュールの書き込みを行います。

インストールしたパッケージは以下です。

* [eslint](https://www.npmjs.com/package/eslint)
* [eslint-config-airbnb](https://www.npmjs.com/package/eslint-config-airbnb)（Airbnb の eslint 設定）
* [gulp](https://www.npmjs.com/package/gulp)
* [gulp-eslint](https://www.npmjs.com/package/gulp-eslint)（eslint 実行のための gulp プラグイン）
* [gulp-plumber](https://www.npmjs.com/package/gulp-plumber)（エラー抑制のための gulp プラグイン）
* [node-notifier](https://www.npmjs.com/package/node-notifier)（通知送信のための gulp プラグイン）

上で述べたコマンドのように `--save-dev` をつけてあげることで `package.json` の `devDependencies` に書き込まれます。
※`devDependencies` の依存モジュールはプロジェクト開発者のみが必要な環境なのでデフォルトでは `npm install` で一緒にインストールされません。

## gulpfile.js で eslint のコード チェック自動化
eslint によるコード チェックを自動化するために gulpfile.js にタスクの内容を書き込みます。コードは [koh110](http://qiita.com/koh110)  さんの[「僕なりのフロントエンド開発環境」](http://qiita.com/koh110/items/9c750fb67e40481e52cd)の記事を参考にさせていただきました。というかコードはほぼそのまま使わせていただいております。

```js:gulpfile.js
"use strict";

var gulp = require('gulp');
var eslint = require('gulp-eslint');
var plumber = require('gulp-plumber');
var notifier = require('node-notifier');

// eslint タスク（一時チェック）
gulp.task('lint', function() {
  return gulp.src(['Leaflet/dist/*.js']) // lint のチェック先を指定
    .pipe(plumber({
      // エラーをハンドル
      errorHandler: function(error) {
        var taskName = 'eslint';
        var title = '[task]' + taskName + ' ' + error.plugin;
        var errorMsg = 'error: ' + error.message;
        // ターミナルにエラーを出力
        console.error(title + '\n' + errorMsg);
        // エラーを通知
        notifier.notify({
          title: title,
          message: errorMsg,
          time: 3000
        });
      }
    }))
    .pipe(eslint({ useEslintrc: true })) // .eslintrc を参照
    .pipe(eslint.format())
    .pipe(eslint.failOnError())
    .pipe(plumber.stop());
});

// eslint の watch タスク（常時チェック）
gulp.task('watch',function(){
    gulp.watch('Leaflet/dist/*.js', function(event){
        gulp.run('lint');
    });
});

gulp.task('default', ['lint'], function(){
    gulp.run('watch');
});
```

`eslint({ useEslintrc: true })` とすることでプロジェクトのリポジトリに配置する `.eslintrc` ファイルを参照しています。
gulp-eslint では JavaScript で lint の設定ができるので、必ずしも `.eslintrc` が必要なわけではないようですが、lint 設定もファイル化して管理したほうが共有も更新もしやすいと思いました。
ちなみに、この `.eslintrc` で Airbnb のスタイル設定を読み込みます。

```json:.eslintrc
{
  "globals": {
    "L": true,
    "$": true
  },
  "extends": "airbnb/legacy",
  "rules": {
    "comma-dangle": 0
  }
}
```

`"globals"` にプロジェクトで使うグローバル変数を指定してます。`L` は Leaflet.js、`$` は jQuery で扱う変数です。これを指定しないと無駄なエラーが吐き出されます。

`"extends"` に `"airbnb/legacy"` を指定することで Airbnb の ES5 Lint を参照します。ES6+ および React を書きたい場合は `"airbnb"` だけで OK です。詳細は [eslint-config-airbnb](https://www.npmjs.com/package/eslint-config-airbnb) のページをご覧ください。

これで `cd` でプロジェクト フォルダーに移動して `gulp lint` と叩けば、指定先の js ファイルのコードをチェックしてくれます。

## package.json にコマンドを書き込む

最後にコマンドも共有したいので、`package.json` の `scripts` にコマンドを登録して終わり。

```json:package.json
  "scripts": {
    "lint": "gulp lint",
    "watch": "gulp watch"
  },
```

![スクリーンショット 2015-12-10 22.37.49.png](https://qiita-image-store.s3.amazonaws.com/0/81547/cfe56fb2-35a3-6b3d-5e26-f67522ff2fa0.png)

動いた動いた。

ここには書きませんが、README.md とか CONTRIBUTING.md に開発のフローや環境について記述しておくのが筋なので、そちらも書き加えています。全部英語ですが、参考になれば幸いです。

* [muxlab/map-effects-100 | GitHub](https://github.com/muxlab/map-effects-100)

最後まで読んでくれてありがとうございました。
この記事書いてる最中に新たな Issue が立っていました。
「次は processhtml プラグイン使ってモックは自動で外せるようにしてさー！ごにょごにょ」..マイペースに対応しよう(汗)
という感じで gulpfile.js はまだまだ成長しそうなので、また書きます。