webpack/webpack

Webpack gives $ is not defined or jQuery is not defined error in console

pfftdammitchris opened this issue Β· 39 comments

Do you want to request a feature or report a bug?

What is the current behavior?

If the current behavior is a bug, please provide the steps to reproduce.

What is the expected behavior?

If this is a feature request, what is motivation or use case for changing the behavior?

Please mention other relevant information such as the browser version, Node.js version, webpack version and Operating System.

Hey guys I tried everything and I am ready to burst out in shame and I am tired of getting this same error over and over for the past 4 hours. I'm just going to copy and paste the console so we can see how bad it is:

    Uncaught Error: Bootstrap's JavaScript requires jQuery
        at bootstrap.min.js:6
    (anonymous) @ bootstrap.min.js:6
    etw.js:4 Fri Feb 10 2017
    etw.js:125 Uncaught ReferenceError: $ is not defined
        at LFDTrack (etw.js:125)
        at Object.LFD_Search (etw.js:244)
        at User.lfd_search (etw.js:25)
        at etw.js:250
    LFDTrack @ etw.js:125
    LFD_Search @ etw.js:244
    User.lfd_search @ etw.js:25
    (anonymous) @ etw.js:250
    jBox.min.js:2 Uncaught ReferenceError: jQuery is not defined
        at jBox.min.js:2
    (anonymous) @ jBox.min.js:2
    jquery.datetimepicker.full.min.js:1Uncaught ReferenceError: jQuery is not defined
        at jquery.datetimepicker.full.min.js:1
        at jquery.datetimepicker.full.min.js:1
    (anonymous) @ jquery.datetimepicker.full.min.js:1
    (anonymous) @ jquery.datetimepicker.full.min.js:1
    owl.carousel.js:1517 Uncaught ReferenceError: jQuery is not defined
        at owl.carousel.js:1517
    (anonymous) @ owl.carousel.js:1517
    (index):539 Uncaught ReferenceError: $ is not defined
        at (index):539
    (anonymous) @ (index):539
    featherlight.min.js:8 Uncaught ReferenceError: jQuery is not defined
        at featherlight.min.js:8
    (anonymous) @ featherlight.min.js:8
    jquery.datetimepicker.full.min.js:1 Uncaught ReferenceError: jQuery is not defined
        at jquery.datetimepicker.full.min.js:1
        at jquery.datetimepicker.full.min.js:1
    (anonymous) @ jquery.datetimepicker.full.min.js:1
    (anonymous) @ jquery.datetimepicker.full.min.js:1
    pagecrossfade-min.js:1 Uncaught ReferenceError: jQuery is not defined
        at pagecrossfade-min.js:1

Here is my main.js file, the entry:

    "use strict";
    
    import $ from 'jquery';
    import jQuery from 'jquery';
    window.$ = jQuery;
    import moment from 'moment';
    import _ from 'lodash';
    import math from 'mathjs';
    //import jBox from 'jbox';

And here is my webpack.config.js
I tried switchign everything around. a.k.a taking out the loaders part and leaving the plugins part there, or taking out the imports in the main.js and leaving only the stuff in the webpack.config.js for jquery, etc. Nothing works. I feel like I am the only person in the web who still has this error because everyone else has gotten it fixed so I have no where to look on google search anymore.(p.s. I dont know if this does anything but the datetime picker and other scripts in the console are script tags pointing to cdn's in the html file)

    const path = require('path');
    const webpack = require('webpack');

    module.exports = {
        entry: './main.js',
        output: { path: __dirname, filename: 'bundle.js' },
        watch: true,
        plugins: [
            new webpack.ProvidePlugin({
                $: "jquery",
                jQuery: "jquery",
                "window.jQuery": "jquery"
            })
        ],
        module: {
            loaders: [
                {
                    test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
                    loader: "imports?this=>window"
                },
                {
                    test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
                    loader: "imports?define=>false"
                }
        ]
        }
    }

I dont know if this does anything but the datetime picker and other scripts in the console are script tags pointing to cdn's in the html file

@pfftdammitchris Externals

webpack.config.js

externals: {
  jquery: 'jQuery'
}

Is the console output from devTools or Terminal ?
Is the bundle referenced after the CDN <script>'s (JQuery Plugins)

These questions are also better suited for StackOverflow πŸ˜›

edit: still Doesn't work even when I re-edited to fit that criteria and added in the externals part

I don't see how you are using Bootstrap (no import?), but if it's loaded through a script tag, expose-loader would work.

Note that support questions should go to Stack Overflow as per instructions.

Still Doesn't work even when I re-edited to fit that criteria and added in the externals part

yeah thought so tbh πŸ˜› , it's not enough information to fix it properly

index.html

  <script src="cdn/jquery.min.js"></script>
  <script src="cdn/jquery-plugin.min.js"></script>
  ...
  <script src="cdn/bootstrap.min.js"></script>
  <script src="bundle.js"></script> // Logic only with externals

The question is why webpack then , you don't really need it if most of the deps are referenced via a CDN anyways. Otherwise

index.html

  <script src="index.bundle.js"></script> // Libs + Logic

index.js

import $ from 'jquery'
import boostrap from 'bootstrap'

import plugin from 'jquery-plugin'
...

$()...
ptflp commented

Just use like this

import $ from 'jquery';
window.jQuery = $;
window.$ = $;

or add to webpack

new webpack.ProvidePlugin({
  $: 'jquery',
  jQuery: 'jquery'
})

anyone finding this that is having this issue while using angular cli this worked for me.
Step 1)
Import JQuery one time, across the project .
β—‹ Open .angular-cli.json
β—‹ Replace or add the jquery script to the scripts section with the following.
"scripts": [ "../node_modules/jquery/dist/jquery.js"],
Step 2)
Add declaration in the typings file
Open typings.d.ts
β€’ Declare jQuery
declare var jQuery: any;

