Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly add jquery plugins to jquery object in webpack?

TL;DR What is the proper way of extending jQuery object with plugins, exposing it globally and using external AMD libs with ES6 modules in webpack? Is webpack the right tool for the task, or would SystemJs suit the situation of refactoring a legacy app to ES6 modules better?

I am trying to wrap my head around working with webpack and ES6 modules. I have a legacy mostly jquery app that I am currently converting. I am facing the following challenges:

  1. finding best practices in the webpack/babel-loader workflow
  2. figuring out which loader/plugin to use for which purpose
  3. getting AMD resources like jquery and jquery plugins to play nice with the rest of the modules.
  4. exposing jquery globals, extended with all the plugins and jquery-ui

I have relied on the following resources: This great answer explains a lot, though it does not mention the exports loader, which I am mostly relying on: https://stackoverflow.com/a/28989476/2613786

http://webpack.github.io/docs/shimming-modules.html - the documentation lists many possibilities, but i lack the experience to decide which one is the right one. It seems to be preferred to use the ProvidePlugin instead of the expose-loader. Sadly I didn't get it to work with an extended jQuery object. Neither did it work for the use of module functions invoced in <script> tags.

I still struggle to find programatic solutions and decide which webpack plugin is the right one for the job. Some advice or examples from an experienced webpack user are greatly appreciated.

In my webpack.config.js i have the following loaders to expose jquery and transpile with babel:

module: {
    loaders: [
        { 
            test: /\.js$/, 
            exclude: /node_modules/,
            loader: 'babel-loader',
            query: {modules: 'common'}
        },
        {
            test: /jquery\.js$/,
            exclude: /node_modules/,
            loader: 'expose?jQuery',
        },
        {
            test: /jquery\.js$/,
            exclude: /node_modules/,
            loader: 'expose?$',
        },
        {
            test: /[\/\\]vendor[\/\\]jquery.sparkline\.js$/,
            loader: "imports?define=>false"
        }
    ]
},
amd: { jQuery: true },
// plugins: [
//     new webpack.ProvidePlugin({
//        $: 'jquery',
//        jQuery: 'jquery',
//        'window.jQuery': 'jquery',
//        'root.jQuery': 'jquery'
//    })
// ], ...

In my entry.js file I include jquery in the following way:

import 'expose?jQuery!expose?$!./vendor/jquery';
import './jquery/jquery-ui';
import './vendor/jquery.sparkline';

I had to comment out the ProvidePlugin, when i use it, the jQuery is not extended with custom plugins anymore, any idea why that is the case? Does it have to do with the plugins using ES6 module syntax?

I had to add loader: "imports?define=>false" for jquery.sparkline.js to get it to be recogniced. Is this really necessary, or is there a better way to do it?

Concerning jquery-ui i had to find an old version that did not use AMD define to get it to add to the jquery object. What would be the right way to do it?

Any help and advice is greatly appreciated, a reason to switch to SystemJs and Jspm might also be a solution.

like image 326
RemEmber Avatar asked Mar 24 '15 15:03

RemEmber


People also ask

What are jQuery plugins?

A jQuery plugin is simply a new method that we use to extend jQuery's prototype object. By extending the prototype object you enable all jQuery objects to inherit any methods that you add. As established, whenever you call jQuery() you're creating a new jQuery object, with all of jQuery's methods inherited.

What is the use of plugins in webpack?

A webpack plugin is a JavaScript object that has an apply method. This apply method is called by the webpack compiler, giving access to the entire compilation lifecycle.


1 Answers

I have had issues with this and it seems that it was because some plugins assume $ and others assume jQuery, but the following eventually worked for me, even if it is rather ugly:

Edit, note that I'm testing for plugins which are named jquery.xyz.js, you'd have to adjust the regex appropriately. Also, I'm not sure if the two different expose loaders for jQuery are causing issues, but so far this works.

// webpack.config.js
...
"module": {
    "loaders": [
        {
            test: require.resolve("jquery"),
            loader: "expose?$!expose?jQuery"
        },
        {
            test:   /jquery\..*\.js/,
            loader: "imports?$=jquery,jQuery=jquery,this=>window"
        }
...
like image 108
Luke H Avatar answered Sep 19 '22 15:09

Luke H