I’ve written about hosting Middleman apps a couple of times before. This article supersedes the advice given in those earlier blog posts.
This new approach uses Heroku’s official Ruby buildpack and uses its asset precompile behaviour to build the Middleman site.
The advantage of this approach is that the site gets built on deploy and doesn’t need to be rebuilt every time that the app reboots. This should result in faster and more reliable app boots.
I used the latest version of Middleman (4.2.1) and Ruby (2.4.0) at the time of writing. You may need to adapt the steps if you’re using different versions…
-
Create a new Middleman app/site:
middleman init awesome-site
If you’ve already got a Middleman app, you can skip this step…
-
Append the following to the Gemfile:
gem 'rake' gem 'puma' gem 'rack-contrib'
I also recommend specifying the Ruby version by adding the following on a new line after
source "https://rubygems.org"
ruby "~> 2.4.0"
If you use RVM or rbenv, also add a
.ruby-version
file with2.4.0
as the contents) -
Run
bundle install
-
Add the following to the
config.rb
file:# Use “pretty” URLs (without the `.html` suffix) activate :directory_indexes # Append hashes to compiled assets activate :asset_hash
You may also, optionally, wish to enable javascript and CSS minification
-
Create a file called
config.ru
(replace its contents if it already exists) with the following contents:require "rack" require "rack/contrib/try_static" # Enable proper HEAD responses use Rack::Head # Add basic auth if configured if ENV["HTTP_USER"] && ENV["HTTP_PASSWORD"] use Rack::Auth::Basic, "Restricted Area" do |username, password| [username, password] == [ENV["HTTP_USER"], ENV["HTTP_PASSWORD"]] end end # Attempt to serve static HTML files use Rack::TryStatic, :root => "build", :urls => %w[/], :try => ['.html', 'index.html', '/index.html'] # Serve a 404 page if all else fails run lambda { |env| [ 404, { "Content-Type" => "text/html", "Cache-Control" => "public, max-age=60" }, File.open("build/404/index.html", File::RDONLY) ] }
-
Add a
Procfile
to the project root:web: bundle exec puma -t 5:5 -p ${PORT:-3000} -e ${RACK_ENV:-development}
-
Add a new file named
Rakefile
:namespace :assets do task :precompile do sh "middleman build" end end
-
Add a 404 page (
source/404.html.erb
):--- title: Page not found --- <h1> Page not found </h1>
-
Commit your changes and push to Heroku.
Hurrah! That’s it.
Postscript
If you’re using an external asset pipeline that requires Node.js, you should add the Node.js buildpack to your Heroku app.
heroku buildpacks:set heroku/ruby
heroku buildpacks:add heroku/nodejs --index 1
Note: The Ruby buildpack should be last when you run heroku buildpacks
More about Heroku buildpacks: