Developing a Rails project with a rich client side features, at some point you may want to replace the Asset Pipeline with a modern Node.js-based asset compilation toolkit. Webpack is a great example of an asset compilation tool.
There are a lot of opinions about issues with Asset Pipeline. Some of the reasons are: it doesn’t scale well for SPA applications; it doesn’t support require/commonjs modules and asset bundling (using
require "component.css" from
This is it: one day you decide switch to Webpack in your Rails app. How do you start? For majority of developers, the easiest way is to start with a gem. The most popular one is webpack-rails.
But in our case, the problem with the gem was that it required us to change the workflow. Instead of simply running
rails server you would need to manage processes with
It’s the same reason why I wrote a post about ActiveRecord fields encryption. I do not like using universal gems with hidden logic that just works (tm) because in most cases you can implement it with a small snippet avoiding introducing a new dependency that you’d have to upgrade and maintain in the future.
I saw no need in using an extra dependency here, because a basic integration with Webpack is quite fast-forward.
Working on OnboardIQ in 2015, we came up with a solution that I want to share in this post. All of Webpack and Rails integration is just a set of techniques and helpers that tie them together.
The asset helper
In development, Webpack requires running a separate process that would compile changed assets and as a developer who is not famillar with Webpack it’s easy to forget to run or restart the Webpack process.
I decided to fix it on the Rails side. The idea is to inform the developer is the webpack process is not running.
Then you proxy all calls to webpack-generated assets with
webpack_bundle_tag (instead of
When you’re browsing in your Rails app and modifying assets, Webpack will recompile JS when the files are changed. Since it’s not very likely that you will monitor the Webpack output, sometimes you may miss that there is a compilation error in your code. To avoid these cases, me and Emil Kashkevich came up with the following trick:
- Small Webpack plugin writes all compilation errors to
tmp/webpack-status.json. If there are no errors, the file becomes empty
tmp/webpack-status.jsonis not empty, Rails will read the file and display the backtrace
- You’ll immediately see all Webpack errors right in your browser
I decided not to share the plugin here because the implementation was too dirty, but it should’t take more than an hour for you to write a similar script.
Running on Heroku
We also wanted to make Heroku automatically precompile all assets when the app is deployed. At first I tried to write a simple Heroku buildpack myself, but then I discovered that the official Node buildpack from Heroku perfectly works for us.
We had to configure Heroku to use two buildpacks:
And set the NPM environment:
You’ll also need to have the
package.json which it’s basically a
Gemfile for the NPM world. This file allows to set a
postinstall callback that will run on Heroku. In our case it precompiled the assets:
Well done. From now on, when you push the code to Heroku, it will run NPM/Webpack scripts to precompile the assets as well as the Rails app.
I hope these three recipes helped you to get started with Webpack on Rails and Heroku.
Big thanks to my former colleagues at Evil Martians who contributed to the Webpack integration described in this post.