Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confusion over various webpack shimming approaches

I'm a little confused on the various ways webpack allows to expose a variable that isn't available on npm or to be put in the bundle. I was able to expose the google visualizations chart script's global google var by using

resolve: {
    extensions: ['.js', '.json'],
    alias: {
      'google': path.resolve(__dirname, 'vendor', 'google.js')
    }
  }

combined with

  plugins: [
    new webpack.ProvidePlugin({
      'google': 'google'
    })
  ]

however looking at the webpack docs there a couple other ways to shim, which look like they might do something similar. There is imports-loader and exports-loader, and script-loader. I know that I've linked to the docs, but I still find their descriptions of when these four should be used a bit unclear.

Also looking at this example, is this require not assigned to a variable? Where is it meant to go? And where is the documentation on what is going on with this syntax?

require("imports?$=jquery!./file.js")

Can someone provide me some examples of when each of these should be used?

like image 614
1252748 Avatar asked Jun 08 '17 15:06

1252748


People also ask

What is shimming in Webpack?

The webpack compiler can understand modules written as ES2015 modules, CommonJS or AMD. However, some third party libraries may expect global dependencies (e.g. $ for jQuery ). The libraries might also create globals which need to be exported.


2 Answers

scripts-loader

I never used this myself, but the idea is simple I guess. I think it can be used if for some reason you want to inject a script or a function or something in one of the modules/files you have no control over them.

imports-loader & exports-loader

In one of the apps I worked on we had to use tinymce which in its older versions was dependent on this being always window because it was built to work as a global script. Not as a CommonJS or ES module.

So in order to fix that, we had to use the import-loader so it can inject window to the script. Here how it looked like in webpack.config.js

{ test: require.resolve('tinymce/tinymce'), use: ['imports?this=>window', 'exports?tinymce'] }

Which says inject window in place of this & also we are using exports-loader here so we can export the global tinymce as a default export named tinymce so we can use it as a normal module in our app.

Thankfully all of this is already fixed in the latest releases.

ProvidePlugin

In my experience, this is useful when a library is depending on another library being in a global scope or something. Like jQuery plugins for example, they do use one of these $, window.$, jQuery & window.jQuery

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

So what this plugin will do is to make sure when webpack sees one of these variations it will provide the jQuery object to it instead.

The difference between this & imports-loader for example that you might not know which variation is used by which script. So you let webpack handle this while the imports-loader is kind of more specific.

I hope this helped you a bit to understand the differences between all of them, also this is the new documentation page which I think better than the one you were checking https://webpack.js.org/guides/shimming/

like image 55
ahmedelgabri Avatar answered Sep 20 '22 13:09

ahmedelgabri


imports and exports loaders are very simple to understand. If you use one of them, or both, your module is wrapped into another function with exports and imports.

For example, I'm using paho-mqtt module meant to be used like global <script src=""> on the page:

import Paho from 'imports-loader?this=>window!exports-loader?Paho!paho-mqtt';

//and this is transformed by webpack to something like:
(function(window){

    //wow you can use `window here`, `this` in the global context === window.


   // original module code here
   // that exposes global var `Paho`


   module.exports = Paho;

})(this);
like image 21
arturkin Avatar answered Sep 21 '22 13:09

arturkin