Minify your JavaScript and CSS

When building a full-featured MVC web site (or any web site), it is likely that you will have lots of JavaScript and CSS resources.  In addition, when you are using 3rd-party libraries, you can often get "minified" versions of the files, but you may end up with a handful or even dozens of separate js files.  It is important to reduce the load times of these files as much as possible.  There are a few concepts that help speed up page loads:
  1. Minify files: remove unnecessary spaces and line breaks so the file size is as small as possible.
  2. Combine files: rather than have 20 separate js or css files, combine them into as few as possible to reduce the number of request/response cycles the browser must go through to load the page.
  3. Compression: enable gzip compression on your web server so the minified/combined files are reduced even further when being transmitted over the network.
There are several tools out there to minify and combine tools, and Visual Studio 2012 has some great features to do this in MVC 4.  But if you are not on VS2012 yet, or if you need more precise control over your files (and the order in which they are loaded), you have other options.

I will walk through some steps of using Microsoft's Ajax Minifier.  This is a command-line utility that can minify and combine js and css files and can easily be integrated into your build process.

First, get the Ajax Minifier.  In order to make it easy for a development team to use, I added AjaxMin.exe to my "ReferencedLibs" folder for my project which is checked into TFS for the whole team to use.  That becomes my base path for running the script.

Next, I set up a batch file to minify all the files I need.  This is definitely old-school, but it is a simple way to minify and combine files in the precise order you specify.

Here is an example of what my Minify.bat file looks like:

rem CSS
ReferencedLibs\ajaxmin -clobber ^
    MyProject\Content\Site.css ^
    -o MyProject\Content\Site.min.css
 
rem Toolkit JS
ReferencedLibs\ajaxmin -clobber ^
    MyProject\Scripts\kendoui\js\jquery.min.js ^
    MyProject\Scripts\kendoui\js\kendo.web.min.js ^
    MyProject\Scripts\jquery.validate.min.js ^
    MyProject\Scripts\jquery.validate.unobtrusive.js ^
    MyProject\Scripts\jquery.unobtrusive-ajax.min.js ^
    MyProject\Scripts\jqueryform\jquery.form.js ^
    -o MyProject\Scripts\Toolkits.min.js
 
rem MyProject JS
ReferencedLibs\ajaxmin -clobber ^
    MyProject\Scripts\MyProject\Desktop.js ^
    MyProject\Scripts\MyProject\Account.js ^
    MyProject\Scripts\MyProject\History.js ^
    MyProject\Scripts\MyProject\Analytics.js ^
    -o MyProject\Scripts\MyProject\AllDesktop.min.js

 You may wonder why I include a section to build Toolkits.min.js when most of the files are already minified.  This is so we can combine all of those already-minified files into a single file to speed up the load time a bit more. 

And now that we have our batch file, we can set it up to run every time we do a build.  Open your project properties in Visual Studio and under "Build Events" add this to either the pre-build or post-build event command line (this assumes that you placed your Minify.bat file in your main solution directory):

cd "$(SolutionDir)"
call Minify.bat

You will notice that all of the original files remain intact--I am only creating new ".min" versions of existing files.  This is useful for two reasons:
  1. You can continue to use your un-minified files for development and every time you build, the minified files will be updated.
  2. You can use your un-minified files for debugging purposes, when your project is in debug mode.
In order to switch between minified and un-minified files based on debug mode, we need to add a few lines of code.  If you are using MVC with Razor, here is the code you can put in your cshtml file to wrap around any CSS or JavaScript declarations:

@if (Context.IsDebuggingEnabled)
{
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
}
else
{
    <link href="@Url.Content("~/Content/Site.min.css?v=1")" rel="stylesheet" type="text/css" />
}

So now, if in your web.config, you have debug set to true:

<compilation debug="true" targetFramework="4.0" />

Then it will use the regular, un-minified version of the file.  If debug is false, it will use the minified version.  I also appended a "?v=1" at the end as a querystring parameter.  You can build version numbers into the minified files, but this is another way to force browsers to load a new version when an older version may be cached.

Now you can use the developer tools in your browser to see which files are loaded and do some comparisons between the minified and un-minified versions of your site.  I have been seeing more than a 50% improvement in file size when comparing before and after minification.
comments powered by Disqus