Skip to content

Instantly share code, notes, and snippets.

@bazzel
Last active May 26, 2021 04:20
Show Gist options
  • Star 34 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save bazzel/2c64e2e5804077f9a61938a93ed54823 to your computer and use it in GitHub Desktop.
Save bazzel/2c64e2e5804077f9a61938a93ed54823 to your computer and use it in GitHub Desktop.
Rails 6 and Bootstrap 4

This blogpost shows how to setup Rails 6 with Bootstrap 4.

This snippet shows a somehow different and less customized approach.

$ rails new rails6-bootstrap4
$ bundle --binstubs
$ yarn add bootstrap jquery popper.js expose-loader
// config/webpack/environment.js

// Make $ available on the window object
// for SJR views and jQuery plugins
// that may expect `$` to be globally available.
environment.loaders.append('expose', {
  test: require.resolve('jquery'),
  use: [
    {
      loader: 'expose-loader',
      options: 'jQuery',
    },
    {
      loader: 'expose-loader',
      options: '$',
    },
  ],
});
// app/javascript/packs/application.js

import $ from 'jquery';
import 'bootstrap/dist/js/bootstrap';

$(document).on('turbolinks:load', function() {
  $('body').tooltip({
    selector: '[data-toggle="tooltip"]',
    container: 'body',
  });

  $('body').popover({
    selector: '[data-toggle="popover"]',
    container: 'body',
    html: true,
    trigger: 'hover',
  });
});
// app/javascript/packs/styles.scss

@import '~bootstrap/scss/bootstrap';
# config/webpacker.yml

...
extract_css: true
# app/views/layouts/application.html.erb

<%= stylesheet_pack_tag 'styles', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
...
<body>
  <div class='container'>
    <%= yield %>
  </div>
</body>
$ bin/webpack-dev-server
$ bin/rails s

I recently found this article that seems to do the same, but a bit more explanation. Worth reading!

@osheroff
Copy link

import '~bootstrap/scss/bootstrap';

should read

@import '~bootstrap/scss/bootstrap';

instead. Thanks for the guide!

@bazzel
Copy link
Author

bazzel commented Oct 16, 2019

@osheroff good catch. Thx.

@maxgronlund
Copy link

Thanks for the guide.

I had to rename 'style.css' to 'style.scss'

@a-ta-ta
Copy link

a-ta-ta commented Nov 8, 2019

Error: File to import not found or unreadable: ~bootstrap/scss/bootstrap.
on line 16:1 of app/assets/stylesheets/application.scss

@import '~bootstrap/scss/bootstrap';

@bazzel
Copy link
Author

bazzel commented Nov 9, 2019

@a-ta-ta You should put this line in app/javascript/packs/styles.scss, not in app/assets/stylesheets/application.scss.

@renatopanda
Copy link

Not sure if it's the best solution but I was getting Uncaught ReferenceError: $ is not defined when trying to use $(...) in a view and ended up solving it by setting $ as global (together with jQuery right after importing:

# app/javascript/packs/application.js
import $ from 'jquery';
global.$ = $;
global.jQuery = $;
...

@bb
Copy link

bb commented Jan 5, 2020

@renatopanda: you may need to configure expose-loader for exposing globals automatically.

@bazzel
Copy link
Author

bazzel commented Jan 6, 2020

@renatopanda: I realized I forgot the snippet to configure the expose-loader code needed to make jQuery globally available. I've updated the gist.

@la-ruby
Copy link

la-ruby commented Feb 1, 2020

I can script it with bash 👍

@belgoros
Copy link

belgoros commented Feb 21, 2020

Putting a stylesheet file in app/javascript/... folder looks a little bit weird for me... even if we consider that webpack is a JS library...

@dodafish
Copy link

I think app/javascript/packs/application.js is missing the line import './styles';

I had to add this. Otherwise, there was no CSS added to the page.

@bazzel
Copy link
Author

bazzel commented Mar 31, 2020

@FrischerHering For me it was sufficient to create app/javascript/packs/styles.scss and use it in the layout file by calling stylesheet_pack_tag 'styles'.

@dennym
Copy link

dennym commented Apr 1, 2020

Just out of curiosity... from where would you serve custom css with this setup? Also from app/javascript/packs?

@bazzel
Copy link
Author

bazzel commented Apr 1, 2020

(updated comment)

@dennym I have several SCSS-file in the packs folder (can be stored in subfolders of course). Given you have 1 'main' CSS file styles.scss you can import other files in here as you would normally do:

// app/javascript/packs/styles.scss
@import 'base'
@import 'modules'

// app/javascript/packs/_base.scss
body {
  ...
}

// app/javascript/packs/_modules.scss
@import 'modules/navbar'
@import 'modules/search'
...

Then in my layout file I can use stylesheet_pack_tag 'styles'.

@dennym
Copy link

dennym commented Apr 1, 2020

@bazzel Yeah thats what I thought. It just feels a bit off context when still having the app/assets/stylesheets of rails. Basically its decision between what is served with sprockets (which is still serving everything in app/assets I guess) and webpack. Where would anyone stop... images / fonts?

@viktorianer
Copy link

What about Popper?

I found following guide really helpful and it also takes into account to import Popper for Bootstrap 4.
https://www.timdisab.com/installing-bootstrap-4-on-rails-6/

PS: thx for nice and short installation guide @bazzel

@radubogdan
Copy link

radubogdan commented Aug 25, 2020

Thanks for sharing. I have few considerations @bazzel

  1. looks like bootstrap is including jquery, I guess it will work only by installing it with yarn.
  2. if expose must be used, they changed the API so new code should be something like:
environment.loaders.append('expose', {
  test: require.resolve('jquery'),
  loader: 'expose-loader',
  options: {
    exposes: ['$', 'jQuery'],
  },
});

Regards

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment