Bootstrap in Rails 6

Since the release of Rails 6, there have been some changes made to default tools for asset compilation. In specific sprockets no longer processes JavaScript and instead uses  webpack as the default configuration. Following the philosophy of "convention over configuration", the current "Rails way" is understood to be: use webpack for JavaScript and sprockets for everything else.

Minor changes to asset compilation

This does change how common CSS frameworks like Bootstrap are added to a Rails project. For example, the twbs/bootstrap-ruby gem is no longer as helpful because sprockets is not used for compiling assets. So we need another way.


  1. Install Bootstrap via yarn
# Bootstrap 5
yarn add  bootstrap@5.0.0 jquery @poperjs/core

Since jquery was removed from Rails as a dependancy approx. around Rails 5 in favour of rails-ujs, we will need re-add it to use Bootstrap. We use yarn here because we will packaging these JavaScript dependencies using webpack.

2. Update config/webpack/environment.js

const { environment } = require('@rails/webpacker')

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

module.exports = environment

Now that webpack is processing our JavaScript, we need to make it aware of the libraries installed via yarn. We can do this via the ProvidePlugin to automagically, "load modules instead of having to import or require them everywhere."

3. Update app/javascript/packs/application.js

// Other impots

import 'bootstrap'

Finally, we need to directly import our bootstrap library in the main application.js JavaScript file.

4. All Webpack Method

The Rails community is somewhat divided on whether to use webpack for everything or use the combination of sprockets / webpack. For those whom sprockets has caused heart burn in the past the all webpack method may be much more desirable

4a. Co-locating CSS and JavaScript:

You can co-locate your CSS, and images by putting them in the same directory. Add a stylesheets folder with application.scss to your javascript/packs

# app/javascript/packs/stylesheets/application.scss
@import "~bootstrap/scss/bootstrap"; // never forget the semicolon at the end
@import "./_custom";

# app/javascript/packs/stylesheets/_custom.scss
h1 { 
  color: red;

4b. Including Asset Pipeline in Webpack

This avenue lets you keep your CSS, images and styling separate from your javascript.

Update the config/webpack.yml to include the app/assets directory in resolved_paths

resolved_paths: ['app/assets']

You will then need to manually import your style sheets into your app/javascript/packs/stylesheets/application.scss

// app/assets/stylesheets/home.css
h1 { color: green; }

// app/javascript/stylesheets/application.scss
@import "~bootstrap/scss/bootstrap"; // never forget the semicolon
@import "./_custom";
@import "stylesheets/home";

4. Webpack & Sprockets

If you want to stay course and continue the Basecamp Rails way the current convention is to continue using sprockets for processing stylesheets and images.

  1. Add to app/assets/stylesheets/application.css:

// if .scss
@import "bootstrap/scss/bootstrap";

// or if .css

*= require bootstrap/scss/bootstrap

To add Bootstrap you need to import the bootstrap library via scss imports or a sprockets require directive in. Be sure to add gem 'bootstrap', '~> 5.0.0' to your project.

That should be it - have fun bootstrapping your next project!