'Getting Jquery and Bootstrap to work with Rails 6

I am a new to rails and struggling to get Jquery and Bootstrap to work with Rails 6. I think it has something to do with switching the app from rails 5 to rails 6 and using webpacker to load Jquery rather than loading it as a gem. I have gone through the instructions for this however it still doesn't seem to work properly. Someone helped me with a more specific problem and got me to paste this into the view which then seemed to make it work:

<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

However, this feels like a workaround and I want Jquery available in all views. Below is a copy of /javascript/packs/application.js :

require("jquery")
require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
require("bootstrap/dist/js/bootstrap")

import '../stylesheets/application'
import './bootstrap_custom.js'


//= require jquery3
//= require popper
//= require bootstrap-sprockets

and /config/webpack/environment.js:

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

const webpack = require('webpack')
environment.plugins.prepend('Provide',
  new webpack.ProvidePlugin({
    $: 'jquery/src/jquery',
    jQuery: 'jquery/src/jquery'
  })
)

module.exports = environment

I don't get the difference between Require("...") and //= require ...? is the //= a legacy notation that should be converted to Require("...")?

Also do I need both require("jquery") and //= require jquery3? I assume not. If so which one should I delete?

In /apps/views/layouts/Application.html.erb I have the following contained within the header:

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


Solution 1:[1]

I struggled with this for days, so hopefully my experience will help you :)

First of all, you will be loading jQuery and Bootstrap as a webpack module, so you don't need any of this:

<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

Instead, you want to install the modules using yarn on your prompt:

$ yarn add jquery bootstrap

After that, you should import jQuery into your project. The safest way to do it is editing your /config/webpack/environment.js, much in the way you did:

...
environment.plugins.append('Provide',
  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery'
  })
...

Now, since you're importing jQuery as a webpack global plugin (that is, available throughout all your views, and even from other modules), then you should not import it again in your app/javascript/packs/application.js, as this is a known cause for unexpected behavior. In that file you do want, however, to import Bootstrap. So it should look like this:

# app/javascript/packs/application.js

import 'bootstrap';
import '../stylesheets/application'

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")

Note that I'm using the import 'module' syntax, which is preferred over the older require("") syntax. And you definitely don't want to use any of these:

//= require jquery3
//= require popper
//= require bootstrap-sprockets

They're Sprockets (asset pipeline) directives with no use in Webpack-land.

So, by now you have both jQuery and Bootstrap js imported into your project, but you're still missing Bootstrap stylesheet. In order to import it, just include this in your application.scss (which I assume you're using given you're importing it with import '../stylesheets/application'):

# application.scss

@import "~bootstrap/scss/bootstrap";

And there you are, jQuery and Bootstrap imported into your project. Hope it helps! If you're new to Webpack (as I am) you will encounter lots of obstacles before you can fully use it, since there are a lot of differences with the asset pipeline. After several days (if not weeks) of research I've managed to deal with most of them, so feel free to look into my question history to see if you find some useful answers.

Additional info:

  1. You didn't specify it, but if you're going to use all of Bootstrap's js functions, you'll also need Popper.js in your project. In order to install just run $ yarn add popper.js in your command line, and edit your /config/webpack/environment.js so it looks like this:
environment.plugins.append('Provide',
  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    Popper: ['popper.js', 'default']
  })
)
  1. Lastly, I tried to answer your question in the most concise way I could, but if you're still struggling, you may want to check some more step-by-step tutorials, like this: https://medium.com/@adrian_teh/ruby-on-rails-6-with-webpacker-and-bootstrap-step-by-step-guide-41b52ef4081f. Also, I've put together a barebones Rails 6 core app with jQuery, Bootstrap and popper.js installed, so feel free to clone into the repo, here: https://github.com/Dijkie85/rails6core.git.

Good luck!

Solution 2:[2]

I use in Rails 6:

#/Gemfile
gem "bootstrap", "~> 5.1"
gem "jquery-rails", "~> 4.4"

#/app/javascript/packs/application.js
...
import 'bootstrap';

and

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

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

module.exports = environment

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dijkie85
Solution 2 FVVID