Using MVC4 bundling and minification in an MVC3 project
20th Feb 2013
When you push any site to production, you should at least do some basic front end optimisation. Running through a number of optimisation steps will ultimately make your website load quicker and feel more responsive to the end user.
If this is the first you have heard about front end optimisation, I must recommend that you read "High Performance Websites" by Steve Souders.
One of the best ways to make your site load quicker is to make it smaller. Reduce the amount of data that needs to go from your server to the client machine. And one of the best ways to make massive gains in doing this is to Bundle and Minify the CSS and Javascript that your application uses.
MVC4 has made this incredibly easy with built in Bundling and Minification. However, you do not need to upgrade your entire MVC project to take advantage of this fantastic new set of features.
Firstly, open up the project that you want to optimise. I'll be demonstrating this with a new empty MVC3 web application. Currently, the head of my _Layout.cshtml file looks like this:
<head>
<title>@ViewBag.Title</title>
<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-1.7.1.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/modernizr-2.5.3.js")" type="text/javascript"></script>
</head>
So lets run the page and just see what's going on under the hood:
So at the moment, my page is a massive 355.89 Kilobytes - and all it does is display some text - "Index". That's way too big - and we can see that the biggest and slowest loading areas of the site are the Javascript libraries that are being pulled onto every page of the site. (It's worth noting at this point that you could used the already minified versions of the files. For the sake of this demo, I'll be using the full fat versions).
So let's get bundling and minifying.
Open the package manager console, and enter the following command to drag down the Microsoft ASP.NET Web Optimization Framework:
- Install-Package Microsoft.AspNet.Web.Optimization -Pre
Once added to your project, you can the begin configuring your bunding and minification. Open your Global.asax.cs file and add a reference to System.Web.Optimization
using System.Web.Optimization;
Then, go ahead and create a new static method, RegisterBundes:
public static void RegisterBundles(BundleCollection bundles) { }
Now, lets create some Bundles. I'm going to put all of my Javascript into one minified bundle, and my CSS into another minified bundle:
public static void RegisterBundles(BundleCollection bundles)
{
//CSS
var styles = new StyleBundle("~/Content/bundledcss").Include("~/Content/site.css");
//JS
var js = new ScriptBundle("~/Scripts/bundledjs").Include("~/Scripts/jquery-1.7.1.js", "~/Content/jquery.validate.js", "~/Content/jquery.validate.unobtrusive.js", "~/Content/modernizr-2.5.3.js");
bundles.Add(styles); bundles.Add(js);
BundleTable.EnableOptimizations = true;
}
There are three types of bundle that you can create:
- Bundle - a non-minified bundle of a collection of files
- StyleBundle - a minified bundle of a collection of css files
- ScriptBundle - a minified bundle of a collection of Javascript files
Now, lets wire up a call to our new RegisterBundles method. In Global.asax.cs, locate your Application_Start method. Add the following line:
RegisterBundles(BundleTable.Bundles);
Now, when your application starts up, the bundles will be created. Now, all we need to do is to tell the views that they now need to load a bundled file and not the raw, unbundled and unminified css and js files.
In your _layout.cshtml file, or whichever file you have your stylesheets and javascript files referenced, swap out your raw file references. Firstly, add a reference at the top of your view to System.Web.Optimisation:
@using System.Web.Optimization
Now, lets swap the old references to our full fat files out:
<link rel="stylesheet" type="text/css; href="@BundleTable.Bundles.ResolveBundleUrl("~/Content/bundledcss")" />
<script src="@BundleTable.Bundles.ResolveBundleUrl("~/Scripts/bundledjs")">"</script>
And that's us. Let's test it out. Remember to build first:
And we've made a massive improvement. We have:
- Reduced the number of requests (from 6 to 3, as we've bundled multiple files into one
- Reduced the file sizes
This won't take long to bring into an existing site and is definitely worth the benefits.
Edit: Of course, you should also move your Javascript to the foot of the html document for even more speed improvements.