Elm + Rails + Webpack + Heroku

Alex Koppel bio photo By Alex Koppel

So! I’ve been building a side project in Elm. It’s been really fun. Elm is the first statically typed language I’ve worked with and the first functional language I’ve built anything significant in since college, and it’s stretching me in good ways.

Last week, I got my project (about books and Twitter) to the point I was ready to put it online using Heroku. It was straightforward to get the Rails backend1 and Elm frontend set up locally (thanks to Abe Voelker’s helpful blog post), but I ran into a few additional snags getting it hosted.

Here’s what I learned, in the hope it will be useful to others:

Buildpacks

Heroku’s built-in buildpacks (Settings > Buildpacks) are all you need, but the order of the buildpacks matters. The Node.js buildpack (which handles all the npm work required for webpack, which in turns turns Elm into browser-compatible Javascript) needs to be first, the Ruby buildpack second.

Heroku Buildpacks

When mine were in the wrong order, Heroku expected that the web dyno would run npm start, which doesn’t work (no such npm task being defined).

Properly set up, my dynos (Resources > Free Dynos) look like this – yours should probably look similar:

Heroku Resources

Precompiling Elm

Locally, Webpack will compile your Elm files as needed. That’s not going to work on Heroku, though – they have to be compiled when the slug is built (that is, when Heroku packages up your app).

This may all change if/when Webpack is supported in Rails 5.1, but for now there’s a little bit of work to do.

Fortunately, it’s just a little bit of work, following Jan Dudek’s example: add a Rake task that uses Webpack to compile Elm, and hook it into the assets:precompile task.

namespace :webpack do
  desc 'compile assets using webpack'
  task :compile do
    sh '`npm bin`/webpack --config $PATH_TO_YOUR_WEBPACK_CONFIG_JS_FILE'
  end
end

Rake::Task['assets:precompile'].enhance ['webpack:compile']

Heroku is Case-Sensitive

One final gotcha for those of us developing on Macs: Heroku is case-sensitive, OS X is not.

I extracted some view code into a views/ directory – creating, for instance, a module Views.Home that lived in views/Home.elm. Locally it worked fine and everything looked right, but on Heroku it failed with this error:

 ERROR in ./webpack/elm/Main.elm
       Module build failed: Error: Compiler process exited with error Compilation failed
       I cannot find module 'Views.Home'.
       Module 'Main' is trying to import it.
       Potential problems could be:
       * Misspelled the module name
       * Need to add a source directory or new dependency to elm-package.json

On Heroku, it expected to find the file at Views/Home.elm. Keep that in mind when setting up your directory structure/namespaces.

That’s it!

Other than these relatively small issues, everything’s worked smoothly and my app is up and running (for me, at least: it’s way too ugly to share at the moment 😝). Hopefully this may save someone the few hours I spent figuring this stuff out.

Have a great 2017!

  1. The advantage of Rails is that I know it; in two hours I had all the CRUD endpoints I needed built and could focus on learning Elm. Perhaps someday I’ll port the backend to, say, Elixir, but only after I’ve got the frontend down.