Bundling and Minification in ASP.NET MVC

Richness of Web Content has been growing at a phenomenal pace and thanks to Modern browsers supporting HTML5 and CSS3, with a little work, a Web Application can be made almost as rich as Native applications. Yes, they are still a little behind but Web today is unrecognizable from web 5 years ago.

This rich-ness of behavior on the web, is all thanks to the power of JavaScript frameworks, libraries and plugins, whereas the rich user experience comes from effective use of graphics and CSS3.

However all this has a cost. If we look at a plain vanilla ASP.NET Web Template in Visual Studio, it has a total of eight (8) JavaScript files and sixteen (16) css files. Now most of these are loaded in the _Layout page. Some are loaded as required in Forms Pages. But how does the loading of these many artifacts affect the performance of your web site? Let’s find out.

Downloading multiple files from Server on to the Browser

The experts among us know that a Browser is restricted from opening unlimited number of simultaneous client connections. In most modern browser, it’s limited to about 6 simultaneous connections. Now if you have more than 6 artifacts to download, some are going to get queued

before-jquery-ui

Let’s go to the _Layout.cshtml and make one change to the default MVC4 template, that is to enable jQueryUI bundle. Now let’s refresh the page. My first result was rather off the charts so I did a Ctrl+F5 the second time to refresh IE again.

after-jquery-ui

Between the first image and the second, we can see the explosion of files that were downloaded and more importantly the grey bars that started cropping up. If you see closely, only 6 bars have started with Yellow, the rest have started with grey as in they have had to wait till one of the other artifacts finished downloading. Also notice the number of Bytes received, that also quarter of an MB. In internet terms that is MASSIVE.

This is on my local machine. Imagine the round-trips over the web across the planet. Those milliseconds begin to pile up.

But it was once proposed that smaller files are better than one massive chunk!

Very true, however there is a fine line between a few smaller discretely split up files vs. many small files for a framework (like jQuery UI above). Luckily for us, there is now an easy way out via ASP.NET’s Bundling and Minification feature. Though they are taken in the same breath, they are two distinct actions that we will take up one at a time.

Bunding and Minification

Minification

Minification involves reducing the size of the script or style by removing inconsequential whitespaces. It’s like sucking the air out of a Suit protector using a vacuum cleaner. The full suit is there, it’s not been folded, however, its size has shrunk because the air was sucked out. This helps us reduce the amount of data transferred.

Bunding

Bundling involves combining different files that are likely to be used together into once air tight (minified) chunk so that number of requests to the server go down in an attempt to squeeze everything down to those 6 or 7 simultaneous requests that the browser can make at one time.

Enabling Bundling and Minification

Let us see what we gain by bundling and minifying our content. As you will notice most JS files already come with their .min.js files. We can turn off Debug mode in Web.config to get the minification going and ASP.NET will start picking up the .min files themselves.

compilation-debug-true

Another option is to enable optimization in the App_Start\BundlesConfig.cs add the following line to enable optimizations.

BundleTable.EnableOptimizations = true;

With either one of the two settings set, let’s run the app again on the Index page

image

As we can see above, the total number of items downloaded is now down from 21 to 10, the number of bytes received has gone down from three quarters of an MB to about 330 KB. Awesome gain.

So far so good, what gives?

After we enabled Bundling and Minification on the server, the amount of data transmitted to the client was significantly reduced and so were the number of requests. But what is it that we are giving away in return? Let’s look at the above Network transfer chart closely, you will notice that there are only two possible categories for CSS and JavaScript each. What happened to our JS files and CSS files? Where did they all go? Well they are there but they have been crunched up into one or two files each depending on the number of Style Bundles and Script bundles we created. Confused? Let’s take a closer look at BundlesConfig.cs and our previous network transfer chart

bundle-correlation

As you can see from the mashup above, each bundle in BundleConfig has resulted in one request from the client to the server and bundles are not done haphazardly, rather they are grouped manually based on what we think are similar types of files. Above it’s obvious that all jQuery UI files should be bundled together and jQuery should have its own bundle. Ditto with the CSS files.

Bundling and Minification Conventions and Syntax

Now that we have seen how Bundling and Minification adds value, let’s look at the server side code.

- Each Bundle has a name unique name. Script bundles start with ‘~/bundles/…’ and Style Bundles start with ‘~/Content/’. For example the jQuery bundle is called ‘~/bundles/jquery’

- You can include as many files as you like comma separated via the bundle’s Include method.

- You cannot use top level wildcards like ~/Scripts/*

- The {version} wildcard makes the bundle version agnostic so if you update your queries via Nuget your bundles will continue to work.

In ASP.NET MVC Razor view engine, you include Bundles using the following syntax

@Styles.Render("~/Content/themes/base/css") // For including Style Bundles
@Scripts.Render("~/bundles/modernizr") // For including Script Bundles.

Conclusion

Bundling and Minification are important optimizations that should not be left as optional when going to production. They can significantly improve a Page’s response time and hence end user satisfaction.

2 comments:

  1. hi,
    What about backround-imag in css files. It is not working with budling.

    ReplyDelete
  2. MVC Bundling now has a bug with the latest Google Chrome. Any media queries will not be minified correctly, and will not work.

    This fix will help: http://i-skool.co.uk/net/mvc/mvc-bundling-and-minifcation-issues-with-google-chrome/

    ReplyDelete