I've been searching for a way to describe what the DefinePlugin actually does. The docs say*:
* Actually that should read "used to say". I've made some changes to the official docs.... (Surprisingly easy to do that by the way; it's just a wiki you can edit at will.)
Define free variables. Useful for having development builds with debug logging or adding global constants.
I think I would describe it thusly: the DefinePlugin allows you to create global constants which can be configured at compile time. I find this very useful for allowing different behaviour between development builds and release builds. This post will demonstrate usage of this approach, talk about what's actually happening and how to get this working nicely with TypeScript.
For our example we want to define 2 global constants; a string called
__VERSION__ and a boolean called
__IN_DEBUG__. The names are deliberately wacky to draw attention to the fact that these are not your everyday, common-or-garden variables. Them's "special". These constants will be initialised with different values depending on whether we are in a debug build or a production build. Usage of these constants in our code might look like this:
__IN_DEBUG__ is set to
true this code would log out to the console the version of the app.
To introduce these constants to webpack we're going to add this to our webpack configuration:
What's going on here? Well, each key of the object literal above represents one of our global constants. When you look at the value, just imagine each outer
JSON.stringify( ... ) is not there. It's just noise. Imagine instead that you're seeing this:
A little clearer, right?
__IN_DEBUG__ is given the boolean value
__VERSION__ is given the string value of
1.0.0. plus the ticks off of
Date.now(). What's happening here is well explained in Pete Hunt's excellent webpack howto: "definePlugin takes raw strings and inserts them".
JSON.stringify facilitates this; it produces a string representation of a value that can be inlined into code. When the inlining takes place the actual output would be something like this:
And if you've got some UglifyJS or similar in the mix then, in the example above, this would actually strip out the statement above entirely since it's clearly a NOOP. Yay the dead code removal! If
false then (perhaps obviously) this statement would be left in place as it wouldn't be dead code.
The final piece of the puzzle is making TypeScript happy. It doesn't know anything about our global constants. So we need to tell it:
And that's it. Compile time constants are a go!