When you have a dependency that does not export itself properly, you can use the
exports-loader to force it to export the pieces of the file that you need.
Here, we have a module called leftpad that exposes itself on the window. We're using it by importing it and expecting it to export itself, so that we can use it like a regular ES6 module.
If we go ahead and run our application, we're going to get an error when we run that code. If we open up our console here, we're going to see pipe error. That's because leftpad is not defined because it's not actually exporting anything.
This would be pretty easy to fix if we can simply say module.exports = leftpad. We can refresh here and say sweet. Let's assume for a moment that we don't have control over this module.
How can we force this module to expose the things that we need it to expose, so that we can use it like a regular ES6 module? We can do this with the exports loader.
Let's go ahead and fix this code back up to where it was before. We'll npm install as a dev dependency the exports loader. We can verify that we have that installed here in our package.json. We'll go back to this module import. We'll use Webpack's enhanced import statement, so that we can test things out.
We'll say exports, and that will reference the exports loader. We'll add the exclamation point there to indicate that this is indeed a loader. We'll add a query string here with leftpad. That will tell us to export the leftpad variable that's in our module.
We'll go ahead and add an eslint statement line there, so that we don't have that red line there. There's actually an eslint plugin that you can use that can understand Webpack module imports. I recommend you go look that up.
If we run npm start to start up our server again, then we refresh our browser, we can say sweet, and everything is working fine. We're using the exports loader to ensure that what is being exported is what we expect.
If we look at the leftpad file, we're actually seeing at the bottom here, a module exports is added. This is being added from the exports loader.
This still isn't solving the problem of polluting the global namespace on window. We're still getting window.leftpad there. We can see that still here. We're going to actually also use the imports loader, so that we can make sure that this module doesn't pollute the global namespace.
To do this, we'll npm install as a dev dependency the imports loader. In our enhanced import here, we'll also add imports as another loader. The query will be window is assigned to an empty object.
If we run npm start and refresh our browser, we'll see that now, at the very top of the file, window is being assigned to an empty object. If we open up our console here, we can say window.leftpad, and we get undefined.
We're not polluting the global namespace. We're exporting this module as a regular ES module, so that we can use it throughout the rest of our code base like a regular module.
There's one last thing that we're going to do here. That is we don't have to do this crazy import statement everywhere we're using this module. We're going to actually extract this into our Webpack config.
We'll go to our Webpack config and add another loader. The test will be directly to this specific module. We'll add a loader here. We'll simply paste in what we had before. We'll remove that last exclamation point. This is going to work fine.
I don't like the way that this looks with multiple loaders. Each one has a query. We're going to use the loaders property instead, which accepts an array of loaders. Instead of being separated by an exclamation point, they're two separate elements.
If we restart our server, we can refresh the browser, and we'll see things still work. We can open up our leftpad. We still see the imports from the imports loader. We see the exports from the exports loader.
In review, to fix up a module that we don't actually have access to, all that we needed to do was add the exports loader dependency. Then, we added that to our loaders for this specific module.