Split your Webpack config up by module (for ReactJS)

Difficulty: intermediate

It’s no secret that properly setting up a ReactJS project is an insanely complex exercise in tedium and frustration.

ReactJS “Hello world”

A lot of this complexity comes from Webpack, without which it’s pretty much impossible to do anything serious with ReactJS.

It gets worse if you’re following 12-factor app principles…which you should if you don’t like tearing your hair out while fighting with unstable 20-hour deployments only to have everything mysteriously crash and burn in production 2 days later. This of course also means inclusion of code testing (not necessarily test-driven development), adding further layers of complexity. As a result, a proper webpack setup ends up having to cover ever-so-slightly different setups for a development, testing, and production environments.

If you use a compile-to-JS language (I’m partial to Typescript — but that’s a story for another day), it gets even more complicated, since yo sometimes require slightly different transpilation configurations for each environment. Not to mention PostCSS (I also recommend it), which by nature requires intensive configuration.

Your Webpack configuration files can end up being 100s of lines long. The classic solution is to split them up by environment, having each environment-based config also pull in a shared config file. This works to a certain extent, but even this falls apart if a project gets large enough.

I propose an alternative solution, with which I have had great success: taking a page from Grunt, Gulp, and other task runners, I split my Webpack configuration into modules based on functionality rather than environment. For example (you don’t have to read all of this):

This is admittedly a lot to digest (feel free to steal it of course) , but the gist of it is this: any individual properties on the Webpack configuration object that grow too lengthy get moved into their own files.

The advantages have been innumerable (or rather…there have been 6):

  1. Infinite scaling. No matter how big the configuration gets, it can always be split down even more. Splitting by environment leaves you with a hard upper limit on how much you can cut it up. I’ve never found it necessary to add more than one file for a property, but it’s certainly possible.
  2. Easy navigation. I know exactly where to find the Webpack option I’m looking for based on the filename — no need to sift through both webpack.shared.config.js and whichever environment I’m seeking. I have a single, say, 40 line file to search rather than two 400-line files. This advantage is reduced if you have to split individual properties into multiple files, but it’s still preferable, as you still have a lot fewer lines to sort through.
  3. Related to both previous points, it’s just a lot cleaner and easier to work with smaller files. Especially in a language like Javascript that naturally tends towards disorganization.
  4. Reduced likelihood of breaking unrelated functionality in your Webpack setup. If you’re only editing one aspect of your Webpack setup and the build starts failing, you can be (fairly) confident the issue lies in the specific module you just edited. It’s far too easy to break other components of your Webpack build.
  5. Load order. This is perhaps the most important. I’ve noticed that if you need to do operations and calculations on your Webpack config, Webpack can sometimes export your build before all of them are completed. Since require’ing is synchronous in NodeJS, this becomes a much smaller potential issue if any components requiring such calculations are imported.
  6. It fits in much more nicely with the modular nature of ReactJS and the ecosystem around it. After dealing with nicely separated concerns in your UI and client-side data store, dealing with giant single-file monoliths in your build system can feel like returning to the dark ages.

Note that this is definitely overkill if your project is small and simple, but it’s worth trying out if your Webpack configuration starts to get overwhelming. When that happens, this can be a lifesaver, and I highly recommend it. Of course, YMMV, and there’s no accounting for taste, but I’ve had a lot of success with it, and it’s been well-received by co-workers as a vast improvement in build configuration readability. After all, if you’re working in a team, you’re writing code for humans AND computers (unless you’re an asshole), and modularity is a great way to reduce the pain of reading one another’s code.