50

I’m trying out webpack (http://webpack.github.io/) and it looks really nice, however I’m kind of stuck here.

Say that I’m using a CDN for a library, f.ex jQuery. Then in my code, I want the require('jquery') to automatically point to the global jquery instance, instead of trying to include it from my modules.

I’ve tried using plugins like the IgnorePlugin:

new webpack.IgnorePlugin(new RegExp("^(jquery|react)$"))

This works for ignoring the library, but it still says that the required module is "missing" when I run the webpacker.

Somehow I need to tell webpack that jquery should be picked up from the global context instead. Seems like a common use case, so I’m kind of surprised that the docs doesn’t target this specifically.

David Hellsing
  • 97,234
  • 40
  • 163
  • 203

1 Answers1

77

According to the Webpack documentation, you can use the externals property on the config object "to specify dependencies for your library that are not resolved by webpack, but become dependencies of the output. This means they are imported from the enviroment while runtime [sic]."

The example on that page illustrates it really well, using jQuery. In a nutshell, you can require jQuery in the normal CommonJS style:

var jQuery = require('jquery');

Then, in your config object, use the externals property to map the jQuery module to the global jQuery variable:

{
    externals: {
        // require("jquery") is external and available
        //  on the global var jQuery
        "jquery": "jQuery"
    }
}

The resulting module created by Webpack will simply export the existing global variable (I'm leaving out a lot of stuff here for brevity):

{
    1: function(...) {
        module.exports = jQuery;
    }
}

I tried this out, and it works just as described.

Martian2049
  • 1,578
  • 15
  • 25
Garrett
  • 871
  • 5
  • 4
  • 14
    Just tried this with UMD output, and it doesn't work. Instead, it outputs code that does require('jQuery'), which fails because the module name is 'jquery', not 'jQuery'. I don't understand how this feature is supposed to work. – user1009908 May 04 '15 at 16:29
  • 1
    I had your same issue, I am using ES6 modules. Even though I write `import React from 'react';`, the externals are simply configured as `externals: { 'react': 'react' }` – gcedo Sep 06 '15 at 17:59
  • 2
    For UMD you have to pass in an object that gives a different string for each module type. E.g. `{ amd: 'jquery', global: 'jQuery', commonjs: 'jquery' }` the exact properties there are probably wrong, but should be a good lead for anyone to get this right in the future. – Adam A Oct 30 '15 at 00:25
  • 2
    Wow, it is possible to have UMD use different names as @Adam A said, but the right properties are: `amd`, `commonjs`, `commonjs2`, and `root`! This way you can do: `externals: {jquery: {amd 'jquery', root: '$', commonjs: 'jquery', commonjs2: 'jquery'}}` – Caleb Hearon Jan 12 '16 at 20:46
  • 1
    @CalebHearon this is cool syntax but I was hoping I could do something like this `externals: {jquery: {commonjs2: 'global.jQuery'}}` but unfortunately this still results in a `module.exports = require('global.jQuery');` where I'm just looking for the non-commonjs behavior of `module.exports = global.jQuery;` in a `commonjs2` target build. Any ideas, I tried the `NormalModuleReplacementPlugin` with no luck – dtothefp Feb 25 '16 at 14:49
  • 1
    how about fallback. Is there a simple/best way for that with webpack? – Ravi Mar 11 '16 at 04:06