How to install bootstrap 4.3 on a Rails 6 app using Webpack

And learn how to serve assets through Webpack in the process

Guilherme Pejon
Mar 8, 2019 · 5 min read

If you are new to this world of having Webpack inside Rails, and have no idea how to manage dependencies through it, don’t worry, you came to the right place.

While building a new project I decided to try Rails 6.0.0.beta2 and all its glorious new features. One problem that I stumbled upon was how to install css and js packages through Webpacker, instead of the usual process that I was accustomed to, using a gem.

In this tutorial I’ll guide you through the process of installing bootstrap on a brand new Rails 6.0.0.beta2 project, but you can still use pretty much the same steps with an existing Rails ≥ 5.2 project.

1. Setup

Let’s start by creating a brand new app.

rails new my_awesome_app

Now we need to tell our app to serve our css and js assets through Webpack. Let’s start by creating a new css manifest inside our app/javascript folder. We will use this file to import all our css from now on.

$ mkdir app/javascript/stylesheets
$ touch app/javascript/stylesheets/application.scss

Note: In an existing app, you’ll have to import all your current css to the folder we created above, and import them through the newly created manifest file.

Now, let’s import the file we just created in our js manifest.

# app/javascript/packs/application.jsimport '../stylesheets/application'

The last step is to tell Rails to start using Webpack. To do that, open the application.html.erb file and make the following change to it.

# app/views/layouts/application.html.erb<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>

Here we replaced the stylesheet_link_tag and javascript_include_tag helpers with stylesheet_pack_tag and javascript_pack_tag, respectively. If we run our app now, we should be able to see these assets served by Webpack.

Webpacker will now watch for any change in our assets, and compiles them when we refresh the page. This may cause our page to load slightly slower in development, but thankfully there’s a way around it.

2. Setup Foreman (Optional)

If you, like me, are not comfortable with losing those precious extra milliseconds waiting for your page to load every time you make a change to your assets, don’t worry, we can use Foreman with webpacker-dev-server to "bring back" real-time compilation.

If you’ve never used foreman before, you can read more about it here. Let’s start by installing it, like any other gem.

gem install foreman

Next, let’s create a Procfile.dev file in the root of our app, and add the following content to it.

Note: I’m assuming you are using Puma as your web server, since it’s the default for new Rails apps.

# Procfile.devweb: bundle exec puma -C config/puma.rb
webpacker: ./bin/webpack-dev-server

All we have to do now is start Foreman, and it will create the two processes we declared above in a single terminal window.

foreman start -f Procfile.dev

There we go! Now our assets will compile automatically when we make any changes to them, and we won’t have to waste those precious extra miliseconds waiting for our page to load after every change.

3. Add your package

Finally, let’s install bootstrap and its required dependencies, jquery and popper.

yarn add bootstrap@4.3.1 jquery popper.js

We also need to add them as plugins, so let's go ahead and add these lines to our config/webpack/environment.js file.

# config/webpack/environment.js...const webpack = require('webpack')
environment.plugins.append(
'Provide',
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
Popper: ['popper.js', 'default']
})
)
...

You might be wondering, how do I know what to add in my application.js and application.scss files? That's a great question, and since you are reading this, you won't have to waste your time trying to google it and getting nowhere, like I did.

Open your node_modules folder and voilà!

We now have two choices. We can either add the entire bootstrap framework javascript and css files from the node_modules/bootstrap/dist folder, or we can hand-pick the resources we are going to use in our app.

I'm going to show you how to do the second option since it allows you to have more control over the installation process. Create a new file in your app/javascript/packs folder called bootstrap_custom.js with the following content.

# app/javascript/packs/bootstrap_custom.jsimport 'bootstrap/js/dist/alert'
import 'bootstrap/js/dist/button'
import 'bootstrap/js/dist/carousel'
import 'bootstrap/js/dist/collapse'
import 'bootstrap/js/dist/dropdown'
import 'bootstrap/js/dist/index'
import 'bootstrap/js/dist/modal'
import 'bootstrap/js/dist/popover'
import 'bootstrap/js/dist/scrollspy'
import 'bootstrap/js/dist/tab'
import 'bootstrap/js/dist/toast'
import 'bootstrap/js/dist/tooltip'
import 'bootstrap/js/dist/util'

And link it in your app/javascript/packs/application.js file.

# app/javascript/packs/application.jsimport './bootstrap_custom.js'

Now you can adjust app/javascript/packs/bootstrap_custom.js to fit your needs, by commenting out the imports you don't need.

Let's do the same thing for our css.

# app/javascript/stylesheets/application.scss@import './bootstrap_custom.scss';

And create the file bootstrap_custom.scss inside our app/javascript/stylesheets folder.

# app/javascript/stylesheets/bootstrap_custom.scss@import '~bootstrap/scss/_functions.scss';
@import '~bootstrap/scss/_variables.scss';
@import '~bootstrap/scss/_mixins.scss';
@import '~bootstrap/scss/_root.scss';
@import '~bootstrap/scss/_reboot.scss';
@import '~bootstrap/scss/_type.scss';
@import '~bootstrap/scss/_alert.scss';
@import '~bootstrap/scss/_badge';
@import '~bootstrap/scss/_breadcrumb';
@import '~bootstrap/scss/_button-group';
@import '~bootstrap/scss/_buttons';
@import '~bootstrap/scss/_buttons.scss';
@import '~bootstrap/scss/_card.scss';
@import '~bootstrap/scss/_carousel.scss';
@import '~bootstrap/scss/_close.scss';
@import '~bootstrap/scss/_code.scss';
@import '~bootstrap/scss/_custom-forms.scss';
@import '~bootstrap/scss/_dropdown.scss';
@import '~bootstrap/scss/_forms.scss';
@import '~bootstrap/scss/_grid.scss';
@import '~bootstrap/scss/_images.scss';
@import '~bootstrap/scss/_input-group.scss';
@import '~bootstrap/scss/_jumbotron.scss';
@import '~bootstrap/scss/_list-group.scss';
@import '~bootstrap/scss/_media.scss';
@import '~bootstrap/scss/_modal.scss';
@import '~bootstrap/scss/_nav.scss';
@import '~bootstrap/scss/_navbar.scss';
@import '~bootstrap/scss/_pagination.scss';
@import '~bootstrap/scss/_popover.scss';
@import '~bootstrap/scss/_print.scss';
@import '~bootstrap/scss/_progress.scss';
@import '~bootstrap/scss/_spinners.scss';
@import '~bootstrap/scss/_tables.scss';
@import '~bootstrap/scss/_toasts.scss';
@import '~bootstrap/scss/_tooltip.scss';
@import '~bootstrap/scss/_transitions.scss';
@import '~bootstrap/scss/_utilities.scss';

And you can do the same thing we did before, you can choose which parts of their css you want to add to your project.

Note: Do not change the order of the scss imports (at least the top ones) or you'll get all sorts of errors.

Also, note that we didn’t had to add the node_modules part of the path to the import because Webpack already knows where to look for them.

And that’s it! Bask in the glory of your newly installed package and start spreading those col and row everywhere!

Guilherme Pejon

Written by

Passionate about web development, open source projects and coding puzzles.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade