Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webpack ProvidePlugin vs externals?

I'm exploring the idea of using Webpack with Backbone.js.

I've followed the quick start guide and has a general idea of how Webpack works, but I'm unclear on how to load dependency library like jquery / backbone / underscore.

Should they be loaded externally with <script> or is this something Webpack can handle like RequireJS's shim?

According to the webpack doc: shimming modules, ProvidePlugin and externals seem to be related to this (so is bundle! loader somewhere) but I cannot figure out when to use which.

Thanks

like image 832
Henry Avatar asked Apr 26 '14 01:04

Henry


2 Answers

It's both possible: You can include libraries with a <script> (i. e. to use a library from a CDN) or include them into the generated bundle.

If you load it via <script> tag, you can use the externals option to allow to write require(...) in your modules.

Example with library from CDN:

<script src="https://code.jquery.com/jquery-git2.min.js"></script>  // the artifial module "jquery" exports the global var "jQuery" externals: { jquery: "jQuery" }  // inside any module var $ = require("jquery"); 

Example with library included in bundle:

copy `jquery-git2.min.js` to your local filesystem  // make "jquery" resolve to your local copy of the library // i. e. through the resolve.alias option resolve: { alias: { jquery: "/path/to/jquery-git2.min.js" } }  // inside any module var $ = require("jquery"); 

The ProvidePlugin can map modules to (free) variables. So you could define: "Every time I use the (free) variable xyz inside a module you (webpack) should set xyz to require("abc")."

Example without ProvidePlugin:

// You need to require underscore before you can use it var _ = require("underscore"); _.size(...); 

Example with ProvidePlugin:

plugins: [   new webpack.ProvidePlugin({     "_": "underscore"   })  ]  // If you use "_", underscore is automatically required _.size(...) 

Summary:

  • Library from CDN: Use <script> tag and externals option
  • Library from filesystem: Include the library in the bundle. (Maybe modify resolve options to find the library)
  • externals: Make global vars available as module
  • ProvidePlugin: Make modules available as free variables inside modules
like image 176
Tobias K. Avatar answered Oct 01 '22 00:10

Tobias K.


Something cool to note is that if you use the ProvidePlugin in combination with the externals property it will allow you to have jQuery passed into your webpack module closure without having to explicitly require it. This can be useful for refactoring legacy code with a lot of different files referencing $.

//webpack.config.js module.exports = {   entry: './index.js',   output: {      filename: '[name].js'    },   externals: {     jquery: 'jQuery'   },   plugins: [     new webpack.ProvidePlugin({       $: 'jquery',     })   ] }; 

now in index.js

console.log(typeof $ === 'function'); 

will have a compiled output with something like below passed into the webpackBootstrap closure:

/******/ ([ /* 0 */ /***/ function(module, exports, __webpack_require__) {      /* WEBPACK VAR INJECTION */(function($) {         console.log(typeof $ === 'function');      /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))  /***/ }, /* 1 */ /***/ function(module, exports, __webpack_require__) {      module.exports = jQuery;  /***/ } /******/ ]) 

Therefore, you can see that $ is referencing the global/window jQuery from the CDN, but is being passed into the closure. I'm not sure if this is intended functionality or a lucky hack but it seems to work well for my use case.

like image 41
dtothefp Avatar answered Sep 30 '22 23:09

dtothefp