webpack - ReferenceError: $ is not defined - javascript

I've read many answers to this question but I can't get to resolve my issue so I come here for help...
Here's my webpack conf file :
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// https://github.com/webpack-contrib/mini-css-extract-plugin
const webpack = require('webpack');
const jquery = require('jquery');
module.exports = {
mode: 'development',
entry: './assets/js/app.js',
output: {
path: path.resolve(__dirname, 'public/dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../',
hmr: process.env.NODE_ENV === 'development',
},
},
'css-loader',
],
},
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 100000,
},
},
{
loader:"file-loader",
options:{
name:'[name].[ext]',
outputPath:'images/' //the images will be emited to dist/images/ folder
}
}
],
},
{
// Exposes jQuery for use outside Webpack build
test: require.resolve('jquery'),
use: [{
loader: 'expose-loader',
options: 'jQuery'
}, {
loader: 'expose-loader',
options: '$'
}]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[name]-[id].css',
ignoreOrder: false,
}),
/* Use the ProvidePlugin constructor to inject jquery implicit globals */
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery'",
"window.$": "jquery"
})
],
/*resolve: {
alias: {
jquery: "jquery/src/jquery"
}
}*/
};
And my entry file app.js :
// Import CSS
import 'bootstrap/dist/css/bootstrap.css';
import '#fortawesome/fontawesome-free/js/all';
import '../css/style.css';
// Import JS
import $ from 'jquery';
window.$ = jQuery;
window.jQuery = jQuery;
import * as JSZip from 'jszip'; //export xlsx
import 'bootstrap';
//require('webpack-jquery-ui');
//require('webpack-jquery-ui/css');
I keep on trying different solution but still when I use jQuery in my code I get :
ReferenceError: $ is not defined
Could you please help me out ?

Look at this in your code:
import $ from 'jquery';
window.$ = jQuery;
window.jQuery = jQuery;
Think a second.
.
.
.
.
.
.
.
.
.
.
.
.
Notice you never defined jQuery. Fix it.
import $ from 'jquery';
window.$ = $;
window.jQuery = $;

One solution to add the jquery library as external. The second solution is to add jquery to the bundle.
1. External
webpack.js
externals: {   
jquery: 'jQuery'
}
plugins: [   new webpack.ProvidePlugin({      
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'    
})]
adding jquery to html
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous">
adding jquery in js
import $ from 'jquery';
const test = $('h1').text();
console.log(`from jquery: $ {test}`);
2. The second solution, adding jquery to the bundle First you need to install jquery locally.
yarn add -D jquery
adding jquery in js
import $ from 'jquery';
const test = $('h1').text();
console.log(`from jquery: $ {test}`);
This can be optimized and split using splitChunks but that's a story for another entry;)
I added an example of external jquery use

OK the mistake was stupid, app.js was called at the end of the layout and I was trying to use jQuery in the view.
So make sure that you check the order in which your broken code and the include which contains jquery is called.

Related

magnificPopup is not working with webpack

I have installed magnificPopup via "npm i magnific-popup" command after that imported it in the app.js file. But in the browser console it shows (magnificPopup is not a function )
app.js
import $ from "jQuery";
window.$ = window.jQuery = $;
import "magnific-popup";
$(document).ready(function() {
$('.play-btn').magnificPopup({ type: 'video' });
});
webpack.config.js
var path = require("path");
var webpack = require('webpack');
module.exports = {
entry: {
app: "./app/assets/scripts/app.js",
vendor: "./app/assets/scripts/vendor.js"
},
output: {
path: path.resolve(__dirname, "./app/temp/scripts"),
filename: "[name].js"
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ["es2015"]
}
}
}
]
},
plugins: [
new webpack.ProvidePlugin({
'$': 'jquery',
'jQuery': 'jquery',
'window.jQuery': 'jquery'
}),
]
}
I've fixed the problem
jQuery doesn't need to import in app.js
After fixing app.js file looks like this
import "magnific-popup";
$(document).ready(function() {
$('.play-btn').magnificPopup({ type: 'video' });
});
Its simple, your files are not on the import location. Please check your path or file location/position once. Moreover please check your JQuery library if that included then it should be above this library files/code.

Webpack bundles jQuery but I can't use it

