Install Bootstrap 4 on a Rails 6 App with Webpacker

Posted on July 30, 2020 - 4 Minute Read

I know many existing tutorials explain how to install Bootstrap 4 on a Rails 6 application with Webpacker (like the GoRails example). However, I wanted to create this tutorial to highlight a few gotchas, as well as highlight why and how I made some of my choices.

  1. rails new rails-bootstrap
  2. yarn add bootstrap jquery popper.js
  3. Add jQuery and Popper.js plugins. These are required by Bootstrap.

This step was always so cryptic to me. I would just blindly copy and paste what I saw on other tutorials, but I wanted to know how people knew to even do this.

I found this example in the Webpacker docs, so decided to use it knowing it was in the official documentation.

// config/webpack/environment.js
const { environment } = require('@rails/webpacker')
const webpack = require('webpack')

environment.plugins.prepend(
    'Provide',
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      jquery: 'jquery',
      'window.jQuery': 'jquery',
      Popper: ['popper.js', 'default'],
    })
)

module.exports = environment

Another big problem I ran into was how to correctly import Bootstrap's styles.

I initially created app/javascript/packs/application.scss and imported the styles in that file. However, that seemed to break my build in a way that made it so app/javascript/packs/application.js never compiled.

Next, I renamed app/assets/stylesheets/application.css to app/assets/stylesheets/application.scss, and imported the styles into that file. That worked, but it meant that the Asset Pipeline was responsible for my styles. This isn't necessarily a bad thing, but I wanted Webpacker to be responsible for all of my front-end code.

Also, by using a .scss file, you can easily override Bootstrap's default variales

  1. mkdir app/javascript/
  2. touch app/javascript/stylesheets/application.scss
  3. Import Bootstrap Styles
// app/javascript/stylesheets/application.scss
@import '~bootstrap/scss/bootstrap'
  1. Import Bootstrap, load styles, and optionally load Tooltips and Popovers everywhere.
// app/javascript/packs/application.js
...
require("bootstrap")
import "../stylesheets/application";
document.addEventListener("turbolinks:load", function() {
    $(function () {
        $('[data-toggle="tooltip"]').tooltip()
        $('[data-toggle="popover"]').popover()
    })
})

Webpacker emits css files only if extract_css is set to true in webpacker.yml otherwise stylesheet_pack_tag returns nil.

When I was running through these steps, I found it strange that I didn't need to add a stylesheet_pack_tag as I had seen in other tutorials. I realized that this is because I was in development.

If you change extract_css: false to extract_css: true under the default: block in config/webpacker.yml and then restart your server, you'll notice that the styles no longer load.

  1. To fix this, simply add the stylesheet_pack_tag and restart the server. After ensuring the styles haves loaded set extract_css: true back to extract_css: false under the default: block in config/webpacker.yml. You might need to run rails webpacker:clobber after making that change.
<%# app/views/layouts/application.html.erb %>
<!DOCTYPE html>
<html>
  <head>
    <title>RailsBootstrap4Integration</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %>    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <div class="container">
      <%= yield %>
    </div>
  </body>
</html>
  1. Finally, add the responsive meta tag
<%# app/views/layouts/application.html.erb %>
<!DOCTYPE html>
<html>
  <head>
    <title>RailsBootstrap4Integration</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <div class="container">
      <%= yield %>
    </div>
  </body>
</html>
Categorized In: