ProvidePlugin()
Looks like a commonly used approach. There is a gist about it, showcasing how to include whatwg-fetch polyfill into a Webpack build. Lots of answers on StackOverflow use it here and here.
new webpack.ProvidePlugin({ '$': 'jquery', 'jQuery': 'jquery', 'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch' })
entry: [...]
I was a little surprised by this approach when I discovered it in this gist but it works just as well.
entry: [ 'babel-polyfill', 'whatwg-fetch', 'jquery', 'webpack-hot-middleware/client', path.join(process.cwd(), 'app/app.js') ],
ProvidePlugin()
entirely.import
This one is very straightforward, see this app.js example. This file is an entry-point to a React application.
/** * app.js */ import 'whatwg-fetch'; import 'babel-polyfill'; import 'jquery';
Observation: Between all three approaches, I haven't noticed any changes in the bundle size.
Is there one recommended way of handling global libraries with Webpack (and React)? Would any of these solutions cause a problem down the road with server-side rendering?
Thanks!
Webpack externals tell Webpack to exclude a certain import from the bundle. Often externals are used to exclude imports that will be loaded via CDN. For example, suppose you are implementing server-side rendering with Vue and Express, but your client-side code imports Vue via a CDN.
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.
Webpack supports the following module types natively: ECMAScript modules. CommonJS modules.
I wouldn't recommend exposing libraries as global unless you really do need it, i.e. the point of a module system is to explicitly declare dependencies, e.g.
// app.js import $ from 'jquery'; $.ajax(...);
If you absolutely do need jQuery on the global because a third party script requires it on your page or maybe for debugging in the console then here's some information regarding the approaches you've listed:
ProvidePlugin
The ProvidePlugin won't expose jQuery on the global and is really designed to fix third-party modules which incorrectly rely on the presence of a global module so I wouldn't recommend this, e.g.
// app.js $.ajax(...);
Is effectively transpiled into:
// app.js require('jquery').ajax(...);
Entry & Top level import
These approaches won't work for a regular UMD module such as jQuery as jQuery is smart enough not to expose itself on the global when being loaded by a commonjs / amd / es6 aware loader.
These two approaches are however ideal for modules with side effects such as the babel-polyfill
/ whatwg-fetch
because they don't export anything, they inherently mutate the global environment.
My recommendation for jQuery is therefore to use the expose-loader
which is designed to expose a modules export globally, e.g.
// webpack.config.js { module: { loaders: [ test: require.resolve('jquery'), loader: 'expose-loader?jQuery!expose-loader?$' ] } }
You then still need to import it in your app code:
// app.js import $ from 'jquery'; $.ajax(...)
But it's available on the global for other scripts on the page to access if absolutely necessary:
// console window.$ window.jQuery
NOTE: Technically you could just import 'jquery'
once in your entry point when using the expose loader and then rely on the global in other modules.
As I say however, it isn't really advisable to expose a module if you don't need to, even if you happen to currently use it in every other module.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With