Introducing Webpacker

Official Rails gem for bundling JavaScript assets with Webpack

With the ever-changing JavaScript world, one important thing that has been lacking in Rails was support for proper bundling system for JavaScript assets, but soon this is going to change with the introduction of new Webpacker gem.

Rails 5.1 will have first-class support for webpack via the –webpack option and out of the box integration with React, Angular, and more coming soon.

In this post, we are going to explore the new alpha version of the webpacker gem and the features it has to offer.



Before starting out make sure ruby, node and yarn is installed on your machine. See prerequisites section for more details.

Lets start by creating a brand new Rails 5.1 app. Open up the terminal or command line and run the first command:

bundle exec rails new webpacker-example-app --edge --webpack
// or 
bundle exec rails new webpacker-example-app --edge --webpack=react
bundle exec rails new webpacker-example-app --edge --webpac=angular

Notice the new nifty -webpack option, this will setup webpack with Yarn after creating a Rails 5.1 app. Once both gems and node_modules are bundled we are set to use webpack in our Rails app. Voila! 🎉

If you have an existing Rails 4.2+ app you can install webpacker, by adding it to your Gemfile and install it like so,

rails webpacker:install
rails webpacker:install:[react, angular or vue] (optional)

Feel free to checkout the project readme here,

Note: We can also setup React or Angular if we supply the relevant options.


As with all Rails things, webpacker also comes with certain conventions by default. Lets take a look at them one by one:

1. Folder structure

Take a look at the new app/*javascript folder. This is the folder that will contain all of the JavaScript app code and webpack entry points (a.k.a packs). By default it’s app/javascript/packs

The convention here is that all webpack entry points should be placed in the app/*javascript/*packs folder and the modules can be placed inside app/*javascript folder in any way you like. So, lets say if we are building a new calendar app. We can structure it like so:

*Note: All options are customisable from config/webpack/paths.yml

File and folder convention

By default notice webpacker generates an application.js inside the packs directory file for demo purposes.

2. Webpack configuration

The generator adds webpack configurations for each environment into the *config/webpack. These configurations out of the box support many of the webpack features for various environments, like code-splitting, asset-fingerprinting, and linking static assets like image and stylesheets (including post-css).

*Note: All options are customisable from config/webpack/paths.yml

Live reloading

Webpacker provides a binstub for running webpack-dev-server that supports live code reloading in the development environment. You will need to install additional plugins for Webpack if you want features like HMR [Hot module replacement]. *Note: Dev server options are customisable from config/webpack/development.server.yml

You can checkout these links on this subject,

Putting it into action

Now, lets create a small JavaScript module and put it all together to see how it works.

1. Setup

First, lets add foreman gem for managing multiple processes in development group of your Gemfile and run bundle install. Then, create two files called Procfile and dev) in the root folder.


web: bundle exec puma -p $PORT

web: bundle exec rails s
# watcher: ./bin/webpack-watcher
hot: ./bin/webpack-dev-server

Also, lets setup a small binstub that runs the, create a file inside bin/* folder called server and paste following commands:

#!/bin/bash -i
bundle install
bundle exec foreman start -f

You might also need to do chmod 777 bin/server incase you get permission denied when running this binstub. So, now we can do ./bin/server and it will run the and run webpack and puma as intended.

2. Code

Now, lets add our new example counter module, first create a module folder called counter in the app/javascript folder then inside this folder create two files: index.js and counter.js with following code.



Then, inside packs directory create an entry file called counter.js and fill it up with following code.

Pretty simple!

3. View

Lastly, for adding this counter to our view lets generate a controller:

bundle exec rails g controller pages index

Then inside the routes.rb file setup our root route to be this:

root ‘pages#index’

..and finally inside pages/index.html.erb paste the following HTML snippet:

<div class=”counter-wrapper”>
<form class=’counter’>
<button id=’increment’>Increment</button>
<input type=”number” name=”counter” id=’counter’ value=’0' />
<button id=’decrement’>Decrement</button>
<%= javascript_pack_tag ‘counter’ %>

Notice, the javascript_pack_tag helper, it will pull in the compiled counter module script and reference it in app like so:

<script src=”http://localhost:8080/counter.js"></script>

4. Running

Open up the current directory in Terminal and run:

# or
bundle exec foreman start -f

You will notice in Terminal that webpack compiles our counter module and displays relevant information like size, etc.

Now, go to http://localhost:5000/ in your browser and you will see the counter app running. Yay! 😄

5. Styling

Lets add some styling to our counter module using Sass. Create a new style.sass inside app/javascript/counter/style.sass with following code:

..and then finally add it to our counter/index.js and view:

<%= stylesheet_pack_tag ‘counter’ %>

Now, go back to the browser and notice the new changes are live-reloaded because of webpack dev server hot module replacement. Amazing! 👍

<link rel="stylesheet" media="screen" href="http://localhost:8080/counter.css" />


Last but not least, lets take a look at deployment, particularly deploying this app to Heroku. Heroku installs yarn and node by default if you deploy a rails app with Webpacker. Also replace sqlite gem with pg gem in Gemfile, bundle, and commit the changes.

Now type git push heroku master from your app folder and it should be deployed to Heroku. Simple! 😀

You can find more examples on this repo: