Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Integrating Google Closure Compiler with MS Build on a build server

I'm looking into ways of minifying javascript files as part of our CI process, so that we can use the un-minified files in development and have them automatically compressed when deployed to staging and live servers.

This is for an ASP.NET site; we use Hudson as a build server.

I'm intrigued by the Google Closure compiler, and I've come across this .Net MSBuild Google Closure Compiler Task, but it doesn't seem to be very widely used. Are there better options for use with MSBuild, using either Closure or alternative minification tools?

like image 802
Herb Caudill Avatar asked Apr 23 '11 16:04

Herb Caudill


2 Answers

We've been using Closure Compiler for some time now in a .NET-based project.

Initially, we used a simple MSBuild .proj file which directly invoked the Python scripts. For example, we would make deps.js with something like the following:

<PropertyGroup>
  <ScriptDirectory>yourprojectname</ScriptDirectory>
  <ClosureLibrary>closure</ClosureLibrary>
  <CalcDeps>$(ClosureLibrary)\bin\calcdeps.py</CalcDeps>
</PropertyGroup>

<Target Name="Deps">
  <Exec Command="$(CalcDeps) -o deps -p $(ScriptDirectory) -d $(ClosureLibrary) --output_file=$(ScriptDirectory)\deps.js" />
</Target>

The actual build was more complex, but still relatively straightforward (assuming you're MSBuild savvy). We simply used different types of item groups for each relevant part of the script invocation.

<Target Name="Build" DependsOnTargets="Init;FindCompiler">
  <PropertyGroup Condition="'@(Extern)' != ''">
    <Externs>-f --externs=@(Extern, ' -f --externs=')</Externs>
  </PropertyGroup>
  <PropertyGroup Condition="'@(Define)' != ''">
    <Defines>-f --define=@(Define, ' -f --define=')</Defines>
  </PropertyGroup>
  <PropertyGroup Condition="'@(Compile)' != ''">
    <Compile>-i @(Compile, ' -i ')</Compile>
  </PropertyGroup>
  <Exec Command="$(CalcDeps) $(Compile) -o compiled -c $(ClosureCompiler) -p $(ClosureLibrary) -p $(ScriptDirectory) $(Externs) $(Defines) -f @(CompilerOption, ' -f ') --output_file $(OutputFile)" />
</Target>

This was simple enough that we didn't bother looking for a task, or trying to invest in building our own. Closure is quite a fast moving project, so it's good to be in a situation where you're not overly dependent upon any third party build systems, especially one that looks to be unmaintained (the task you linked).

Now, I've been speaking in past tense because our build system has migrated a bit. Specifically, as our project kept growing it became increasingly important to partition different parts of our script code into modules. Doing this with the out-of-the-box Closure scripts would be quite a nightmare. Thus, we decided to move to plovr (http://plovr.com/), which makes partitioning code into modules very simple. plovr is very actively maintained and was created by Michael Bolin, who literally wrote the book on Closure (also highly recommended).

We still wrap this using the same MSBuild file. Basically, the stuff that we were defining in the item groups moves to a plovr-config.js file, and the invocation becomes much simpler as well:

<Target Name="Build" DependsOnTargets="Init;FindPlovr">
  <Exec Command="$(Plovr) build plovr-config.js" />
</Target>

There are some other cool features supported by plovr, like size reports and module graphs, but even without those we're very, very pleased with our current setup.

like image 151
Derek Slager Avatar answered Oct 15 '22 21:10

Derek Slager


The most obvious choice is YUI Compressor, it's stable and reliable.

It has a .Net port: Yahoo! UI Library: YUI Compressor for .Net The ships with an mbsbuild task.

Also, using the original (Java) is just as easy using Exec task, the only drawback is that it has java dependency.

like image 41
George Polevoy Avatar answered Oct 15 '22 21:10

George Polevoy