10

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?

Herb Caudill
  • 50,043
  • 39
  • 124
  • 173

4 Answers4

8

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.

Derek Slager
  • 13,619
  • 3
  • 34
  • 34
  • Thanks for the detailed answer. We'll give this a try. – Herb Caudill May 04 '11 at 20:18
  • If anyone's interested, I wrote a quick and dirty MSBuild task for the closure compiler. The main point of interest is that it uses a .Net version of the compiler (using IKVM), so it runs in-process - https://github.com/unintelligible/ClosureCompilerMsBuild (it also has the option to submit to the hosted compiler, though the in-process version is obviously quite a lot quicker.) – zcrar70 Jul 07 '11 at 14:41
  • I'm a total noob to MSBuild but I can't figure out how to make your code there work with plovr. What do I populate $(Plovr) with. I've tried the direct line `` but keep getting exit code 1 when I publish my project. – Ally Mar 28 '14 at 21:07
1

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.

Community
  • 1
  • 1
George Polevoy
  • 7,450
  • 3
  • 36
  • 61
1

There's SquishIt Details which is a runtime compressor, but done quite well.

Scott Weinstein
  • 18,890
  • 14
  • 78
  • 115
0

You should see a very similar question that I answered at Using Microsoft AJAX Minifier with Visual Studio 2010 1-click publish. You should be able to use the details there to solve your problems here.

Community
  • 1
  • 1
Sayed Ibrahim Hashimi
  • 43,864
  • 17
  • 144
  • 178