Can I use an ES6/2015 module import to set a reference in 'global' scope?

tony_k picture tony_k · Jul 3, 2015 · Viewed 18.8k times · Source

I have this situation where I am trying to import an existing library, which I'll call troublesome (using Webpack/Babel FWIW) and it has a global reference to jQuery in it which i am trying to resolve using module syntax.

I have successfully imported jquery into the 'local' scope of a module, via:

import jQuery from 'jquery'

so I tried:

import jQuery from 'jquery'    
import 'troublesome'

but perhaps not surprisingly, I get something like jQuery is not a function kicked back from troublesome.js

I have tried this as well:

System.import('jquery')
.then(jQuery => {
    window.jQuery = jQuery
})
import 'troublesome'

but, it turns out that System.import is part of the, so-called, 'module-loader' spec, which was pulled from the es6/2015 spec, so it isn't provided by Babel. There is a poly-fill, but Webpack wouldn't be able to manage dynamic imports accomplished via calls to System.import anyway.

but... if I call out the script files in index.html like so:

<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/troublesome/troublesome.js"></script>
<script src="the-rest-of-my-js.js"></script>

the reference to jQuery is resolved in troublesome.js and things are good, but I would prefer to avoid the script tag route as webpack doesn't manage those.

Can anyone recommend a decent strategy for dealing with scenarios like this?

update

with some guidance from @TN1ck, I was eventually able to identify one Webpack-centric solution, using the imports-loader

The configuration for this solution looks something like this:

  //...
  module: {
    loaders: [
      //...
      {
        test: require.resolve('troublesome'),
        loader: "imports?jQuery=jquery,$=jquery"
      }
    ]
  }

Answer

TN1ck picture TN1ck · Jul 6, 2015

Shimming modules is the way to go: http://webpack.github.io/docs/shimming-modules.html

I quote from the page:

plugin ProvidePlugin

This plugin makes a module available as variable in every module. The module is required only if you use the variable.

Example: Make $ and jQuery available in every module without writing require("jquery").

new webpack.ProvidePlugin({
  $: "jquery",
  jQuery: "jquery",
  "window.jQuery": "jquery"
})

To use this with your webpack-config just add this object to an array called plugins in the config:

// the plugins we want to use 
var plugins = [
   new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery",
      "window.jQuery": "jquery"
   })
];

// this is your webpack-config
module.exports = {
    entry: ...,
    output: ...,
    module: ...,
    plugins: plugins
}