@ptflp 's solution works for me..

So does bootstrap not allow you to include scripts the old way anymore with regular script tags?

So everything in my webpack chunk functions as expected, however, I wasn't able to access jQuery/$ in the JavaScript console until I followed @ptflp 's advice above and added this to my app.js:

import $ from 'jquery';
window.jQuery = $;
window.$ = $;

How come the script being loaded in my webpage doesn't expose jQuery/$? (i.e. why do I need line 2 & 3 above?)

dlo commented

I came here to ask what @paulcalabro is asking. This is confusing for a newbie to webpack.

Bump for a bit of an explanation? I thought it might have been because jQuery wasn’t being loaded until later...
I’ve seen the workarounds but i’d like to understand in case I come across this again

I have this in webpack.config.js and I can't do any of the the normal troubleshooting using $("#selector") in chrome dev tools console:

plugins: [
   new UglifyJsPlugin(),
   new webpack.ProvidePlugin({
        $: "./jquery-3.3.1",
        jQuery: "./jquery-3.3.1"
    })
]

I get errors like this:

Uncaught TypeError: $(...).removeClass is not a function

@paulcalabro @nathanpurcell @dlo

For every module webpack imports it wraps it in a function and it passes it a custom module and exports object.

Crank open your webpack output and the import for jQuery will look something like this:

function(module, exports){
 //jQuery library
}

So why do we need to assign the library to a variable and then expose it on window? I thought jQuery does that for us?

It does, but only if module.exports is undefined. If module.exports is defined -- which it will be with our webpack import -- module.exports = jQuery.

Unfortunately, to discover this you need to dig into the jquery library(however, the code we're interested in is conveniently at the top and bottom of the file).

if (typeof module === "object" && typeof module.exports === "object") {
    module.exports = global.document ?
        factory(global, true) : // THIS WILL BE CALLED IN OUR WEBPACK OUTPUT
        function(w) {
            if (!w.document) {
                throw new Error("jQuery requires a window with a document");
            }
            return factory(w);
        };
} else {
    factory(global); // THIS WOULD NORMALLY BE CALLED IN A BROWSER ENVIROMENT
}

and down the very bottom of the library:

// as noGlobal is true, this won't be called
if ( !noGlobal ) {
    window.jQuery = window.$ = jQuery;
}

new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
})

alone is not working.

@cgountanis , not sure if this can help, but this is relevant section in my webpack config:

plugins: [
new webpack.ProvidePlugin({
            $: "jquery",  
            jQuery: "jquery" 
        })
],

and i installed jQuery whilst in my repo folder with:

npm install jquery 

How did you install jQuery?

Same way but in order to use jquery directly and not get the $ not found error I have to use

import $ from 'jquery';
window.jQuery = $;
window.$ = $;

which is confusing that I have to edit index.js/app.js and the webpack config.

What do you mean by β€œuse jQuery directly”?

If that means be able to use jQuery in the browsers dev tools console, I had to β€œexpose it” using this type of logic shown on stack exchange:

https://stackoverflow.com/a/29083197

Expose-loader info here:

https://webpack.js.org/loaders/expose-loader/

Hope that helps.

If you just want this damn thing working:

  // expose jquery's $ for imports
  plugins: [
     new webpack.ProvidePlugin({
       $: 'jquery',
       jQuery: 'jquery'
     })
  ]

In your JS where you're importing, preferably at top of file:

import $ from 'jquery';  
window.jQuery = $; window.$ = $;

Still not working.

This is soo stupid a normal import jquery does not work...
Made both modifications to webpack.config and the import $ part
restarted node static generator.

ReferenceError: jQuery is not defined
ReferenceError: $ is not defined

This frustrates me amazingly

Anyone knows a solution?

Im using yarn add jquery
3.1.1 latest as of now

Install with npm jquery and paste the code below to webpack.config.js

...
    resolve: {
        alias: {
            'jquery': path.join(__dirname, '/node_modules/jquery/dist/jquery.min.js')
        }
    },
    plugins: [ new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery'
    }) ]
...

