Deep Dive into ASP.NET Bundling and Minification

Page content

In the previous post, I went on about how to use System.Web.Optimization library to minimize your page load times. However, the new library offers quite a lot of extensibility and even if you don’t want to use the default minification, you can still use the framework.

Bundle Without Minification

Sometimes, first step is just to bundle the files together without minification. I often find some JS is poorly written and is missing the odd semi-colon, which blows up during minificaiton.

Unfortunately, there is not a quick flag you can set on the bundle. The good news is, it’s fairly simple. You can create your own transform and pass it to the bundle. Remember to use Bundle instead of StyleBundle or ScriptBundle.

 1public class NonMinifying : IBundleTransform
 2{
 3    private readonly string _contentType;
 4
 5    public NonMinifying(string contentType = "text/css")
 6    {
 7        _contentType = contentType;
 8    }
 9
10    public void Process(BundleContext context, BundleResponse bundle)
11    {
12        if (bundle == null)
13        {
14            throw new ArgumentNullException("bundle");
15        }
16
17        context.HttpContext.Response.Cache.SetLastModifiedFromFileDependencies();
18        foreach (FileInfo file in bundle.Files)
19        {
20            HttpContext.Current.Response.AddFileDependency(file.FullName);
21        }
22
23        bundle.ContentType = _contentType;
24    }
25}
1//... in your app init
2IBundleTransform cssTramsform = new NonMinifying();
3
4var cssBundle = new Bundle("~/Content/themes/base/css", cssTramsform)
5            .Include("~/Content/themes/base/jquery.ui.core.css",
6            "~/Content/themes/base/jquery.ui.resizable.css");
7    BundleTable.Bundles.Add(cssBundle);

Plugin Your Own Minification

If you don’t like the default minification that comes in with the System.Web.Optimization, you can plug in your own. I’ve used SquishIt few times – lets have a look have we can integrate it in the ASP.NET bundles.

All we need to do is write our own custom SquishIt transform. It will iterate through each file in the bundle and process it.

 1public class SquishItCssTransform<T> : IBundleTransform where T : IMinifier<CSSBundle>
 2{
 3    public void Process(BundleContext context, BundleResponse response)
 4    {
 5        var cssCompressor = MinifierFactory.Get<CSSBundle, T>();
 6        var rawCss = new StringBuilder();
 7
 8        foreach (var fileInfo in response.Files)
 9        {
10            using(var reader = fileInfo.OpenText())
11            {
12                rawCss.Append(reader.ReadToEnd());
13            }
14        }
15        var compressedCss = cssCompressor.Minify(rawCss.ToString());
16        context.HttpContext.Response.Cache.SetLastModifiedFromFileDependencies();
17        response.Content = compressedCss;
18        response.ContentType = "text/css";
19    }
20}
1....
2//in your bundling init
3var cssTransform = new SquishItCssTransform<YuiMinifier>();
4BundleTable.Bundles.Add(new Bundle("~/Content/css", cssTransform)
5.Include("~/Content/site.css"));

The SquishItCssTransform takes type of T so you can specify the type of the CSS minifier from the SquishIt library. In this example, I’ve used the YuiMinifier.

CoffeeScript or SASS, no problem!

If you use CoffeeScript for your JavaScript or SASS/LESS for your CSS, the process is pretty much similar. You need to create a new bundle and pass in your custom IBundleTransform. Using CoffeeScript compiler is dead easy.

 1public class JavascriptCoffeeScriptTransform : IBundleTransform
 2{
 3    public void Process(BundleContext context, BundleResponse response)
 4    {
 5        var compiler = new CoffeeScriptCompiler();
 6        var content = new StringBuilder();
 7        foreach (var fileInfo in response.Files)
 8        {
 9            using (var reader = fileInfo.OpenText())
10            {
11                content.Append(reader.ReadToEnd());
12            }
13        }
14
15        var compiled = compiler.Compile(content.ToString());
16        var factory = MinifierFactory.Get<JavaScriptBundle, JsMinMinifier>();
17
18        var minified = factory.Minify(compiled);
19
20        context.HttpContext.Response.Cache.SetLastModifiedFromFileDependencies();
21        response.Content = minified;
22        response.ContentType = "text/javascript";
23    }
24}
1//.. your bundling setup ...
2var coffeeBundleAndMinify = new JavascriptCoffeeScriptTransform();
3var coffeeBundle = new Bundle("~/bundles/coffee", coffeeBundleAndMinify)
4                       .Include("~/Scripts/Coffee/Script.coffee");
5BundleTable.Bundles.Add(coffeeBundle);

Now you have a bundle from CoffeeScript files that is compiled and minified.

Bundling and Minification with ASP.NET MVC 4

Any questions, tweet me @mirajavora