In this tutorial I’ll be explaining how to install Bootstrap 5 with Ruby on Rails 6 using Webpack. There are some great tutorials out there for Bootstrap 4, but Bootstrap 5 requires some subtle but important changes to get working properly. Let’s begin.
Bootstrap 5.1
Rails 6.0.4
Webpack
4.46.0
)Using your favorite package manager, install the following packages:
Terminal
yarn add bootstrap jquery @popperjs/core
# Or
npm install bootstrap jquery @popperjs/core
The Popper team has released Popper 2, and with it a new package name. Many old tutorials reference popper.js
, which won't work with Bootstrap 5. The new one should be @popperjs/core
to work properly with Bootstrap 5.
Navigate to the following file and update it with the following code:
config/webpack/environment.js
const { environment } = require('@rails/webpacker')
// Add the following lines
const webpack = require("webpack")
environment.plugins.append("Provide", new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
Popper: ['popper.js', 'default'] // Not a typo, we're still using popper.js here
}))
// End new addition
module.exports = environment
The code above allows (or better yet, tells) Webpack to automatically load those modules instead of having to import
or require
them everywhere. So when we reference them in our source Javascript code, they'll be available. This is important for Bootstrap because it is expecting those modules to be accessible.
You can read more about the Webpack ProvidePlugin here.
Next, we need to setup Webpack to know where our Bootstrap CSS is located. Create a new folder called stylesheets
in /app/javascript
. Then create a file called application.scss
within that new folder. Update it with the following line:
/app/javascript/stylesheets/application.scss
@import "~bootstrap/scss/bootstrap";
Finally, we need to update our application.js
file to load Bootstrap:
/app/javascript/packs/application.js
/* You may have a few 'require' lines above this already */
require("@popperjs/core")
import "bootstrap"
// Import the specific modules you may need (Modal, Alert, etc)
import { Tooltip, Popover } from "bootstrap"
// The stylesheet location we created earlier
require("../stylesheets/application.scss")
// If you're using Turbolinks. Otherwise simply use: jQuery(function () {
document.addEventListener("turbolinks:load", () => {
// Both of these are from the Bootstrap 5 docs
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
var tooltipList = tooltipTriggerList.map(function(tooltipTriggerEl) {
return new Tooltip(tooltipTriggerEl)
})
var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
var popoverList = popoverTriggerList.map(function(popoverTriggerEl) {
return new Popover(popoverTriggerEl)
})
})
You should be set! Let’s test to ensure everything is loading and working right.
If you don’t have any views (aka pages) yet, quickly create one using the following commands/code. Otherwise, skip to Part 2.
Terminal
rails g controller home index
And update your routes.rb
file:
Terminal
Rails.application.routes.draw do
root to: 'home#index'
end
Then start your server:
Terminal
rails s
In your application.html.erb
, add the following Bootstrap 5 code snippets to test:
/app/views/layouts/application.html.erb
<!-- Navbar -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Dropdown
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
</li>
</ul>
<form class="d-flex">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</nav>
<!-- Tooltips -->
<button type="button" class="btn btn-primary" data-bs-toggle="tooltip" data-bs-placement="top" title="Tooltip on top">
Tooltip on top
</button>
<!-- Popover -->
<button type="button" class="btn btn-secondary" data-bs-container="body" data-bs-toggle="popover" data-bs-placement="top" data-bs-content="Top popover">
Popover on top
</button>
Then navigate to localhost:3000, and you should see everything is working properly.
Happy development! 🎉