Migrating Rails from Asset Pipeline to Webpacker: Uncaught ReferenceError: $ is not defined in rails-ujs.js
Asked Answered
M

3

5

I am migrating from using the asset pipeline to webpacker in Rails 5.2. My AJAX responses are all causing Uncaught ReferenceError: $ is not defined in rails-ujs.js errors in the browser console.

I have setup my webpacker environment to include jquery.

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

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

module.exports = environment;

I have imported rails-ujs and turbolinks in my ../packs/application.js

import Rails from 'rails-ujs'
import 'activestorage'
import 'bootstrap'
...
import Turbolinks from "turbolinks"

Rails.start();
Turbolinks.start();

// Import application specific stuff
import 'application/javascripts'

I then try to add a class when the request is completed. similar to what is shown in the rails guides https://guides.rubyonrails.org/working_with_javascript_in_rails.html#server-side-concerns

My show.js.erb file looks like this

$("#result").addClass("active")

I get an error

Uncaught ReferenceError: $ is not defined
    at <anonymous>:1:1
    at processResponse (rails-ujs.js:282)
    at rails-ujs.js:195
    at XMLHttpRequest.xhr.onreadystatechange (rails-ujs.js:263)
Mantra answered 7/5, 2019 at 11:58 Comment(0)
M
15

In the meantime, I figured out what I had done wrong. I needed to configure an alias. I found the solution in the docs https://github.com/rails/webpacker/blob/master/docs/webpack.md#configuration

Adding environment.config.set('resolve.alias', {jquery: 'jquery/src/jquery'}); to my /config/webpacker/environment.js did the trick.

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

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

environment.config.set('resolve.alias', {jquery: 'jquery/src/jquery'});

module.exports = environment;
Mantra answered 7/5, 2019 at 14:10 Comment(0)
H
2

Try in app/javascript/packs/application.js:

// jquery
import $ from 'jquery';
global.$ = $;
global.jQuery = $;

Hilaria answered 15/12, 2019 at 15:27 Comment(1)
Try to explain above code in your post, it will helps other to understand in detail.Denumerable
A
0

Thanks for sharing this. Worked like a charm. To add to your answer, there is a folder named node_modules. Inside that you have jquery/src/jquery.js file. That file is what is being referenced by the line of code above. I am new to JS so pardon my ignorance. What I understand is that this file returns a function called jQuery. When we write

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

We mess things up. What this basically means is $ = 'jquery' which is not defined at the moment. Next I define jQuery = 'jquery'. So jquery is still undefined. So we have to define an alias by adding that line.

But if I write

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

Then I don't need to add the code for defining that alias. Both your solution and this worked for me. As I said I am very new to JS and I cannot say if this is the right solution.

Acrostic answered 4/8, 2019 at 6:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.