And import this code to main file.

var $ = require('jquery');

So it worked for me.

Just add declare var $: any; to the beginning of your component ts file.
For example,

import { Component, OnInit } from '@angular/core';
declare var $: any;

@component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {
...
}

I'm using Webpack 4.1.0 within an ejected create-react-app project:

First I installed the library:

npm install jquery

Then I added the following to config\webpack.config.js (this alone is already enough)

plugins: [
    new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery',
        'window.jQuery': 'jquery',
    }),
    ...
]

...but it was also necessary to add an .eslint.rc file to the project root - and register jquery - in order to prevent a console error.

module.exports = {
  parser: "babel-eslint",
  parserOptions: {
    ecmaVersion: 2017,
    sourceType: "module",
    allowImportExportEverywhere: true
  },
  env: {
    es6: true,
    browser: true,
    jquery: true
  }
};

Thank you @sufius! I've been pulling my hair out trying to get Webpack 4 to play nice with JQuery...your answer did the trick!

Just add in your entry file:
window.$ = window.jQuery = require('jquery');

Let me add to the chaos here...

In my webpack config

plugins: [
  ...
  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    'window.$': 'jquery',
    'window.jQuery': 'jquery',
  }),
],

That alone did not work.

So I tried putting this in my entry:

import $ from 'jquery';
window.jQuery = $;
window.$ = $;

That ALSO didn't work.

So I removed the ProvidePlugin. Still no love.

I tried putting this in my config:

alias: {
  'jquery': path.join(__dirname, '/node_modules/jquery/dist/jquery.min.js')
}

with and without the other bits of config/import statements.

I am not using eslint (yet), so I can't try @sufius's fix.

Any other ideas? How is this still so hard?

@igreulich - not sure if this will help, but I put my config in a gist.

as the description states:

β€œjust the config i use, I’m sure it could be better but it’s worked for me for a while”

https://gist.github.com/oshihirii/3facf1112ce14bc1e0a484f4f8ccd1e8

and that assumes you have installed jquery with npm.

global.$ = require("jquery")

You need to use expose-loader in webpack

module: {
  rules: [{
    test: require.resolve('jquery'),
    use: [{
        loader: 'expose-loader',
        options: 'jQuery'
    },{
        loader: 'expose-loader',
        options: '$'
    }]
  }]
}

Ref: https://stackoverflow.com/questions/47469228/jquery-is-not-defined-using-webpack

```js
global.$ = require("jquery")

Worked for me,TY dude.

This thread was very helpful. I spent a long time trying to solve this. This worked for me:

in webpack config:

new webpack.ProvidePlugin({
	$: "jquery",
	jQuery: "jquery",
	"window.jQuery": "jquery",
});

in entrypoint:

global.$ = require("jquery");

perplexingly, jquery does work in the app w/o that global.$ line in the entrypoint, but it's not available in the window. Like, no window.$ Even though "window.jQuery" is specified in ProvidePlugin.

I suspect I am doing something wrong somewhere, but for now this seems to work.

This thread was very helpful. I spent a long time trying to solve this. This worked for me:

in webpack config:

new webpack.ProvidePlugin({
	$: "jquery",
	jQuery: "jquery",
	"window.jQuery": "jquery",
});

in entrypoint:

global.$ = require("jquery");

perplexingly, jquery does work in the app w/o that global.$ line in the entrypoint, but it's not available in the window. Like, no window.$ Even though "window.jQuery" is specified in ProvidePlugin.

I suspect I am doing something wrong somewhere, but for now this seems to work.

same issue :(
@tarponjargon had any progress?

This is a great example for the kind of issues that create huge frustration and bad reputation for webpack, like:
"webpack is to complicate for migrating my projects to it"

@Elia-Sh I just went with adding

global.$ = require("jquery");

And moved on since it worked. Webpack can definitely be frustrating at times, but overall worth the extra effort. I suspect this isn't going to be high on the list of things to address because the JS world is very anti-jquery these days.

Hi I had the same problem. I did everything that this post suggested but still got the error. Anyway I solved my problem and I'm suspecting many might actually have the same problem. Just check your index.html file in the network tab, make sure that you have the <script src="path to jquery"> included. In my case I have many webpack files for dev, staging and prod. I just forgot to add jquery it to my prod file and forgot to disabled cache in the browser.

global.$ = require("jquery");
Didn't work for me any other suggestions?

global.$ = require("jquery");
Didn't work for me any other suggestions?

Adding both of these lines to the entry js worked for me:

global.$ = require("jquery");
global.jQuery = global.$;

yes adding:

global.$ = require("jquery"); in entry point "file" worked!

Got this working by including the expose-loader npm package and adding the following to my webpack.config under module -> rules:

{ test: require.resolve("jquery"), use: [ { loader: "expose-loader", options: "jQuery" }, { loader: "expose-loader", options: "$" } ] },

Tried everything on this page but nothing seems to work. It's a really big issue with webpack and also the only issue that is bugging a lot.