The other day, I took a look at calling Google's Closure compiler from a ColdFusion context. The code, in that example, was fairly complex, involved a lot of Java-Casting, and required a good deal of trial and error to get running. After it was complete, I figured it would be nice to create a ColdFusion component facade for the Closure compiler that would greatly simplify the interactions with the Java code.
Furthermore, unless a given method has to return a significant value (ie, is a "Getter" method), it returns the ClosureCompiler.cfc reference such that the vast majority of methods can be chained together to tell a story. So far, here are the public methods that I have created:
- addExternContent( filename, content )
- addExternFile( filepath )
- compile() :: String
- getErrors() :: Array
- getWarnings() :: Array
- hasErrors() :: Boolean
- hasWarnings() :: Boolean
- setInputDelimiter( inputDelimiter )
- setPrettyPrint( isPrettyPrint )
- stripNamePrefix( namePrefix )
- stripNamePrefixes( namePrefixes )
- stripNameSuffix( nameSuffix )
- stripNameSuffixes( nameSuffixes )
- stripType( type )
- stripTypePrefix( typePrefix )
- stripTypePrefixes( typePrefixes )
- stripTypes( types )
While the ClosureCompiler.cfc doesn't expose the underlying compiler options object (at this time), it does expose three methods that correspond to the primary levels of compilation aggressiveness:
These three methods are meant to be used in a mutually-exclusive manner. You wouldn't want to call more than one of these methods for any given compilation event.
To see how the ClosureCompiler.cfc ColdFusion component can simplify the use of Google's Closure compiler, let's take a look at one of the demos that comes with the project. In this case, I'm going to run the "Advanced Optimizations" example since that will most closely correspond to my previous blog post:
As you can see, the ClosureCompiler.cfc methods tell a story that is fairly easy to understand.
NOTE: The stripConsoleDebugging() is a facade method for stripping all the "types" associated with the "console" and "window.console" usage. Essentially, it removes all references to console logging within the compiled code.
In most of the demos in the ClosureCompiler.cfc project, I am assuming that the compiler.jar file is part of the ColdFusion class paths; but, the ClosureCompiler.cfc is architected such that this assumption can be overridden. Internally, all of the Java object creation and initialization is quarantined within individual private methods. This means that if you need to use an external class loader, all you have to do is sub-class the ClosureCompiler.cfc and override the "create" methods for the various Java objects. In fact, the ClosureCompiler.cfc project comes with a "loader" example that uses Mark Mandel's famous JavaLoader.
As I become more familiar with the Closure compiler, I am sure that the features of this ColdFusion facade will expand; but, I intend to keep it as simple as possible. Probably, I'll end up adding methods to expose the underlying Java objects in case someone needs to get much more granular with their interactions.
Want to use code from this post? Check out the license.