# Mostly clueless

but curious to find out
Aug 11, 2015

# Parameterizing ClojureScript Builds

Just like with most server side software we often want to make minor changes to the behaviour of the code depending on the environment it's run in. This post highlights language and compiler features of ClojureScript making parameterized builds easy peasy.

On servers environment variables are a go-to solution to set things like a database URI. In ClojureScript we don't have access to those. You can work around that with macros and emit code based on environment variables but this requires additional code and separate tools.

With ClojureScript 1.7.48 (Update: There was a bug in 1.7.48 `goog-define`. Use 1.7.107 instead.) a new macro `goog-define` has been added which allows build customization at compile time using plain compiler options. Let's walk through an example:

    (ns your.app)
    (goog-define api-uri "http://your.api.com")

`goog-define` emits code that looks something like this:

    /** @define {string} */
    goog.define("your.app.api_uri","http://your.api.com");

The `goog.define` function from Closure's standard library plus the JSDoc `@define` annotation tell the Closure compiler that `your.app.api_uri` is a constant that can be overridden at compile time. To do so you just need to pass the appropriate `:closure-defines` compiler option:

    :closure-defines {'your.app/api-uri "http://your-dev.api.com"}

Note: When using Leinigen quoting is implicit so there is no quote necessary before the symbol.

Note: Sometimes for debugging you may want to pass the Closure define as a string. If you decide to do so make sure it matches the string in the `goog.define` call in your emitted Javascript (i.e. account for name mangling).

Prior to 1.7.48 you could annotate things with `@define` but without using `goog.define` overriding those defines is not possible when using optimizations `:none` effectively making them much less useful.

### Under the hood

When compiling with `:advanced` optimizations the Closure compiler will automatically replace all occurrences of your defined constants with their respective values. If this leads to unreachable branches in your code they will be removed as dead code by the Closure compiler. Very handy to elide things like logging!

Without any optimizations (`:none`) `goog.define` makes sure the right value is used. There are two global variables it takes into account for that: `CLOSURE_UNCOMPILED_DEFINES` and `CLOSURE_DEFINES`. When you override the default value using `:closure-defines` the ClojureScript compiler prepends `CLOSURE_UNCOMPILED_DEFINES` with your overridden define to your build causing `goog.define` to use the value in there instead of the default value you defined in your source files.

For details see the source of goog.define.