ninja star Compressing JavaScript and CSS on The Fly

by Michael Ceranski, posted on February 11 2010

One of my favorite features of BlogEngine.NET is that it compresses JavaScript and CSS on the fly. Traditionally, most people run their css and js files through a minifier before they deploy code to production. Minifiers effectively strip out white space and comments so you can reduce the size of your files. By compressing these files you will reduce the size of each page request without impacting the functionality.

Although minifiers are great, they do represent an extra step that you have to take each and every time you deploy your code. Of course, you can automate the process by using post-build events in your IDE or by developing some scripts. However, the process I am about to show you will require zero effort on your part once implemented. The only downside to this technique is that you may increase your CPU utilization on your web server from running the "compression" algorithms. So it may be wise to monitor your CPU activity before and after you implement this code.

Before going any further, I want to point out that this solution is based entirely on the BlogEngine.NET source code. BlogEngine.NET uses the Microsoft Reciprocal License. If you are not familiar with the license but you are interested in using this code then please read the License page to make sure you are in compliance with the rules.

Ok, now that the legal obligations are out of the way, lets talk about the code. In order to implement this functionality I downloaded the BlogEngine.NET source code and copied out three class files which were the CSSHandler.cs, JavaScriptHandler.cs and CompressionModule.cs.  I placed these files into the appropriate folders in my ASP.NET application as shown in the image below:

image

These class files did have a few sections of code that were specific to BlogEngine.NET so I had to strip them out to get my project to compile. Most of them were really just checking to see if compression was turned on or off because this is a configurable setting in BlogEngine.NET. I basically removed any conditional logic which checked if compression was enabled. This is really not a big deal because you can selectively choose what to compress from your HTML source; which I will demonstrate later on. Just for you information, I changed this code...

if (BlogSettings.Instance.EnableHttpCompression){
   CompressionModule.CompressResponse(context);
}


to this...

CompressionModule.CompressResponse(context);

Once I got the source to compile, I moved on to the next part of the job which is registering the HttpHandlers in the web.config file. By registering the handlers you are effectively telling ASP.NET that anytime you encounter a URI with a "css.axd" or "js.axd" use the custom handlers:

<httpHandlers>
...
   <!-- to compress css and js files -->
   <add verb="*" path="css.axd"type="CodeCapers.HttpHandlers.CssHandler" validate="false"/>    
   <add verb="*" path="js.axd" type="CodeCapers.HttpHandlers.JavaScriptHandler" validate="false"/>
</httpHandlers>

Finally, if you are using ASP.NET MVC, then you will also need to add a couple of lines to your Global.asax.cs file. This tells MVC to ignore requests made to css.axd and js.axd. In other words, we want MVC to get out of the way so the HttpHandlers can do thier work. Please note that in my application the css files are stored in the Content folder and js files are stored in the Scripts folder. If you are using different paths that you will need to modify your entries to match the structure of your application.

   //for css compression
   routes.IgnoreRoute("Content/{resource}.axd/{*pathInfo}");
   //for js compression
   routes.IgnoreRoute("Scripts/{resource}.axd/{*pathInfo}");

Now we can modify the references to our css and js files in the HTML so they use the custom HttpHandlers. For example, the original path to my css file was "/Content.css" so I modified it to "/Content/css.axd?name=site.css". By making this change, the CSSHandler will get executed. When the request is processed the handler will look at the name parameter passed in on the query string, locate the "uncompressed" file, strip out the whitespace and return it in a minified format.  The JavaScript Handler works the same way except it uses the path parameter instead of name. I am not sure why the BlogEngine.NET developers used different variable names but I just wanted you to be aware of it.

Finally, here is my master page with the updated references. Notice that the first and the last entry are utilizing the custom handlers. The other scripts are already minified so I did not bother modifying them. Like I mentioned earlier, we can control what gets passed through to the custom handlers directly in our HTML.

<link rel="stylesheet" href="/Content/css.axd?name=site.css" type="text/css" />
<link href="/Scripts/themes/overcast/ui.all.css" rel="stylesheet" type="text/css" />
<script src="/Scripts/jquery-1.4.min.js" type="text/javascript"></script>
<script src="/Scripts/jquery-ui-1.7.2.custom.min.js" type="text/javascript"></script>
<script src="/Scripts/js.axd?path=big.script.js" type="text/javascript"></script>

Finally, I want to make sure that credit is given where credit is due. I did not do anything other than take an existing piece of code and modify it to work in my application. The BlogEngine.NET developers did all the real work, so they deserve all the credit.

Download the modifed files ==> CompressOnTheFly.zip (5.67 kb)

blog comments powered by Disqus

About the author

MikeMichael Ceranski is a developer specializing in the .NET stack. I have spent time as a DBA, Web Developer and even a network engineer. Up til now most of my career has revolved around the .NET stack but I have recently taken an interest in microcontrollers which has forced me to get acquainted with lower level languages such as C, and C++.

View my resume

Sponsors