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"
}
]
}
For es6/2015 I done the following.
Then you can use it as normal
Hope this helps.
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")
.To use this with your webpack-config just add this object to an array called plugins in the config:
I've had a similar issue using jspm and dygraphs. The way i solved it was to use dynamic loading like you attempted using
System.import
but the important part was to chain-load each consecutive "part" usingSystem.import
again inside the promise onfulfillment handler (then) after setting the global namespace variable. In my scenario I actually had to have several import steps separated betweenthen
handlers.The reason it didn't work with jspm, and probably why it didn't work for you as well is that the
import ... from ...
syntax is evaluated before any code, and definitely beforeSystem.import
which of async.In your case it could be as simple as:
Also note that the
System
module loader recommendation has been left out of the final ES6 specification, and a new loader spec is being drafted.Shimming is fine and there are various ways of resolving this, but as per my answer here, the simplest is actually just to revert to using require for the loading of the library that requires the global dependency - then just make sure your window. assignment is before that require statement, and they are both after your other imports, and your ordering should remain as intended. The issue is caused by Babel hoisting imports such that they all get executed before any other code.
npm install import-loader
.import 'troublesome'
withimport 'imports?jQuery=jquery,$=jquery!troublesome
.In my opinion, this is the simplest solution to your question. It is similar to the answer you wrote in your question @TN1ck, but without altering your webpack config. For more reading, see: https://github.com/webpack/imports-loader
Importing
jQuery
into your module does not make it available for'troublesome'
. Instead, you could create a thin wrapper module for'troublesome'
that providesjQuery
and any other required "globals".troublesome-module.js:
Then in your code you should be able to