STEP-BY-STEP GUIDE

Ruby on Rails 6 with Webpacker and Bootstrap

Complete step-by-step guide on setting up Bootstrap using Webpacker in Rails 6

Adrian Teh
Jul 11 · 7 min read
Background photo by Samuel Zeller on Unsplash

What is Webpacker?

It’s essentially a gem that makes it easy for us to use Webpack in Rails applications.

So what does Webpack do? Simply put, it takes all of your assets (JavaScripts, css, images, font files, etc.) and bundle all of them together to make one giant file that you can include in to your Rails application. Internally it creates a dependency graph which helps it to navigate through all your asset dependencies in order to generate the bundled file. Like anything else, you can configure webpack via webpacker to generate multiple bundles. I’ll explain further later on how and why you would want to do that.

FYI, i’ll be using webpack and webpacker interchangeable in this article unless clearly indicated.

Sprockets and/or Webpacker?

TLDR: If you’re planning to write react components, use Webpacker. If you only need to sprinkle some Javascript, just use the regular asset pipeline via Sprockets.

The first question that came to mind when I first started a new Rails 6 application. Both sprockets and webpacker comes as default. So, which should I use to manage my assets? Should I be using both?

There are different answers to this depending on your use case, short answer: If you already have all your assets managed through the asset pipeline via sprockets, keep them there. There’s no reason for you to move them over to webpack if you’re not building “app-like JavaScript”. The README on the official webpacker repo explains it well enough:

...It coexists with the asset pipeline, as the primary purpose for webpack is app-like JavaScript, not images, CSS, or even JavaScript Sprinkles (that all continues to live in app/assets).However, it is possible to use Webpacker for CSS, images and fonts  assets as well, in which case you may not even need the asset pipeline. This is mostly  relevant when exclusively using component-based JavaScript frameworks.

Getting Started With Webpacker

Lets start off by creating a new Rails 6 application. I’m using version 6.0.0.rc1 on Ruby 2.6.2 as of this posting:

rails new helloworld

By default, it should generate your Rails application that comes with both the regular asset pipeline and the webpacker gem.

Asset pipeline files are stored under the app/assets folder while webpack files are managed under the app/javascript/packs folder. You’ll also notice that the default application layout file comes with a reference to the application.css file using the stylesheet_link_tag (asset pipeline) and the application.js file using the javascript_pack_tag (webpacker) as follow:

To make sure we have webpack working later, lets create a simple home page that we can use to demonstrate our setup. I’ll go ahead and dump all the controller, view and route code examples below in a single gist. I’ll be doing this throughout the article as well:

Start the rails server and you should see the following in your browser when visiting http://localhost:3000

A simple hello world page

Next, lets install Bootstrap as our front-end framework. We can install this either through the asset pipeline or webpack. Lets use webpack in this case. Run the following yarn command to install Bootstrap along with 2 other libraries that Bootstrap depends on:

yarn add bootstrap jquery popper.js

Once installed, you should check out the app/package.json file to see that the right versions has been installed successfully. The package.json file is similar to the gemfile.lock file in that it helps the app to keep track of all the installed plugins. Here’s an example:

Next, we want to ensure that our javascripts understands the $, Jquery and Popper aliases. To do that, we’ll use the Provide plugin in webpack to autoload the respective libraries / modules and have them mapped to the aliases via the app/config/webpack/environment.js file as follow:

Lets go ahead and import Bootstrap into our main webpack JavaScript file under app/javascript/packs/application.js . We’ll initiate the tooltip feature as well to demonstrate that we have bootstrap properly working:

Launch your rails application on localhost. You should now hover over the button and see a tool tip appearing on top of the button without any styling. Lets import the Bootstrap styles next.

One important thing to take note, in order to get your stylesheets working via webpack, you will need to import them into your webpack JavaScript file. That’s just how webpack works.

Lets create a new sub folder called stylesheets under app/javascript . Inside it we will create the main application.scss file to store our css library imports along with a _custom.scss file to store our custom styles. You can include all your custom css in the same application.scss file of course, I just wanted to show you an example of how you can organize custom styles in separate files should you wish to.

