Integrate Rails 6 and Bootstrap 4 Using Webpacker. Inspired by GoRails.
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.
rails new rails-bootstrap
yarn add bootstrap jquery popper.js
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
mkdir app/javascript/
touch app/javascript/stylesheets/application.scss
// app/javascript/stylesheets/application.scss
@import '~bootstrap/scss/bootstrap'
// 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 totrue
inwebpacker.yml
otherwisestylesheet_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.
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>
<%# 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>