1

I can't seem to work out the correct way to load third party libraries that depend on each other. I'm using TypeScript and Gulp with either Webpack or SystemJS for my module loader, both of which have similar errors in this case. My application code works if I use only jQuery, but if I try to use a jQuery plugin, like jQuery Validation, I get similar errors from both Webpack and SystemJS about jQuery being undefined.

There's kind of a lot of configuration for both setups, I'll demonstrate my most recent attempt at Webpack here:

My main.ts file:

import * as $ from "jquery";
// if I comment out these two imports, the '$("body").css...' line works
import "../bower_components/jquery-validation/dist/jquery.validate";
import "../bower_components/jquery-validation-unobtrusive/jquery.validate.unobtrusive";

$("body").css("color", "red");

The gulpfile used to generate the output:

var gulp = require('gulp'),
    webpack = require("gulp-webpack");

gulp.task("tsc-webpack", function () {
    return gulp.src("app/main.ts")
        .pipe(webpack({
            output: {
                filename: "main.js"
            },
            module: {
                loaders: [
                    { test: /\.tsx?$/, loader: "ts-loader" }
                ]
            }
        }))
        .pipe(gulp.dest(appDir + "js"))
});

My tsconfig.json file:

{
"compilerOptions": {
    "noImplicitAny": false,
    "noEmitOnError": true,
    "removeComments": false,
    "sourceMap": true,
    "target": "es5",
    "module": "commonjs"
},
"exclude": [
    "node_modules"
]
}

Here's the error I get from the Chrome developer console

Uncaught ReferenceError: jQuery is not defined
    at Object.<anonymous> (main.js:12312)
    at __webpack_require__ (main.js:20)
    at Object.<anonymous> (main.js:51)
    at __webpack_require__ (main.js:20)
    at Object.defineProperty.value (main.js:40)
    at main.js:43

Here's the block in the generated file that throws the error (at the very last line)

(function ($) {
    var $jQval = $.validator,
    // ...
    $(function () {
        $jQval.unobtrusive.parse(document);
    });
}(jQuery));
Shaun
  • 1,962
  • 16
  • 44

1 Answers1

1

Generally for jquery in webpack I use:

module: {                                
  rules: [
    {  test: require.resolve('jquery'), loader: 'expose-loader?$!expose-loader?jQuery' },
  ]
},
plugins: [
  new webpack.ProvidePlugin({
    '$': 'jquery',
    'jQuery': 'jquery',
    'window.jQuery': 'jquery'
  }),
]

Webpack is supposed to recognise amd/commonjs and jquery-validation looks like it checks for define.

There is more info here on shimming here: https://webpack.js.org/guides/shimming/

Meirion Hughes
  • 21,021
  • 8
  • 65
  • 114