title-logo

Deploy Middleman to Heroku

October 31, 2014

今日もブログに書くことは何にも思いつかないので、やっぱりこのブログ自体についての記事になりました。

このブログは Heroku でホストしています。サイトが単なる静的な HTML なので、最初は Amazon S3 に置こうと考えていましたが、そんなに容量がでかくなることもないだろうし、Heroku の無料枠で全然いけるんじゃねーかな、と思い直しました。

Middleman を Heroku にデプロイする

Middleman は静的サイトジェネレータです。その生成された静的サイトを Heroku で動かすためには、以下の手順を行う必要があります。

  1. デプロイしたときに静的ファイルを生成する
  2. 生成された静的ファイルをアプリケーションサーバーでサーブする

デプロイしたときに静的ファイルを生成する

Middleman は、以下を実行することで静的ファイルを生成します。

$ middleman build

つまり、git push でデプロイしたときにこれが動くようにすればよいですね。

静的サイトとはいえ Ruby のエコシステムを利用しているので、サイトは Rack アプリケーションとして動作させることを前提とします。参考にした How I deployed Middleman to Heroku という記事には、Heroku では assets:precompile という rake タスクが実行されるとありました。なので、そのタスクを用意して、その中で middleman build を実行すればいいんですが、ぶっちゃけそれだけのためであれば、わざわざ Rakefile を用意せずとも config.ru の中でコマンドを呼べばよさそうです。そこで、config.ru を作って以下の1行を追加しています。

config.ru

~
`bundle exec middleman build`
~

これで、Web サーバーが起動したときに middleman build が実行され、静的ファイルが生成されます。

生成された静的ファイルをアプリケーションサーバーでサーブする

さて、静的ファイルは生成されたので、Rack アプリケーションサーバーがそれらをサーブできるようにしてあげないといけません。幸い、rack-contrib に Rack::TryStatic というミドルウェアがあるのでそれを利用します。ココに書いてある内容のほぼそのまんまですが、config.ru に以下を追加しました。

config.ru

~
use Rack::TryStatic, 
    :root => 'build',
    :urls => %w[/],
    :try => ['.html', 'index.html', '/index.html']

# otherwise 404 NotFound
run proc { [404, { 'Content-Type' => 'text/html' }, [File.read(File.expand_path("../build/404/index.html", __FILE__))]] }
~

index.html を探しにいく設定になっているので、Middleman 側で directory_indexes を有効にしておく必要があります。また、404 ページも先に用意しておかないといけません。

これまでの config.ru の設定をまとめると以下のようになります。

config.ru

require 'rack'
require 'rack/contrib/try_static'

# Build static files when booting
`bundle exec middleman build`

use Rack::TryStatic, 
    :root => 'build',
    :urls => %w[/],
    :try => ['.html', 'index.html', '/index.html']

# otherwise 404 NotFound
run proc { [404, { 'Content-Type' => 'text/html' }, [File.read(File.expand_path("../build/404/index.html", __FILE__))]] }

これで、Web サーバーで静的ファイルをサーブするための準備ができました。あとは Procfile で Rack アプリケーションサーバーの起動を指定してあげればよいだけです。Rack サーバーには Puma を指定しました。この選択には特にこれといった理由があったわけじゃなくて、前述の参考記事の中でそうしてあったのでそのまま真似しただけです。

Procfile

web: bundle exec puma -p $PORT -e $RACK_ENV

これで、Middleman のサイトを Heroku にデプロイしてホストすることができます。もちろん、そのために追加した機能については Gemfile に記載しておく必要があります。念のため。

Gemfile

~
gem 'puma'
gem 'rack-contrib'
~