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









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. [...]
July 15th, 2008 at 8:47 pm
MSBuild tasks si Poor man backup…
…
July 25th, 2008 at 7:56 am
This got me close, but since I’ve never written an MSBuild script before it was just a tease. Have no clue how to make use of this. Scoured the internet too and found nothing very helpful about MSBuild.
July 25th, 2008 at 1:24 pm
Fine great article !
How do you add this into VS Project ? Can do this be done after Publish website task ?
July 26th, 2008 at 7:13 am
What you need to do is open the VS Project in a text editor, and edit the necessary code as outlined above. Or you can right click on the project, click Unload Project, then right click on the grayed out project and click edit. This will bring up the project’s XML MSBuild script, and you can edit it from there. Or alternatively you can use this in the Microsoft Web Deployment Build Script, which is personally what I do.
http://www.microsoft.com/downloads/details.aspx?FamilyId=0AA30AE8-C73B-4BDD-BB1B-FE697256C459&displaylang=en
September 5th, 2008 at 7:57 am
There is a port if YUI for .NET in C# on codeplex. So far, so good. No need for Java.
http://www.codeplex.com/YUICompressor
September 18th, 2008 at 9:39 am
Hi,
I’m trying to implement this and I’m having some trouble. Where do I want to place the YuiCompress.cs file? Should this be in its own project then linked into the project I need it for? Also I’m not sure I understand the AssmeblyFile property of the UsingTask tag should be set to.
Thanks
Andre
September 28th, 2008 at 8:40 pm
Andre -> use the .dll available from: http://www.codeplex.com/YUICompressor
it does everything u want AND doesn’t require java (cringe). It’s all good.
September 29th, 2008 at 3:46 am
PK, I tried it and it didn’t compress my JavaScript in the same way as the YUI compressor. It caused a couple of errors in the JavaScript too. I will try again in a couple of months maybe you will have the problems fixed.