Building Per-Environment Configuration in Your Webpack + TypeScript Apps

Robert McLaws
CloudNimble
Published in
4 min readSep 22, 2018

It’s no secret that Webpack has a rather extreme learning curve. Having spent nearly 20 years in the world of ASP and ASP.NET, getting my head around a compiler powered by the anything-can-be-anything world of JavaScript has been quite a challenge.

In building out BurnRate, yesterday’s challenge was to complete our move to a simpler domain (we used to be startupburnrate.com, now we’re burnrate.io) and update our config files. In my original setup, I was trying to let ASP.NET Core handle the distinction on which environment we were in. That was because my initial prototype started out back in the .NET Core 1.0 + Webpack 1.0 days. Since then, we’ve had 5 .NET Core releases, and 3 major releases of Webpack. So it was time to do it right.

My search brought me to this StackOverflow thread, which provides a number of different options. I felt this one got the closest to what I was looking for, but for some reason I couldn’t get it work. So in re-reading the thread, I saw someone mention the NormalModuleReplacementPlugin. The example in the docs looked convoluted, but it might do the trick.

There were a couple problems with the approach initially. First, the current example is a bit obtuse. I’d rather have the examples be real-world situations than contrived. In addition, the documentation had not been updated with the new module.exports = (env, args)=> {} method signature in Webpack 4. Eventually i got it working, and here’s an excerpt of what my webpack.config.js looks like now:

You can also see it here. The config folder structure looks like this:

Separate configs for each environment

I ran into an unexpected problem, however, when I went to actually use the config in my app. TypeScript couldn’t find the file, and kept complaining.

Thanks, TypeScript. Thanks a lot.

I was hoping maybe Webpack would ignore this, but that didn’t last long.

Yeah, your build system won’t like this.

I thought I was going to be stuck on this with no recourse… but as a hail mary, I tried something, and it worked. The solution? Give TypeScript what it wants: a file at ./config/config-APP_TARGET.ts that matches your config schema. For BurnRate, the contents of the file look like this:

export default {
clientId: '',
domain: '',
callbackUrl: '',
apiUrl: ''
};

One more try, and…. Success!

Take that, Webpack!
Final config folder structure.

Sure, my folder structure is not quite as awesome now, but at least it works.

Open source being as awesome as it is, I filed a Pull Request with the Webpack docs to make sure that the article is easier to understand, has a real-world example, and warns people about the issues with TypeScript. We’ll see if it passes muster.

BONUS ROUND: .csproj Configuration

If you want to have the different configurations build in different environments, you can modify your project file as follows (changes highlighted in yellow):

Then, make sure you create those configurations in your Solution and Project settings, and pass the right value in through your build system.

There you have it… hopefully this saves you some time. Be sure to leave feedback below and I’ll be happy to answer questions. Until next time!

--

--

Robert McLaws
CloudNimble

Founder & CEO of BurnRate (@BurnRate_io). Serial entrepreneur. Former Microsoft MVP. @dotnetfdn member. Helping founders build amazing businesses.