How to create a YUI Compressor MSBuild Task
Recently for IdeaPipe I have been looking for ways to deliver my content more quickly and reduce unnecessary bandwidth use.
According to Yahoo’s Performance Team more than half of the viewers of the Yahoo websites start with an empty cache, which means the browser has to download all the resources for the first time. This combined with a high traffic website and unneeded white space and comments can really add up to a significant bandwidth use. There are many popular ways to minify your static content tax on your bandwidth, using many popular tools, as described in this excerpt from Yahoo:
In terms of code minification, the most widely used tools to minify JavaScript code are Douglas Crockford’s JSMIN, the Dojo compressor and Dean Edwards’ Packer. Each of these tools, however, has drawbacks. JSMIN, for example, does not yield optimal savings (due to its simple algorithm, it must leave many line feed characters in the code in order not to introduce any new bugs).
The goal of JavaScript and CSS minification is always to preserve the operational qualities of the code while reducing its overall byte footprint (both in raw terms and after gzipping, as most JavaScript and CSS served from production web servers is gzipped as part of the HTTP protocol).
The cream of the crop seems to be a tool Yahoo developed to deliver its own static text content scripts and styles, the YUI Compressor:
The YUI Compressor is JavaScript minifier designed to be 100% safe and yield a higher compression ratio than most other tools. Tests on the YUI Library have shown savings of over 20% compared to JSMin (becoming 10% after HTTP compression). Starting with version 2.0, the YUI Compressor is also able to compress CSS files by using a port of Isaac Schlueter’s regular-expression-based CSS minifier.
The YUI Compressor is a Java JAR file that can be download from Julien Lecomte Blog.
The YUI Compressor yielded exceptional results, however it was missing one thing. Integration in to my build and deployment process. In IdeaPipe I use a MSBuild script to compile, manipulate, and prepare for publishing. So naturally I built a MSBuild Task to minimize my JavaScript and CSS files.
The magic actually happens by invoking Java in an external process for each file passed in to the task.
Process process = new Process();
process.StartInfo = new ProcessStartInfo {
FileName = @"c:\program files\java\jdk1.6.0_06\bin\java.exe",
Arguments = String.Format(
@"-jar ""C:\development\tools\yuicompressor-2.3.5.jar"" --type {0} --charset utf8 {1} -o ""{2}"" ""{3}""",
type,
ShowWarnings ? "--verbose" : String.Empty,
newFile,
oldFile
),
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardOutput = true,
RedirectStandardError = true
};
process.Start();
process.WaitForExit(5000);
Then I read the warning from the standard error output and send them back to Visual Studio as a compile warning if the ShowWarning property is true.
string[] warnings = process.StandardError.ReadToEnd()
.Replace(”\r”, String.Empty)
.Split(new string[] { “\n\n” }, StringSplitOptions.RemoveEmptyEntries);
foreach(string warning in warnings)
Log.LogWarning(null, null, null, oldFile, 1, 1, 1, 1, FormatWarning(warning), null);
To integrate this in to my MSBuild script I had to first register my task:
<UsingTask TaskName="ManagedFusion.Build.YuiCompress" AssemblyFile="$(ProjectDir)..\ManagedFusion.Build\bin\$(ConfigurationName)\ManagedFusion.Build.dll"/>
Then setup my ItemGroup for the files:
<ItemGroup> <JavaScriptContent Include="$(SourceWebPhysicalPath)\**\*.js" /> <CssContent Include="$(SourceWebPhysicalPath)\**\*.css" /> </ItemGroup>
Then finally I setup my task to perform the minimization against the JavaScript and CSS files seperately:
<Target Name="AfterBuild"> <!-- do other stuff to prepare for publishing --> <YuiCompress Files="@(JavaScriptContent)" Type="JS" /> <YuiCompress Files="@(CssContent)" Type="CSS" /> </Target>
You can easily incorporate this in to your own MSBuild scripts or even your Visual Studio Project which is just an MSBuild file for compiling your source code for the project. I have included my source code below:
Download: YUI Compressor MSBuild Task Source
Note: There are a couple of static paths to be on the look out for and modify as necessary for your own code. In my code the Java runtime is loaded at c:\program files\java\jdk1.6.0_06\bin\java.exe and the YUI JAR is located at C:\development\tools\yuicompressor-2.3.5.jar.
Update (2008-5-21): Thanks George, apparently IIS doesn’t like serving straight C# files. So I added the code to my Coder Journal Source Control, so that it can be downloaded from there.
Tags: CSS, Java, JavaScript, MSBuild, Yahoo, YUI
Social: |
| View blog reactions
Subscribe via Email
May 18th, 2008 at 6:30 pm
How to create a YUI Compressor MSBuild Task…
You’ve been kicked (a good thing) - Trackback from DotNetKicks.com…
May 18th, 2008 at 9:03 pm
There is a JSCompress task at the MSBuild Community Tasks Project (http://msbuildtasks.tigris.org).
This is based on JSMin (http://javascript.crockford.com/jsmin.html) which is actually available now in several languages, including C#.
Sayed Ibrahim Hashimi
http://www.sedodream.com
May 19th, 2008 at 6:05 am
Sayed,
Thanks for the tip. I actually prefer YUI Compress over JSMin. I will be doing a future article on the differences in the compression using a couple of the popular tools. Plus YUI Compress also does CSS compression.
May 20th, 2008 at 5:37 am
Great work, Nick!
I’ve been using my own C# port of the CssMin inside YUI (http://www.dimebrain.com/2008/03/a-better-css-mi.html), but haven’t had the time to port the Javascript parser aspects of the YUI to perform the analog for JS files.
Daniel
May 22nd, 2008 at 5:09 pm
Good post .. but it has one serious flaw IMO. It requires JAVA to be on the build server
Ouch.
I downloaded the YUI Compressor a few days ago (before i found this article) to see if it could be converted to C# .. so msbuild can then run it nicely … but that’s WAAAYYYY over my head
We really need a codeplex project that does this -> converts the YUI Compress to c#. can be done ….
i do agree that YUI Compress has the best compression for both css and js.
-PK-
May 22nd, 2008 at 5:18 pm
I looked at the YUI Compressor code. It is definitely doable in C# with out much rewriting. But definitely more time than I wanted to spend on the thing. However you might want to try running the Java to C# converter over the source code and see how close you get.
May 30th, 2008 at 10:10 am
[...] YUI Compressor MSBuild task: Nick Berardi at Coder Journal put together a nice tutorial on using YUI compressor as part of his MSBuild workflow. [...]