Rails
Node.js
Heroku

sprocketsではなくnodejsを使うRailsアプリをHerokuにデプロイする方法

More than 3 years have passed since last update.

sprocketsは面倒だし、babelやwebpackなどの最新JSテクノロジーを使うためにnodejsを使ってassetsを組み立てたいという欲求があると思います。

簡単に解決するなら gulp build したものをgitリポジトリに追加してしまえばいいのですが、挙動がおかしかった時にバグがあるのか、それともソースがちゃんと git-add できていなくて古いことが原因なのか、とか考える必要が生じて嫌な感じです。できればデプロイ時にビルドしたい。

そういう風な感じでassetsを管理しているRailsアプリをHerokuにデプロイするときに色々ハマったので備忘録としてその方法を書き残します。


忘れずにrails_12factorをbundleする

nodejsは関係無いですが、HerokuでRailsを動かすには必須らしいですね。


Gemfile

gem "rails_12factor", :group => :production



rubyとnodejsのbuildpackを指定する

Herokuでrubyとnodejsが必要なのでbuildpackを2つ指定します。

heroku create --buildpack https://github.com/heroku/heroku-buildpack-ruby.git APP_NAME

heroku buildpacks:add https://github.com/heroku/heroku-buildpack-nodejs.git

昔は1アプリに複数のbuildpackを指定するにはmulti-buildpackを使う必要があったけど、最近は buildpacks:add するだけで問題無いとのこと。


NPM_CONFIG_PRODUCTION=false

package.jsonで指定したパッケージをインストールして開発を行います。Railsでgulpやらを使う場合、それ自体は開発にしか使わないものなので devDependencies に入れたくなりますが、そのままだとnodejs buildpackが dependencies しかインストールしないので上手く行きません。

一つの回避方法は全部 dependencies に入れてしまうことですが、気持ちが悪いので変わりに NPM_CONFIG_PRODUCTION=false 環境変数を設定します。

heroku config:set NPM_CONFIG_PRODUCTION=false

これで devDependenciesdependencies の両方がインストールされるようになります。


postinstallで全てビルドする

nodejs buildpackを使っているとgit-push時に自動的に npm install が走ります。その後で heroku run gulp build とすることを考えましたが、ビルド結果が永続化されず参照エラーになりました。heroku run でファイルを書き出しても消えちゃうんですかね?Heroku弱者なのでよく分かりません。

この問題を回避するには全てを npm install で生成すればいいということなので postinstall scriptで全てビルドするようにしました。


package.json

{

"scripts": {
"postinstall": "node_modules/.bin/bower install && node_modules/.bin/gulp build"
}
}

bower install していますが、これだけだと bower_components ディレクトリ以下が永続化されません。


ファイルを吐き出すディレクトリは全て cacheDirectories に追加する

cacheDirectories に指定していないディレクトリに生成したファイルは npm install 中だろうと消えてしまいます :expressionless:


package.json

{

"cacheDirectories": [
"bower_components",
"node_modules"
]
}


まとめ

そういう感じで設定をちゃんとすると、Heroku上でgulpでビルドしたものを使うことができるようになります。