I'm a beginner with Webpack and simply stuck.
I'm trying to bundle jQuery plugins and have them in a plugins-bundled.js file.
Then I have my local scripts file where all jQuery code goes. These 2 files are loaded in HTML in order 1. plugins-bundled.js 2. scripts.js But then I got error in a console Uncaught ReferenceError: jQuery is not defined. Is there something I'm missing here?
Webpack config
const path = require('path'),
settings = require('./settings');
module.exports = {
entry: {
App: settings.themeLocation + "js/plugins.js"
},
output: {
path: path.resolve(__dirname, settings.themeLocation + "js"),
filename: "plugins-bundled.js"
},
module: {
rules: [
{
use: {
loader: 'babel-loader',
options: {
presets: ['env']
}
},
test: /\.js$/,
exclude: /node_modules/
}
]
}
}
Webpack App file
import $ from 'jquery';
window.jQuery = $;
window.$ = $;
import slick from 'slick-carousel';
import localScroll from 'jquery.localscroll';
import popper from 'popper.js';
import bootstrap from './bootstrap.min';
Local scripts file
(function($){
"use strict";
// code goes here...
})(jQuery);

How to import jquery in webpack

I have a problem with jquery when i using it on webpack.
My code:
const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const CompressionPlugin = require("compression-webpack-plugin");
module.exports = {
entry: {
vendor: [
'./src/main/webapp/js/vendor/jquery-3.3.1.min.js',
// './src/main/webapp/js/vendor/fs.js',
'./src/main/webapp/js/vendor/google-adsense.js',
'./src/main/webapp/js/vendor/jquery.menu-aim.min.js',
'./src/main/webapp/js/vendor/jquery.touchSwipe.min.js',
],
app: './src/main/assets/js/desktop/app.js',
mobile: './src/main/assets/js/mobile/app.js',
touch: './src/main/assets/js/touch/app.js',
},
module: {
rules: [{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
},
{
test: require.resolve('jquery'),
loader: 'expose-loader?jQuery!expose-loader?$'
}
],
},
plugins: [
// new CleanWebpackPlugin(['src/main/webapp/assets']),
new webpack.optimize.CommonsChunkPlugin({
name: 'common' // Specify the common bundle's name.
}),
new UglifyJsPlugin({
test: /\.js$/,
sourceMap: process.env.NODE_ENV === "development"
}),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
],
output: {
filename: '[name].js',
path: path.resolve(__dirname, './src/main/webapp/js')
}
};
When above code compiles , console throws this error
vendor.js:1 Uncaught ReferenceError: webpackJsonp is not defined
at vendor.js:1
And when i try to use this
externals: {
jquery: 'jQuery'
}
It throws
vendor.js:1 Uncaught ReferenceError: jQuery is not defined
at Object.231 (vendor.js:1)
at o (common.js:1)
at Object.228 (vendor.js:1)
at o (common.js:1)
at window.webpackJsonp (common.js:1)
at vendor.js:1
And i using jquery in my core js file import $ from 'jquery'.
What did i do wrong ? any help ? Thank you.
So there are few themes in your webpack.config.js, some of which conflict. Just going to list them so I can better understand what I think you are trying to achieve.
Theme 1
You have an entry called vendor that is clearly referencing a minified jQuery library you have presumably downloaded and placed in the directory specified.
Theme 2
You also have an expose-loader that is essential exposing the jquery library from its node_modules probably listed in the dependencies of your package.json.
This makes the jquery in the node_modules available as $ and jQuery in the global scope of the page where your bundle is included.
Theme 3
You also have included the ProvidePlugin with configuration for jQuery.
The ProvidePlugin is supposed to inject dependencies into the scope of your module code, meaning you do not need to have import $ from 'jquery' instead $ and jQuery will already be available in all of your modules.
Conclusion
From what I have gathered I think you're trying to bundle jQuery from the static file at ./src/main/webapp/js/vendor/jquery-3.3.1.min.js in a vendor bundle.
You are then trying to expose the libraries in the vendor bundle to the global scope (jQuery).
Then also have your application code able to import jQuery from what is made available by the vendor bundle in the global scope.
Answer
So if that is what you are doing you need to do the following things.
Firstly, check in your package.json files dependencies for jquery. If its there you want to remove it, there's no need for it if you're going to use your jquery-3.3.1.min.js file instead to provide jQuery to your application.
Secondly, change your test of the expose-loader to trigger when it sees your jquery-3.3.1.min.js file in your entries, not resolve it from the jquery dependency from your node_modules.
This regex pattern should do the trick.
{
test: /jquery.+\.js$/,
use: [{
loader: 'expose-loader',
options: 'jQuery'
},{
loader: 'expose-loader',
options: '$'
}]
}
Thirdly, remove the ProvidePlugin if you're going to import the library explicitly with import $ from 'jquery' you do not need it.
Lastly, you need to tell webpack when it sees an import for jquery it can resolve this from window.jQuery in the global scope. You can do this with the externals configuration you already referenced.
externals: {
jquery: 'jQuery'
}
With all these changes you should end up with a webpack.config.js file that looks like this.
const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const CompressionPlugin = require("compression-webpack-plugin");
module.exports = {
entry: {
vendor: [
'./src/main/webapp/js/vendor/jquery-3.3.1.min.js',
// './src/main/webapp/js/vendor/fs.js',
'./src/main/webapp/js/vendor/google-adsense.js',
'./src/main/webapp/js/vendor/jquery.menu-aim.min.js',
'./src/main/webapp/js/vendor/jquery.touchSwipe.min.js',
],
app: './src/main/assets/js/desktop/app.js',
mobile: './src/main/assets/js/mobile/app.js',
touch: './src/main/assets/js/touch/app.js',
},
module: {
rules: [{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
},
{
test: /jquery.+\.js$/,
use: [{
loader: 'expose-loader',
options: 'jQuery'
},{
loader: 'expose-loader',
options: '$'
}]
}
],
},
plugins: [
// new CleanWebpackPlugin(['src/main/webapp/assets']),
new webpack.optimize.CommonsChunkPlugin({
name: 'common' // Specify the common bundle's name.
}),
new UglifyJsPlugin({
test: /\.js$/,
sourceMap: process.env.NODE_ENV === "development"
})
],
output: {
filename: '[name].js',
path: path.resolve(__dirname, './src/main/webapp/js')
},
externals: {
jquery: 'jQuery'
}
};
I hope that does not just give you the answer but enough explanation as to where you were going wrong.

