Best Heroku hosting

Are there good practices to run middleman on Heroku ?

For now the best approach I have is this:

Add a Rakefile that contains this:

namespace :assets do
  desc 'heroku runs this command on push'
  task :precompile do
    system "bundle exec middleman build"
  end
end

^ Heroku will think it’s a Rails app and run that step when building the slug.

Next we need a web server to send the statically compiled files. For now I’m using a Sinata app because it’s relatively fast and convenient.

require "sinatra"
set server: "thin"

# Ugly code that serves all assets directly from memory.
# TODO: .gz support
# TODO: handle redirects
static_dir = File.join settings.root, 'build'
Dir[File.join static_dir, '**', '*'].each do |file_path|
  next unless File.file?(file_path)

  file_data = IO.read(file_path)
  path = file_path.sub(static_dir, '')
  mime = Rack::Mime.mime_type File.extname(path)

  if File.basename(path) == 'index.html'
    path = (File.dirname(path) + '/').gsub(/\/+/, '/')
    get path do
      protected!
      content_type :html
      cache_control :private, :must_revalidate
      body file_data
    end
    get path[0..-2] do
      redirect to(path)
    end
  else
    get path do
      content_type mime
      cache_control :public
      body file_data
    end
  end
end

I’ve noticed that Heroku dynos are quite weak so it would make sense to use a pre-compiled binary like a Go program to squeeze out even more performance.

I came up with a different solution yesterday: Middleman on Heroku (with Nginx)

Using my approach the site is precompiled on Heroku on dyno start-up and then the static files are served via Nginx. I haven’t run any benchmarks, but this should be about as good as serving statics assets gets on Heroku. The Nginx configuration could be improved a bit, though.

I also wrote another, earlier, blog post which details a Rack-based approach:Middleman on Heroku – 2013 edition

I wanted to submit these tutorials to the Middleman directory, but I don’t think they fit into any of the existing categories… Maybe there should be a “Tutorials” category in addition to the existing Extensions, Templates, and Services?

2 Likes

Pretty cool. I agree that this really begs for benchmarks. Is nginx serving from disk faster than ruby serving from memory ? Who knows :smile:

One issue I have had in the past is that middleman would put the assets on different paths with the cache buster. I don’t know if it’s still valid with the asset_hash but it was causing 404s if your page is served from one dyno and the asset from another. That’s why I’m building things upfront.

+1 for tutorials category.