Saturday, February 25, 2012

ASP.NET MVC4 bundling in ASP.NET MVC3

One of the new wildly evangelized features of ASP.NET MVC4 is the built-in support for bundling and minification of scripts and stylesheets.

I don't see any reason why this new feature wouldn't work for ASP.NET MVC3 though. If you open the packages config of an ASP.NET MVC4 beta project, you will find that bundling support lives in the Microsoft.Web.Optimization package.
<package id="Microsoft.Web.Optimization" version="1.0.0-beta" />
So we should just be able to install this package for an ASP.NET MVC3 project. To install the package, run following command. Pay attention to the -Pre switch.
PM> Install-Package Microsoft.Web.Optimization -Pre
Attempting to resolve dependency 'Microsoft.Web.Infrastructure (= 1.0.0)'.
Successfully installed 'Microsoft.Web.Infrastructure 1.0.0.0'.
Successfully installed 'Microsoft.Web.Optimization 1.0.0-beta'.
Successfully added 'Microsoft.Web.Infrastructure 1.0.0.0' to Optimization.
Successfully added 'Microsoft.Web.Optimization 1.0.0-beta' to Optimization.
Adding bundles happens when the application starts, together with registering areas, adding global filters and registering routes.

The quickest way to enable bundling is by enabling the default bundles.
BundleTable.Bundles.EnableDefaultBundles();
This method will add two bundles to the bundle table: one bundle for the stylesheets in the Content folder and one bundle for the scripts in the Scripts folder. The default bundles try to take core scripts into account when ordering the scripts in the bundle. For example, jQuery will be included before any of its plug-ins are included.

To reference these bundles you can add following snippet to your view or layout file.
<link href="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Content/css")" 
    rel="stylesheet" type="text/css" />
<script src="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Scripts/js")">
</script>    
If you start your application now, and inspect the HTML, you will find two versioned links to a minified version of your CSS and JavaScript.


If you're trying this on a new project, you will probably have no problems. However, if you're trying this on an existing project, chances are that some things are not included how they should be.

To troubleshoot what's going wrong, you can inspect the results of the GetRegisteredBundles method.
var registeredBundles = BundleTable.Bundles.GetRegisteredBundles();
If you need more fine-grained control, you can remove the default bundles again and add your own bundles to the bundle table.

For example, this is how you can add a jQuery bundle.
var jQueryBundle = new Bundle("~/Scripts/jquery", new JsMinify());
jQueryBundle.AddDirectory("~/Scripts", "jquery*.js", searchSubdirectories: false, throwIfNotExist: true);

BundleTable.Bundles.Add(jQueryBundle);
<script src="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Scripts/jQuery")">
</script>  
When you instantiate a new bundle, specify the relative path of the bundle and pick a bundle transformation. You can add a directory to the bundle, filtered by a search pattern. You can also tell the algorithm to search in the subdirectories or to throw an exception when the directory doesn't exist.

If you don't want to add a whole directory to the bundle, but just one or more files, you can use the AddFile method.

For example, this is a separate bundle for modernizr.
var modernizrBundle = new Bundle("~/Scripts/modernizr", new JsMinify());
modernizrBundle.AddFile("~/Scripts/modernizr-1.7.js", throwIfNotExist: true);

BundleTable.Bundles.Add(modernizrBundle);
Conclusion

It's relatively easy to take advantage of bundling in ASP.NET MVC3. Install the NuGet package, set up the bundle table, include the references in your view or layout page and you're done.

There are some more interesting things you can do using bundling. I just started experimenting with it, so I wouldn't be surprised if I will be writing a few more things on bundling in the coming weeks.

9 comments:

  1. Good stuff! I was also looking for a way to use the new bundling/minification techniques in our MVC 3 project. Your post helped me to get started.

    ReplyDelete
  2. Also, you should be able to use the shorter @Url.Content("~/Scripts/jQuery") syntax. It works for me.

    ReplyDelete
  3. Congratulations for this!!, i've a question, is it possible to use this bundling library to minify the razor views?, or jquery blocks "script" inside views?, i've tried with meleze, but that affect textareas too, and i don´t want that.

    ReplyDelete
    Replies
    1. Not that I know of. You could always just extract the inline scripts though ;)

      Delete
    2. JavaScript should be located at the bottom of the DOM.

      Delete
  4. Hey,

    Can you check me over at forums.asp.net? http://forums.asp.net/t/1871992.aspx/1?Bundling+in+MVC3

    My script is not working.

    Thank you,
    -imperialx

    ReplyDelete
  5. Hi!

    Bundling and minification are two techniques you can use in ASP.NET 4.5 to improve request load time. Bundling and minification improves load time by reducing the number of requests to the server and reducing the size of requested assets (such as CSS and JavaScript.)
    So thanks for sharing this important information through this article. There are few other links that have described for manage "Bundling and minification".

    http://www.mindstick.com/Articles/2d3da74a-94da-45fe-b361-97263cd725f2/?Bundling%20and%20Minification%20in%20ASP%20NET%20MVC%204

    http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification

    ReplyDelete