Fixing issues that arise from advanced compilation mode with the Closure compiler can be tricky to debug. Referencing external libraries can be troublesome when the compiler doesn’t know about them. However, even when externs are sucessfully configured, things can go wrong… Here’s a quick lesson learned from fixing a function that my coworker identified as broken after advanced compilation was used.
This function uses the
library to count the length of a tweet after link shortening by calling
twttr.txt.getTweetLength(). Our misbehaving ClojureScript function looked
1 2 3 4
Pretty straight forward: it checks to see if the external script has been before calling a function that it provides or falls back counting the number of characters.
Let’s see what the advanced compiled code looks like:
1 2 3
Spot the issue? The optimizer munged
window.de even though
the extern was configured.
As you may have guessed by now,
externs are not recognized when referenced through
It makes sense, but may not be immediately obvious, especially when debugging.
After all, this function only broke after advanced compilation was used.
The fixed function:
1 2 3 4
Note the use of
cljs.core/exists?, to test whether a variable exists. Simply
js/twttr as boolean when the script hasn’t been evaluated would throw
The advanced compiled result looks like:
1 2 3
Lessons learned: reference externs directly from
js/ and, more generally,
js/window unless you’re accessing one of its actual properties.
Using the advanced compiler can bring tons of little nuances like this. They’re often things you may not consider when writing code and thinking about its correctness.
In the end, a rather simple lesson learned, but hopefully it’s helpful to others.