I\'m using Webpack to build an Angular 1.4 project. The project makes use of several jQuery plugins, which are wrapped into angular directives. Those directives internally use <
Apparently you still need to use the commonJs require for angular in the ES6 example.
import $ from "jquery"
window.$ = $;
window.jQuery = $;
var angular = require("angular");
below is the original answer
I want to purpose a easier solution. Just make jQuery a window global so that angular can recognize it:
var $ = require("jquery")
window.$ = $;
window.jQuery = $;
var angular = require("angular");
or in your case (OUT DATED):
import $ from "jquery"
window.$ = $;
window.jQuery = $;
import angular from "angular";
I hope this helps :)
Got this answer from john-reilly:
The mysterious case of webpack angular and jquery
bob-sponge's answer is not quite right - the Provide plugin is actually doing a text replacement on modules it processes, so we need to provide window.jQuery
(which is what angular is looking for) and not just jQuery
.
In your
webpack.config.js
you need to add the following entry to your plugins:
new webpack.ProvidePlugin({
"window.jQuery": "jquery"
}),
This uses the webpack ProvidePlugin and, at the point of webpackification (© 2016 John Reilly) all references in the code to window.jQuery will be replaced with a reference to the webpack module that contains jQuery. So when you look at the bundled file you'll see that the code that checks the
window
object forjQuery
has become this:
jQuery = isUndefined(jqName) ?
__webpack_provided_window_dot_jQuery : // use jQuery (if present)
!jqName ? undefined : // use jqLite
window[jqName]; // use jQuery specified by `ngJq`
That's right; webpack is providing Angular with jQuery whilst still not placing a
jQuery
variable onto thewindow
. Neat huh?
There is this japanese article I want to use the jQuery not jQLite in webpack + AngularJS that seems to talk about the same problem (I don't know Japanese yet btw). I used google to translate to english, credits goes to cither for this nice answer.
He provides four ways to solve this:
Assign directly to the window (not really cool)
window.jQuery = require('jquery');
var angular = require('angular');
console.log(angular.element('body'));
//[body, prevObject: jQuery.fn.init[1], context: document, selector: "body"]
Use the expose-loader (ok, but not that cool)
npm install --saveDev expose-loader
webpack.config.js
module.exports = {
entry: "./index",
output: {
path: __dirname,
filename: "bundle.js"
},
module: {
loaders: [{
test: /\/jquery.js$/,
loader: "expose?jQuery"
}]
}
};
usage:
require('jquery');
var angular = require('angular');
console.log(angular.element('body'));
//[body, prevObject: jQuery.fn.init[1], context: document, selector: "body"]
Use expose-loader (better)
npm install --saveDev expose-loader
webpack.config.js
module.exports = {
entry: "./index",
output: {
path: __dirname,
filename: "bundle.js"
},
module: {
loaders: [{
test: /\/angular\.js$/,
loader: "imports?jQuery=jquery"
}, {
test: /\/jquery.js$/,
loader: "expose?jQuery"
}]
}
};
usage:
var angular = require('angular');
console.log(angular.element('body'));
//[body, prevObject: jQuery.fn.init[1], context: document, selector: "body"]
Use ProvidePlugin (Best solution)
This is actually the same as studds's accepted answer here
module.exports = {
entry: "./index",
output: {
path: __dirname,
filename: "bundle.js"
},
plugins: [
new webpack.ProvidePlugin({
"window.jQuery": "jquery"
})
],
};
usage:
var angular = require('angular');
console.log(angular.element('body'));
//[body, prevObject: jQuery.fn.init[1], context: document, selector: "body"]
I thought I'd share this here since we had the exact same problem. We used the expose-loader
solution in our project with success. I suppose that the ProvidePlugin
which injects jquery directly in window
is also a good idea.
So, I give my solution, which is actually a mashup of the @BobSponge answer and @Bob's hints / comments. So nothing original, just showing what works for me (in a project not using Babel / ES6, BTW) and attempting to explain why it works...
The (final) trick is indeed to use the expose loader.
As explained in their page, we have to put in module.loaders
:
{ test: require.resolve("jquery"), loader: "expose?$!expose?jQuery" },
Moreover, in the plugins
list, I have:
new webpack.ProvidePlugin(
{
$: 'jquery',
jQuery: 'jquery',
_: 'lodash',
// [...] some other libraries that put themselves in the global scope.
//angular: 'angular', // No, I prefer to require it everywhere explicitly.
}),
which actually finds the global occurrences of these variables in the code, and require them into variables local to each module. It eases the migration of an existing project (from RequireJS to Webpack) as I do... I think we can do without this plugin if you prefer to be explicit in your imports.
And, importantly (I think), in the entry point of the application, I require them in the order I want them. In my case, I made a vendor bundle, so that's the order in this bundle.
require('jquery');
require('lodash');
// [...]
var angular = require('angular');
// Use the angular variable to declare the app module, etc.
Webpack will add the libraries to the relevant bundle in the order it sees the require
s (unless you use a plugin / loader that reorder them).
But the imports are isolated (no global leak), so Angular wasn't able to see the jQuery library. Hence the need for expose
. (I tried window.jQuery = require('jquery');
instead, but it didn't work, perhaps it is too late.)
In your case is better to use ProvidePlugin. Just add this lines to your webpack config in plugins section and jquery will available in your app:
new webpack.ProvidePlugin({
"$": "jquery",
"jQuery": "jquery"
})