Skip to content

Instantly share code, notes, and snippets.

@brennovich
Forked from mrrooijen/.gitignore
Last active December 17, 2015 12:29
Show Gist options
  • Save brennovich/5609580 to your computer and use it in GitHub Desktop.
Save brennovich/5609580 to your computer and use it in GitHub Desktop.
Middleman setup on Heroku

Instructions

If you don't already have a MiddleMan website, simply generate a new one by running:

middleman init my_new_website --bundler --rack

When ready, copy over the contents of the files in this gist/repository to your own project.


To run in development mode:

bundle exec thin start -p 3000

To have MiddleMan auto-build on each save, we use the Watchr gem. It will auto-build on each save in the source directory:

bundle exec watchr ./Watchrfile

To deploy to Heroku:

heroku create mywebsite --stack cedar
git push heroku master

Assuming you've committed everything you were going to deploy.

Also, note that you must pass in the --stack cedar for various reasons, such as:

  • Being able to write to the filesystem (anywhere, not just ./tmp)
  • Being able to use Procfile to tell Heroku to render/compile the site to build (aka public) before running the Thin server

How does it work?

When the website has been deployed to Heroku, it will, on the first request, compile the website to the build directory. Once compiled, it will spin up a Thin server to serve the pages. Now since the only thing it serves will be static pages, it will still be blazing fast, regardless of whether it has to go through the Rack-layer. The reason this going behind a Rack layer is because we're using Rack::TryStatic from Rack-Contrib. This will allow us to have "pretty" URLs. So for example say you have a request come in at http://mywebsite.herokuapp.com/some-page it will look for a file in build/some-page.html.

There is no longer the need to pre-compile your static files locally, commit them and then push them to Heroku. Just push your dynamic code to Heroku and it should just work.

require File.expand_path("../rack_try_static", __FILE__)
use ::Rack::TryStatic,
:root => "build",
:urls => ["/"],
:try => [".html", "index.html", "/index.html"]
run lambda {
not_found_page = File.expand_path('../build/404.html', __FILE__)
[404, {'Content-Type' => 'text/html'}, [File.read(not_found_page)]]
}j
source 'https://rubygems.org'
ruby '2.0.0'
gem 'middleman', '~> 3.1.0.beta.1'
gem 'middleman-blog'
gem 'middleman-syntax'
gem 'bourbon'
gem 'neat'
gem 'rb-fsevent'
gem 'redcarpet'
gem 'thin'
web: bundle exec middleman build && thin start -p $PORT
# encoding: utf-8
module Rack
class TryStatic
def initialize(app, options)
@app = app
@try = ["", *options.delete(:try)]
@static = ::Rack::Static.new(
lambda { [404, {}, []] },
options)
end
def call(env)
orig_path = env["PATH_INFO"]
found = nil
@try.each do |path|
resp = @static.call(env.merge!({"PATH_INFO" => orig_path + path}))
break if 404 != resp[0] && found = resp
end
found or @app.call
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment