自分の Ruby 製の Web アプリでいつも JS ファイルをコミットして git push heroku master
しているのがダサいのでやめたいなーと思い、やり方を調べてみた。
すごく簡単だったのでこれからは JS も提供するような Ruby の Web アプリケーションを提供するようなときには必ずこのやり方を使おうと思った。
heroku-buildpack-multi
heroku のデフォルトでは 1 つのアプリに対して 1 つの buildpack しか使えないけど、ddollar/heroku-buildpack-multi を使うと 2 つの buildpack を使い、node.js + gulp でクライアントサイドの JS をビルドし、ruby + rack でサーバーサイドの Web アプリを提供する、ということができるっぽい。
アプリを作るときに heroku-buildpack-multi を指定するか、
$ heroku create your-app-name --buildpack https://github.com/ddollar/heroku-buildpack-multi.git
すでに作成したアプリに設定を追加してもよい。
$ heroku config:add BUILDPACK_URL=https://github.com/ddollar/heroku-buildpack-multi.git
で、.buildpacks
ファイルに buildpack の Git URL を 1 行 1 つで書いておく。
$ cat .buildpacks
https://github.com/heroku/heroku-buildpack-nodejs.git
https://github.com/heroku/heroku-buildpack-ruby.git
試すためのアプリ
gulp build
で src/index.jade
から public/index.html
を生成し、rack で public/index.html
を提供するという最小限の構成で試してみた。
Gemfile
source 'https://rubygems.org'
gem 'thin'
config.ru
use Rack::Static, urls: [''], root: 'public', index: 'index.html'
run Rack::Directory.new 'public'
gulpfile.coffee
gulp = require 'gulp'
jade = require 'gulp-jade'
gulp.task 'build', ->
gulp.src('./src/index.jade')
.pipe jade()
.pipe gulp.dest('public')
src/index.jade
doctype html
html
head
title hello
body
#app world
Procfile
このやり方がいいのかはよく分からないけど、Procfile
には下記のように書いてみた。
web: gulp build && bundle exec thin start -p $PORT
こう書いておくと heroku push origin master
するときにも gulp build
が実行されるし、heroku restart
でアプリを再起動するときにも gulp build
が実行されるので、heroku の ephemeral filesystem でも index.html
が消失してしまうという問題は起きなさそう。
うまく動いた例を tily/testing-heroku-buildpack-multi に置いておいた。
参考資料
-
Getting Started with Ruby on Heroku | Heroku Dev Center
- $PORT
-
Dynos and the Dyno Manager | Heroku Dev Center
- ephemeral file system
- Procfile に gulp build を書けば大丈夫なことを確認した
- ddollar/heroku-buildpack-multi
- Buildpacks | Heroku Dev Center
- ダメ男のブログ: Herokuのwebサーバをthinに変更する
- CoreOS のパブリックイメージをリリースしました! : ニフティクラウド ユーザーブログ
- React.js、やっと使えるようになった - ただのにっき(2015-04-18)