PhoenixフレームワークでBrunchもGulpもGruntも使いたくない場合


## 対象
BrunchもGulpもGruntも面倒くさいんじゃ〜！
`npm run <something>`コマンドでjsと付き合いたいんじゃ〜！！
というあなたに届けます。

ですが、BrunchからGulpやGruntに替える際も参考になると思います。

前提として、今回は`mix phoenix.new`の時に`--no-brunch`オプションは付けていません。

あ、大事なこと書き忘れてた。本編は[Elixir Phoenix + Browserify](http://martinholman.co.nz/blog/2015/09/27/elixir-phoenix-browserify/)をアレンジしたものです。

## 手順

nodeモジュールを全部消します。

```sh
$ rm -rf node_modules
```

`package.json`を編集してbrunch周りを全部消します：

```json:packange.json
{
  "repository": {
  },
  "dependencies": {
  }
}
```

js周りのパッケージをインストールします：

```sh
$ npm install watchify browserify babelify uglify-js --save-dev
$ npm install babel-preset-es2015 babel-preset-react --save-dev
```

`--save`じゃなくて`--save-dev`付けてますが、npmパッケージじゃないのでどっちでもいいです。babelの方はお好みで変えて下さい。

babelの設定ファイルを書きます：

```js:.babelrc
{
  "presets": [
    "es2015",
    "react"
  ]
}
```

css周りのパッケージをインストールします：

```sh
$ npm install catw --save-dev
```

sass/less/stylus/postcssなどをお使いの方はそれ用のパッケージに書き換えてください。

assets周りのパッケージをインストールします：

```sh
$ npm install watch-run --save-dev
```

あとtest周りはお好みで入れて下さい。

`package.json`の`scripts`部分を書きます：

```json:package.json
{
  "repository": {},
  "scripts": {
    "build-assets": "cp -r web/static/assets/* priv/static",
    "watch-assets": "watch-run -p 'web/static/assets/*' npm run build-assets",
    "build-js": "browserify -t babelify web/static/js/app.js | uglifyjs -mc > priv/static/js/app.js",
    "watch-js": "watchify -t babelify web/static/js/app.js -o priv/static/js/app.js -dv",
    "build-css": "cat web/static/css/*.css > priv/static/css/app.css",
    "watch-css": "catw web/static/css/*.css -o priv/static/css/app.css -v",
    "build": "npm run build-assets && npm run build-js && npm run build-css",
    "watch": "npm run watch-assets & npm run watch-js & npm run watch-css",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "dependencies": {},
  "devDependencies": {
    "babelify": "^7.2.0",
    "browserify": "^12.0.1",
    "catw": "^1.0.1",
    "uglify-js": "^2.6.1",
    "watch-run": "^1.2.4",
    "watchify": "^3.6.1"
  }
}
```

これで`npm run watch`で開発用、`npm run build`でプロダクション用のjs/css/assetsがコンパイルできるようになりました。

`web/static/js/app.js`でphoniex_htmlのjsファイルをアプリケーションルートを基準に読み込む設定になってるので、browserify/babelが分かるように書き換えます：

```js:web/static/js/app.js
import "../../../deps/phoenix_html/web/static/js/phoenix_html"
```

最後に`config/dev.exs`の`watchers`の部分を書き換えます。

```elixir:config/dev.exs
config :goal_server, GoalServer.Endpoint,
  http: [port: 4000],
  debug_errors: true,
  code_reloader: true,
  cache_static_lookup: false,
  check_origin: false,
  watchers: [npm: ["run", "watch"]] # ←この行
```

これで`mix phoenix.server`コマンドで自動的に`npm run watch`を動かすようになりました。

プロダクションリリースの際にはサービス起動前に`npm run build`が走るように各種ツールの設定ファイルを書くのを忘れないようにしてください。

## まとめ

Brunch外しのポイントは、`web/static/js/app.js`と`config/dev.exs`の書き換えですね。GulpやGruntに替える際もそこを注意すれば良いと思います。

最後に`git diff`の結果を貼っておきます：

```diff
diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..bd20dc1
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,6 @@
+{
+  "presets": [
+    "es2015",
+    "react"
+  ]
+}
diff --git a/config/dev.exs b/config/dev.exs
index 8fbca2c..c622b18 100644
--- a/config/dev.exs
+++ b/config/dev.exs
@@ -12,7 +12,7 @@ config :goal_server, GoalServer.Endpoint,
   code_reloader: true,
   cache_static_lookup: false,
   check_origin: false,
-  watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin"]]
+  watchers: [npm: ["run", "watch"]]
 
 # Watch static and templates for browser reloading.
 config :goal_server, GoalServer.Endpoint,
diff --git a/package.json b/package.json
index eb0a7bc..ad955bf 100644
--- a/package.json
+++ b/package.json
@@ -1,12 +1,25 @@
 {
-  "repository": {
+  "repository": {},
+  "scripts": {
+    "build-assets": "cp -r web/static/assets/* priv/static",
+    "watch-assets": "watch-run -p 'web/static/assets/*' npm run build-assets",
+    "build-js": "browserify -t babelify web/static/js/app.js | uglifyjs -mc > priv/static/js/app.js",
+    "watch-js": "watchify -t babelify web/static/js/app.js -o priv/static/js/app.js -dv",
+    "build-css": "cat web/static/css/*.css > priv/static/css/app.css",
+    "watch-css": "catw web/static/css/*.css -o priv/static/css/app.css -v",
+    "build": "npm run build-assets && npm run build-js && npm run build-css",
+    "watch": "npm run watch-assets & npm run watch-js & npm run watch-css",
+    "test": "echo \"Error: no test specified\" && exit 1"
   },
-  "dependencies": {
-    "babel-brunch": "^6.0.0",
-    "brunch": "^2.0.0",
-    "clean-css-brunch": ">= 1.0 < 1.8",
-    "css-brunch": ">= 1.0 < 1.8",
-    "javascript-brunch": ">= 1.0 < 1.8",
-    "uglify-js-brunch": ">= 1.0 < 1.8"
+  "dependencies": {},
+  "devDependencies": {
+    "babel-preset-es2015": "^6.3.13",
+    "babel-preset-react": "^6.3.13",
+    "babelify": "^7.2.0",
+    "browserify": "^12.0.1",
+    "catw": "^1.0.1",
+    "uglify-js": "^2.6.1",
+    "watch-run": "^1.2.4",
+    "watchify": "^3.6.1"
   }
 }
diff --git a/web/static/js/app.js b/web/static/js/app.js
index 8f61e4d..55dd958 100644
--- a/web/static/js/app.js
+++ b/web/static/js/app.js
@@ -11,7 +11,7 @@
 //
 // If you no longer want to use a dependency, remember
 // to also remove its path from "config.paths.watched".
-import "deps/phoenix_html/web/static/js/phoenix_html"
+import "../../../deps/phoenix_html/web/static/js/phoenix_html"
 
 // Import local files
 //
```