This post assumes that you know your way around basic Webpack configuration, if not, check out this great official “getting started” tutorial first.

I still remember the first time I decided to check some articles about Webpack after a discussion with one of my colleagues who was really enthusiastic about using it on a customer project.

Because of that, I started reading Webpack’s official documentation, blogs and checking out Github repositories with some seed projects using Webpack as their main build tool. I remember one of those seeds in particular. It had multiple wepack.<target>.config.js files. After viewing their source, it turned out that the only thing they were doing was setting some boolean flags and requiring the main config file which contained a lot of if-s and was really hard to understand. After successfully using Grunt to manage build processes in multiple previous professional projects, this felt like a step back.

Standard Webpack build

In this post we will not get in depth on all the possible parameters, loaders and plugins. Use the official documentation if you are looking for that kind of information. That being said, lets check out how can “Your standard Webpack build Example™” actually look like?

A basic Webpack build

Pretty clean and simple isn’t it? But what will happen if we start to add all the possible configuration? We can end up with something like this…

A bit longer and more complicated Webpack build

As you can see, much more fine tuned configuration made it’s way into our build. Around this stage you will also notice that you actually need to apply some of these configurations conditionally.

For example, let’s say we want to use source maps during development but not in a production build. Or that we want to store the result of our build process in different folders based on if it was for testing or production. And of course, don’t forget about the mandatory minification — again, for production only…

This was the main reason why I started to search for some guides on how to parametrize Webpack builds. I wanted it to be easy to use, understand and navigate. I didn’t really find anything that I liked so I decided to write a build seed myself.

How to parametrize your Webpack build

As I mentioned in the beginning, if-s are not the way to go if you want to keep things clean, simple & scaleable.

Learning form the Ancestors

What I really liked about the Grunt task runner was that it made customization of tasks really simple. You could define default options and then specify multiple targets per task. Every target then inherited these default options and merged them with it’s own target specific options. Executing it was simple too. The syntax was something like <task>:<target> which we can illustrate with example like grunt jshint:dev.

The goals

Ideally, we would like to achieve a build process that enables us to define specific targets, which are easy to execute. Targets should be highly customizable in terms of their count and content. And all of this while maintaining minimal code-duplication.

How to parametrize the Webpack Build

By following the already proven approach to parametrization of Grunt task runner (and surely also many other build tools) our build configuration needs to contain some default configuration and then specific configurations which will extend that default configuration. Besides that we need a way to specify target which we would like to run.

Default configuration — just store everything what would be normally exported from webpack.config.js in a variable

— just store everything what would be normally exported from webpack.config.js in a variable Specific configuration — create a Javascript object to store the specific configurations per target

Specify build target — retrieve target from command line arguments, retrieve target specific configuration and merge it with default configuration

Anatomy of a parametrized Webpack build

The only thing which is now missing is to add some real default and per target configuration to our build. Following example was taken from React Typescript Webpack Github repository and supports DEV, BUILD and DIST targets.

Example of full parametrized Webpack build

How to run the specific build?

This one is straight forward. You can use command line directly but I personally personally prefer using npm scripts. The npm and package.json became ubiquitous and are considered default for any frontend / Javascript related project so why not to use them?

We have specified the scripts and now we can just simply execute desired script by using npm start or npm run dist.

We are calling “npm start”, build process then prints info about selected build and proceeds with building itself…

Conclusion

I consider Webpack a major step forward because it abstracted away stuff which had to be done / configured manually with solutions like Grunt or Gulp. You’ll get advanced stuff like cache busting out of the box (by using [hash] or [chunkhash]) or generation of index.html based on provided template (by using HtmlWebpackPlugin). The only thing that is currently missing is more examples on how to configure your Webpack build for larger enterprise projects. And that’s exactly what I tried to provide you with in this post…

That being said it is possible that in the future all the build tools become obsolete after introduction of HTTP2 and native support of Javascript modules, but until then, use Webpack.

Cool, that’s all for today!

Don’t forget to recommend this article if you found it helpful and check out other interesting front-end and Angular JS related posts like Proper testing of Angular JS applications with ES6 modules or Model pattern Angular 1.X.

Follow me on Twitter to get notified about the newest blog posts and useful front-end stuff.