Custom jQuery extensions/plugin not found when using webpack

Viewed 57

I am trying to migrate an old project to use webpack. I wrote some custom plugins which not don't work anymore. Though I think this problem shoud have occured to somebody else, I couldn't find any post about it.

Here is my base.js containing:

(function ($) {
    $.fn.my_extension = function () {
       alert("I am found!");
    };
}(jQuery));

That's how I use it in my template:

<script type="text/javascript">
    $(document).ready(function() {
        $('#my-id').my_extension();
    });
</script>

Here's my include in my index.js:

// JS Dependencies
import 'jquery';
...

// Custom JS
import '../js/base.js';

And here is my webpack.config.js:

var path = require('path');
var webpack = require('webpack');
var BundleTracker = require('webpack-bundle-tracker');

module.exports = {
    context: __dirname,
    mode: 'development',
    entry: './static/js/index.js',
    output: {
        path: path.resolve('./static/webpack_bundles/'),
        filename: "[name]-[hash].js"
    },
    module: {
        rules: [            
            {
                test: require.resolve('jquery'),
                use: [{
                    loader: 'expose-loader',
                    options: 'jQuery'
                }, {
                    loader: 'expose-loader',
                    options: '$'
                }]
            },
            ...
        ],
    },
    plugins: [
        new BundleTracker({filename: 'webpack-stats.json'}),
        new webpack.ProvidePlugin({
            $: "jquery",
            jQuery: "jquery",
            'window.jQuery': 'jquery'
        })]
}

And here's the error I get when calling the template:

TypeError: $(...).my_extension is not a function

Any ideas what I might be doing wrong?

Thanks!

1 Answers

After trying different approaches for ages, I figured out that the registration works but jQuery is not the same instance, when I use it in my template.

What solved my problem was finally adding this line to my base.js.

require('jquery');

I'm not 100% sure but I guess the expose-loader is recognizing this import and creating the global scope for it.

Maybe this helps somebody else.

Related