We love jQuery – many things are now easier/cleaner/more testable using JavaScript rather than ASP.NET (that statement blows my mind, but it's true!). Because of that, we have a lot of JavaScript code. Ideally, we want to develop using readable JavaScript files (even 3rd party files) and deploy compressed/obfuscated code. Our solution has simply been to apply a post-build task to our project. Here's what we did.
First, we use the .NET port of Yahoo's YUI Compressor, freely available on CodePlex. (note, the YUICompressor comes with an MSBuild Task, which you can use in addition (or as an alternative) to my approach).
We took the library and wrapped it into a simple console application which takes 2 inputs – the input directory containing the debug javascript files, and the target output directory to place the compressed files in:
using System;
using System.IO;
using Yahoo.Yui.Compressor;
public class Program
{
public static void Main(string[] args)
{
var input = args[0];
var output = args[1];
if (!Directory.Exists(output))
{
throw new ArgumentException(string.Format("The output directory '{0}' doesn't exist", output));
}
if (Directory.Exists(input))
{
CompressDirectory(input, output);
}
else if (File.Exists(input))
{
CompressFile(input, output);
}
else
{
throw new ArgumentException(string.Format("{0} isn't a known directory or file", input));
}
}
public static void CompressDirectory(string root, string outputDirectory)
{
Console.WriteLine("Compressing all .js files within: " + root);
foreach (var file in Directory.GetFiles(root, "*.js"))
{
CompressFile(file, outputDirectory);
}
foreach (var directory in Directory.GetDirectories(root))
{
//skip .svn folders and what not
if ((new DirectoryInfo(directory).Attributes & FileAttributes.Hidden) != FileAttributes.Hidden)
{
var newOuputDirectory = outputDirectory + directory.Substring(root.Length) + "\\";
CompressDirectory(directory, newOuputDirectory);
}
}
}
public static void CompressFile(string file, string outputDirectory)
{
var name = Path.GetFileName(file);
Console.WriteLine("Compressing file: " + name);
using (var sw = new StreamWriter(outputDirectory + name))
using (var sr = new StreamReader(file))
{
var compressed = JavaScriptCompressor.Compress(sr.ReadToEnd(), false);
sw.Write(compressed);
}
}
}
We compile our console application and place the .exe somewhere relative to our main solution. Next, we open our project's properties, go into the Build Events tab, and enter the following into the "Post-build event command line" box:
$(SolutionDir)..\Tools\YUICompressor\YUICompressor.exe $(ProjectDir)\content\js\debug\ $(ProjectDir)\content\js\release\
Now, whenever we build, all of our .js files within content/js/debug/ get compressed and moved to content/js/release/.
The last step is to use an HtmlHelper expression method to include our javascript file:
public static string IncludeJs(this HtmlHelper helper, string javascriptFile)
{
#if DEBUG
var subfolder = "debug";
#else
var subfolder = "release";
#endif
var path = string.Format("{0}/Content/js/{1}/{2}.js", _applicationPath, subfolder, javascriptFile);
return string.Format("<script type=\"text/javascript\" src=\"{0}\"></script>", path);
}
Which can simply be used like:
<%= Html.IncludeJs("jquery") %>
<%= Html.IncludeJs("main") %>
<%= Html.IncludeJs("jquery_validate") %>
Posted
Mon, Dec 29 2008 11:14 AM
by
karl