Restart your rails server and voila! You have a working Rails app with Bootstrap using Webpack.

Simple hello world page with Boostrap working

Including Asset Pipeline Into Webpack

Why would I want to do this? Many reasons, one of which is “I like to keep my CSS, images and font files separate from my Javascripts”

To do this, we’ll need to update config/webpacker.yml to be able to resolve assets stored in the app/assets folder.

resolved_paths: ['app/assets']

Create a home.css file under the app/assets/stylesheets folder and import that into our main webpack application.scss :

Restart your application and reload the home page. You should now see a green “Hello World” title since the home.css stylesheet is imported last which overrides the red color set in the _custom.scss stylesheet. Sweet.

Simple hello world page with Green title

So what is 'stylesheet_pack_tag' for anyways?

The official README doesn’t really explain much about it’s purpose or how to even use it properly. Basically, this tag is optional. Without it, all CSS imported into our main webpack application.js will be available inline within the JS file. But, if you want to load your stylesheets separately from the webpack generated JavaScript file, you would use this tag.

Two things must be in place to make sure this is working correctly:

  1. Make sure to name it the same as your main webpack Javascript file. If your main Javascript file is called “calendar.js” you want to make sure its written as stylesheet_pack_tag ‘calendar’
  2. Update the config/webpacker.yml file to set the extract_css to true.

FYI, under the hood, webpacker is using the mini-css-extract-plugin to compile a separate bundle for the css imported into the main webpack application.js file.

Restart your Rails app and reload the page. Peeking into the source will reveal the additional stylesheet reference. Here’s the before and after result:

Without `stylesheet_pack_tag` where all styling are inlined within the webpack generated application.js file
With ‘stylesheet_pack_tag` with a separate stylesheet bundle generated

I didn’t really realize the benefit of this until it was pointed out by a friend of mine. When the CSS is in-lined within the webpack javascript file, there seems to be a slight delay before the styles get loaded into the page on initial page load. Extracting the CSS into a separate stylesheet bundle eliminates this and makes the initial page load much smoother.


The Beauty of Using Webpack(er): Easily generate separate JS and/or CSS bundles

One of the benefits I enjoyed the most is the ability to now easily generate a separate Javascript and/or CSS bundle that can be included on only pages that requires it, without the need to load it in all the pages on our app.

Lets just say we have a calendar Javascript component that only needs to be loaded into a single page within our Rails app. Creating a separate calendar.js file within the app/javascript/packs folder will auto magically compile and generate a separate calendar bundle via Webpack. Here’s an example:

Here’s what is looks like when the calendar page is loaded via http://localhost:3000/calendar

Generating and loading only the calendar js component on a single page

Few Other Interesting Findings

Some of these are directly quoted from the official webpacker README that I think is useful to have it highlighted below:

  1. Running WEBPACKER_DEV_SERVER_HOST=0.0.0.0 ./bin/webpack-dev-server separately is optional. When you start rails server, fetching a page will automatically compile your webpack in real-time. This is why you’ll notice a longer response time when fetching a page. Essentially if you want to use live code reloading, or you have enough JavaScript that on-demand compilation is too slow, you’ll need to run ./bin/webpack-dev-server or ruby ./bin/webpack-dev-server.
  2. Run rails assets:clobber to delete all your compiled webpacks under the public/packs folder. This is useful when you simply want to reset and start a fresh webpack compilation.
  3. In regards to deployment: Webpacker hooks up a new webpacker:compile task to assets:precompile, which gets run whenever you run assets:precompile. If you are not using Sprockets, webpacker:compile is automatically aliased to assets:precompile. Similar to sprockets both rake tasks will compile packs in production mode but will use RAILS_ENV to load configuration from config/webpacker.yml (if available).

A working example of the code snippets mentioned in this article can be found here: https://github.com/AdrianTeh/HelloWorldWebpacker

This article serves as a reference for myself and hopefully others in getting started with Webpack(er) in Rails. Please share under the comments section any other useful findings around Webpack and/or Webpacker in Rails.

Adrian Teh

Written by

Entrepreneur. Product Manager. Ruby Engineer. Co-founder of Evercondo.com (Acquired). Currently Application Architect at Frontsteps.com