Webpack is a JavaScript module bundler, or so the blurb goes. This is an apt name for it. However, what I would like to do in this article, is to expand on the true power of Webpack.

This article will not explain how to use Webpack. Rather, explain the reasoning behind it, and what makes it more special than just a bundler.

Webpack is still a Bundler

One of the main reasons for tools like Webpack is to solve the dependency problem. The dependency problem that is caused by modules within JavaScript; specifically Node.js.

Node.js allows you to modularise code. Modularisation of code causes an issue with dependencies. Cyclic dependencies can occur-e.g., A -> B -> A referencing. What tools like Webpack can do, is build an entire dependency graph of all of your referenced modules. With this graph, analysis can occur to help you alleviate the stress of such a dependency graph.

Webpack can take multiple entry points into your code, and spit out an output that has bundled your dependency graph into one or more files.

Webpack is so much more

For me, what makes webpack so special is the great extension points it provides.

Loaders

Loaders are what I like to refer to as mini-transpilers. They take a file of any kind - e.g., TypeScript, CoffeeScript, JSON, etc. - and produce JavaScript code for later addition to the dependency graph Webpack is building.

The power of loaders is that they are not in short supply. Loaders are an extension point. You can create your own loader, and there are 100’s of default and 3rd party loaders out there.

For example, could there be a point where we would ever want to take a statically typed language like C#, and transpile this into JavaScript for Webpack to understand?

The limits are boundless with loaders. Loaders can be chained, configured, filtered out based on file type, and more.

Custom Loader Example

As the webpack documentation explains, a loader is just a node module exporting a function. A loader is as simple as a defined node module that exports a function:

module.exports = function(src) { return src + '

' + 'window.onload = function() {

' + ' console.log("This is from the loader!");

' + '}'; };

This is a trivial example of what a loader is. All this loader is doing is appending a function to write to the console on window load for the current browser session.

With this idea in mind, it becomes apparant that we now have the power to take any source input, and interpret it in anyway we want. So coming back to our previous example, we could take C# as the input, and create a parser that transpiles it into native JavaScript that Webpack expects.

A C# to JavaScript transpiler is a bit far-fetched, and in all honesty slightly pointless, but I hope you appreciate how we can leverage loaders in Webpack to make it more than a bundler.

Plugins

Plugins allow the customisation of Webpack on a more broader scope than file by file like loaders. Plugins are where you can add extra functionality to the core of Webpack. For example, you can add a plugin for minification; Extract certain text from output such as CSS; Use plugins for compression, and so on.

Plugins work by having access to the Webpack compiler itself. They have access to all the compilation steps that can and may occur, and can modify those steps. This means a plugin can modify what files get produced, what files to add as assets, ans so on.

A small example of a plugin is the following:

file: './my-custom-plugin.js' function MyCustomPlugin() {} MyCustomPlugin.prototype.apply = function(compiler) { compiler.plugin('emit', displayCurrentDate); compiler.plugin('after-emit', displayCurrentDate) } function displayCurrentDate(compilation, callback) { console.log(Date()); callback(); } module.exports = MyCustomPlugin;

In this example, we are adding two event handlers to two separate event hooks in the Webpack compiler. The outcome of this is one date that is printed to console just before the assets are emitted to the output directory, and one date after the assets have been emitted.

This plugin can be used in the main Webpack configuration:

var MyCustomPlugin = require('my-custom-plugin'); var webpackConfig = { ... plugins: [ new MyCustomPlugin() ] }

This plugin will now run on the emit and after-emit stages of the compilation process. A good list of compiler event hooks are available on the Webpack website.

The importance of plugins, once again, is that they are an extension point. The way Webpack has been designed is to allow the user to fully extend the core of Webpack. There are many plugins to choose from, and a lot are 3rd party.

With this in mind, a plugin could take all your assets that you require, and compress them with an algorithm. In fact, there is already a plugin for this very thing.

Summary

Webpack is a module bundler, that is what the label says. It takes your dependency graph, and outputs a browser readable format.

However, webpack can be so much more.

What if we could take C# code, and transpile it into JavaScript? What if we could take a YAML configuration file, and create a working program just out of configuration? What if we took an image, and automatically made it cropped and greyscaled?

I think if you start thinking of Webpack as more of a transpiler, not just a bundler, the true power of Webpack can be seen.

Thanks for reading and hope this helps.