コンパクトなJSフロント開発環境を求めて ~ gulpなしでやってみる ~

ども、フロントエンドの平山です。
興味本位でBabel6の開発環境をgulpなしで構築してみましたので、ご報告します！

## 背景

最近は、フロント領域のウェイトが大きくなる開発が増えてきました。
それに伴いgulpなどのビルドツールを使用するケースがほとんどだと思います。
その反面、個人の制作時にはもっとライトに作りたいにも関わらず、
都度、gulpfileを作成して・・・というフローが生まれ、気軽に着手するには手間が多い環境のように感じます。
またツールの移り変わりも多く、変化への追従やgulp自体の変化など注意を払うべき変数が多い状況です。

## やるぞ

ということで、手軽に試せるが、新しいスタックで取り組めるように考慮して環境構築を行ってみました。
Babel6やreact、eslint、power-assertなどを使用しました。

## 結論

説明が長くなったので結論を先に。

GitHub: [khirayama/boilerplate](https://github.com/khirayama/boilerplate)

gulpを使用した環境とほぼ同じことをできました。
画像の圧縮やRails環境への配置など行っていませんが、基本的にはやることは変わらないかと思います。
また今回行って感じたのは、gulpなしの環境の（精神的な）手軽さと管理すべき環境を少なくできたのはよかったように思います。設定ファイル（.babelrcなど）の作成も検討しましたが、手軽さを重視したため、package.jsonに設定の記述を行うようにしました。babelやmochaでoptionが増えてきたときには別途作成するのがよいでしょう。
その反面、gulpの利点も感じました。チーム開発や変数的に管理する場合やwatchを手軽に行う場合など効果が高そうです。
シーンによってすぐに切り替えれるとよりよりJSライフを楽しめるのではないでしょうか！

## さて、内容です。

### HTML

こちらはJadeを使用しました。
まずはJadeをinstall

```
$ npm i -D jade
```

そしてjadeをhtmlに変換するscriptを記述します。

```
"scripts": {
    "build:html": "jade src --out dist"
}
```
```
$ npm run build:html
```
こうすることで```src```ディレクトリにあるjadeファイルをhtmlに変換できます。
また自動変換する場合、jadeは```--watch```があるので、

```
"scripts": {
   "watch:html": "jade -w src --out dist"
}
```
```
$ npm run watch:html
```

とすればファイル監視を行えます。

### CSS

CSSもsassを使用し、HTML同様にビルドしてみます。

```
$ npm i -D node-sass
```
```
"scripts": {
  "build:css": "sass src/styles/index.sass:dist/index.css --style compressed --sourcemap=none",
  "watch:css": "sass -w src/styles/index.sass:dist/index.css --style compressed"
}
```
sassの場合、開発時にはsourcemapがある方が便利ですが、デプロイ時には不要のため、```build:css```では```--sourcemap=none```としています。

### JavsScript

JavaScriptではBabel6を用い、reactも使用可能な環境を構築します。Babel6からはpresetsという形で様々なものを使用できるようになりました。
[Babel ES2015 preset](https://babeljs.io/docs/plugins/preset-es2015/) : [https://babeljs.io/docs/plugins/preset-es2015/](https://babeljs.io/docs/plugins/preset-es2015/)

では早速es2015とreactを使用できるようにしていきます。
まずはインストール。

```
$ npm i -D babel babel-preset-es2015 babel-preset-react
```

またbrowserify（babelify）を使用したいため、そちらもインストールします。

```
$ npm i -D browserify babelify
```

そして、以下をpackacge.jsonに追加します。

```
"babel": {
  "presets": ["es2015", "react"]
}
```

これはBabel使用時にes2015とreactをpresetsで使用するという感じです。
そしてbuildスクリプトを記述します。

```
"scripts": {
   "build:js": "browserify src/scripts/index.js -t babelify -o dist/bundle.js --extension=jsx"
}
```

拡張子がjsxでも対応するよう```--extension=jsx```とします。

```
$ npm run build:js
```

を実行すると、```src/scripts/index.js```をエントリーポイントとして、```dist/bundle.js```を作成します。
jsでもHTML、CSSと同様にファイル監視を行ってみましょう。
browserifyはファイル監視のオプションを持っていないため、watchifyを使用します。

```
$ npm i -D watchify
```

ファイル監視用のタスクを追加します。

```
"scripts": {
   "watch:js": "watchify src/scripts/index.js -t babelify -o dist/bundle.js --extension=jsx --debug"
}
```

基本的にbrowserifyと同様ですが、デバッグしやすいように```--debug```を付与しています。
必要に応じて削除しても構いません。

### 開発用サーバ

開発用のサーバを構築します。今回は手軽にbrowser-syncを使用します。

```
$ npm i -D browser-sync
```

自動リロードも行いたいため、そのオプションも付与しましょう。

```
"scripts": {
  "server": "browser-sync start --server \"dist\" --files \"src/**/*.js\", \"src/**/*.sass\", \"src/**/*.jade\" --port 3000 --reload-delay 300 --no-notify"
}
```

別タスクの完了の検知を知ることができなかったため（知見ある方、教えて下さい！）、ファイル更新後のリロードまでに300msの間を持っています。このscriptを実行してみます。

```
$ npm run server
```

その後、http://localhost:3000 にアクセスするとdistをルートディレクトリとしてサーバが起動していると思います。

### ビルド・開発用スクリプト

上記で基本的に必要なスクリプトは作成できたので、組み合わせてビルド・開発環境用のスクリプトを作成します。

単純なビルドは以下で可能です。作られたdistディレクトリをコピーなどしてrailsに置くことも可能です。

```
"scripts": {
  "build": "if [ -e dist ]; then rm -r dist; fi && mkdir dist && npm run build:html & npm run build:css & npm run build:js"
}
```
```
$ npm run build
```

そして開発用はこちら。

```
"scripts": {
  "watch": "if [ -e dist ]; then rm -r dist; fi && mkdir dist && npm run watch:html & npm run watch:css & npm run watch:js",
  "develop": "npm run watch & npm run server",
}
```
```
$ npm run develop
```

これを行うとhttp://localhost:3000 にサーバが立ち上がり、更新が行われたらビルド→自動リロードを行います。
サーバの起動が不要な場合は、```$ npm run watch```で良いため、二つのスクリプトに分けています。

※ 大雑把に``` rm -rf```を使用していますが、

### Lint

Listにはeslintを使用します。reactのシンタックスにも対応するため```eslint-plugin-react```を使用します。

```
$ npm i -D eslint eslint-plugin-react
```

またeslintの設定項目は非常に多く、柔軟に対応できる反面、ルールの管理にコストがかかる場合も多いように感じます。そのため、AirBnBが公開しているJavaScriptスタイルガイドに習った設定を利用したいと思います。
これはnpmで配布されているため更新も手軽です。
[Airbnb JavaScript Style Guide() {](https://github.com/airbnb/javascript): [https://github.com/airbnb/javascript](https://github.com/airbnb/javascript)

```
$ npm i -D eslint-config-airbnb
```

この設定を利用するため、packge.jsonにその旨を追記します。

```
  "eslintConfig": {
    "extends": "airbnb"
  }
```

スクリプトは以下です。

```
"scripts": {
 "lint": "eslint src --ext=js --ext=jsx"
}
```
```
$ npm run lint
```

### テスト

最後にテストです。テストコードもBabel6を使用する想定で書いていきます。
フレームワークにmocha、アサーションにはpower-assertを使用します。

```
$ npm i -D mocha power-assert babel-core
```

スクリプトでは、babelを使用するため、```--require=babel-core/register```オプションを付与します。

```
"scripts": {
 "test": "mocha --require=babel-core/register"
}
```

テスト用にプロジェクトルートに```test```ディレクトリを作成しテストを記述していきます。
完成したら、```$ npm test```で実行！

### 完成物

[package.json](https://github.com/khirayama/boilerplate/blob/master/package.json)
[全体像 khirayama/boilerplate](https://github.com/khirayama/boilerplate)

※結論は上部

#### 参考
[gulp なしの Web フロントエンド開発 - アカベコマイリ](http://akabeko.me/blog/2015/08/dev-web-front-end-without-gulp/)
[ES2015 preset](https://babeljs.io/docs/plugins/preset-es2015/)
[Airbnb JavaScript Style Guide() {](https://github.com/airbnb/javascript)