Making a node_module global using Webpack 2

I am using the below package on an angular project:
https://github.com/pablojim/highcharts-ng
A requirement is that it needs highcharts as a global dependency, in which it tells you to add a script tag into your html:
<script src="http://code.highcharts.com/highcharts.src.js"></script>
Rather than add the above script tag into my HTML I would like to make it global via Webpack.
I have installed highcharts via npm and have tried using the ProvidePlugin and the noParse methods described here (to no avail): https://webpack.js.org/guides/shimming/#scripts-loader
For the ProvidePlugin option I used:
new webpack.ProvidePlugin({
Highcharts: "highcharts",
})
for noParse:
noParse: [
/[\/\\]node_modules[\/\\]highcharts[\/\\]highcharts\.js$/,
],
Neither worked, meaning when highcharts-ng tried to work, it gets an error because it cannot create a new Highcharts:
TypeError: Cannot read property 'Chart' of undefined
// from highcharts-ng which throws above error
chart = new Highcharts[chartType](mergedOptions, func);
Here is my angular module
import angular from 'angular'
import highchartsNg from 'highcharts-ng'
import { ReportsData } from './reports.data'
import { reportsWidget } from './reports-widget/component'
export const ReportsModule = angular
.module('reports', [
highchartsNg,
])
.factory('ReportsData', ReportsData)
.component('reportsWidget', reportsWidget)
.name
My webpack config:
var webpack = require('webpack')
module.exports = {
context: __dirname + '/app/modules',
entry: {
vendor: ['angular', 'highcharts-ng'],
modules: './modules.js',
},
output: {
path: __dirname + '/.tmp/modules',
filename: '[name].bundle.js',
},
plugins: [
// info: https://webpack.js.org/guides/code-splitting-libraries/
new webpack.optimize.CommonsChunkPlugin({
name: ['vendor', 'manifest'],
}),
],
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: { presets: ['es2015'] },
},
],
},
],
},
}
Use expose-loader and write require('expose-loader?Highcharts!highcharts'); somewhere before the first usage of Highcharts global variable. This will require highcharts and save expose it as window.Highcharts in the browser.
Under the hood webpack makes it available for you as:
/* 0 */
/***/ function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(global) {module.exports = global["Highcharts"] = __webpack_require__(1);
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(2)))
/***/ }

Using jquery-mobile with Webpack

I am trying to load jquery-mobile using webpack with no luck so far.
I am aware that jquery-mobile depends on jquery-ui which in turn depends on jquery.
How do I set up such a scenario in Webpack?
Here is my webpack.config.js:
var webpack = require('webpack');
var path = require('path');
var bower_dir = __dirname + '/bower_components';
module.exports = {
context: __dirname,
entry: './assets/js/index.js',
output: {
path: path.resolve('./assets/bundles/'),
filename: "[name]-[hash].js",
},
plugins: [
new BundleTracker({filename: './webpack-stats.json'}),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
})
],
module: {
loaders: [
{test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/, loader: "imports?this=>window"}
]
},
resolve: {
alias: {
'jquery': bower_dir + '/jquery/src/jquery.js',
'jquery-ui': bower_dir + '/jquery-ui/jquery-ui.js',
'jquery-mobile': bower_dir + '/jquery-mobile/js/jquery.mobile.js'
}
}
};
Any help would be much appreciated.
Thank you all in advance.
If you just add the scripts you need to the page in the correct order, you don't need to worry about that in webpack.
All you have to do is tell webpack that those modules are loaded from external references, like so:
{
externals: {
'jquery': 'jQuery'
}
}
This tells webpack that every time you require('jquery') it will return a globally available variable jQuery.

Categories

Resources