10

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' %>

2 Answers 2

28

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!

Sign up to request clarification or add additional context in comments.

13 Comments

Thank you so much this is just the level of info I am looking for. I will try tonight and let you know how I get on.
Your answer was very comprehensive and easy to follow, however, this didn't seem to work. The functionality where it breaks is in calling a bootstrap modal. The modal loads and the action is executed but I can't get the modal to close without adding the three lines of <script src ...> to the view. Would this seem to hint at some of the Jquery functionality working but not others? I have read somewhere about it being the order in which Jquery and then Bootstrap is called..
So I can repeat the issue I am having by swapping the order of <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js..." and '<script src="stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/…...' So my guess is that it is something to do with the order in which these are loading...?
Interestingly the answer here helped - link. As I am not quite sure what this is doing I am not sure if this is the best solution or a workaround... Any thoughts much appreciated...
I'm glad you made it work! I checked the link you provided, and indeed that's how I first managed to get jQuery to work in a project. However, maybe --like me-- you'll find out later that, with that method, you won't be able to call jQuery from additional plugins you may want to use in the future, so it's only a temporary solution. Should that happen, I encourage you to call jQuery from /config/webpack/environment.js, which exposes jQuery to every part of your project. Make sure you're using the syntax I provided ($: 'jquery', jQuery: 'jquery'), and not the one you first posted.
|
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.