Optimize ASP.NET MVC Views with Bundling and Minification Features
ASP.NET MVC web
applications often use client side scripting in one or the other way. Use of
JavaScript libraries such as
jQuery and
frameworks such as
AngularJS is quite common these days. Therefore it is important to pay
attention to the rendering of the views. Especially, script load time is worth
some consideration. Luckily, ASP.NET MVC offers help in the form of bundling and
minification features. This article shows how these features can help you
optimize the views.
Before we go into the details of bundling and minification features, let's
try to understand the underlying problem these features intend to solve.
Web applications work on the basis of request-response model. While a page is
being loaded in the browser, the browser also makes requests to load resources
such as images and script files. That means if an ASP.NET MVC view is
referencing four scripts using the <script> tag, the browser is going to send in
all five requests - one for the main page and four for the script files. You can
easily verify this using browser developer tools. The following figure shows how
Chrome Developer tools show these requests:

Notice that there are four entries - one for /home/index (this returns the
index view) and jquery-1.10.2.js, angular-1.2.js, angular-route.js and
modernizr.js (Note: These libraries are used purely for testing purpose. Most of
the JS frameworks or libraries have readymade minified versions). Also notice the size of each
script file and the time taken for each to
load. If you calculate the totals (script files only) they come to around 1093.2
KB bytes and 1665 milliseconds
respectively. This default behavior
causes performance penalty in two ways:
- It is making five requests to the server. Every request is basically an
"open-close" operation. More the requests poorer will be the performance.
- The script files under consideration are downloaded "as is" - in their
original (un-minified) form.
Bundling and minification features tackle exactly these two areas to improve
the overall page loading time. They do so in two ways:
- Instead of making independent requests to each script file, they make
just one request and download all the necessary script or CSS files at once.
- They minify the script and CSS files which results in a "compressed"
form of the contents. The compressed content is then downloaded on the
client side. This means fewer bytes travel over the wire.
As you might have guessed by this time, bundling features take care of
combining contents of multiple script or CSS files into one chunk whereas
minification involves compressing this content. The resultant content is then
download by the browser.
Now that you know what bundling and minification is, let's see how to enable
it for your ASP.NET MVC
application.
Open Visual Studio
and create a new ASP.NET MVC application based on empty template. Then right
click on the References folder and select Manage NuGet Packages menu option. In
the Manage NuGet Packages dialog search for Microsoft ASP.NET Web Optimization
Framework and then install that package. This package includes all the
assemblies that are necessary to enable and use bundling and minification
features.

Next, add HomeController and Index view to the application as you normally do
for any ASP.NET MVC application. Then add a bunch of script files to the Scripts
folder. For this example I used
jQuery, AngularJS and
Modernizr libraries. Drag and drop these script files from the Scripts
folder to the <head> section of the Index view so that <script> references for
them will be added for you. The following markup shows how the <head> section
looks like currently:
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/angular-1.2.js"></script>
<script src="~/Scripts/angular-route.js"></script>
<script src="~/Scripts/modernizr.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("div").html("<h2>Bundling and minification demo!</h2>");
});
</script>
</head>
<body>
<div>
</div>
</body>
Notice that we have also added a small script block that simply sets the HTML
content of a <div> to some message. This is done simply to test whether the
libraries are downloaded correctly. If this message is displayed as expected we
can rest assured that the libraries are successfully downloaded by the browser.
Now run the application and check (and note down) your results in Chrome
Developer Tools. Based on the version of the script files and speed of your
machine the results may vary from what is shown in the figure earlier. Also make
sure that the <div> displays the message as expected. This is the normal
execution of the application and doesn't use any bundling and minification
features.
Now open Global.asax file and write the following code in the
Application_Start event handler:
...
...
using System.Web.Optimization;
namespace BundlingMinificationDemo
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
ScriptBundle bundle = new ScriptBundle("~/scripts/myscriptbundle");
bundle.Include("~/Scripts/angular-1.2.js",
"~/Scripts/angular-route.js",
"~/Scripts/jquery-1.10.2.js",
"~/Scripts/modernizr.js");
BundleTable.Bundles.Add(bundle);
BundleTable.EnableOptimizations = true;
}
}
}
Notice the code marked in bold letters. We import System.Web.Optimization
namespaces because it contains classes necessary for availing bundling and
minification services. Then we create an instance of ScriptBundle class. The
ScriptBundle class represents a bundle of script files that can be accessed at a
URL specified in the constructor (~/scripts/myscriptbundle). This URL is a
virtual URL and doesn't point to any physical file. Just like ScriptBundle there
is also a StyleBundle class that represents a bundle of CSS files.
Then the code adds all the necessary files to the ScriptBundle using
Include() method. You can create one or more such bundles based on the pattern
of usage of the script files. The newly created bundle is then added to the
BundleTable object's Bundles collection. The EnableOptimizations property turns
the bundling and minification on (true) or off (false). You may set it to false
for testing and debugging purposes.
Finally, you need to replace all the <script> references from the Index view
with a single @Scripts.Render() call that points to our script bundle:
@Scripts.Render("~/scripts/myscriptbundle")
The @Scripts.Render() method adds the required <script> references to the
final HTML output. For rendering style sheets you can use @Styles.Render()
method. If EnableOptimizations is set to false Render() will emit
four <script> elements each pointing independently to a script file. On the
other hand when EnableOptimizations is true you will get a single <script>
reference like this:
<script src="/scripts/myscriptbundle?v=y4ZKq6H7v0q2Opkqq_qF3rJAbUUp9vwKJ5eJGz35Ktc1">
</script>
That's it! If you run the application you should see some performance
improvement. The following figure shows a sample run of the application after
bundling and minifications enabled.

Notice that this time only one request (/Scripts/myscriptbundle) is issued to
the server and it downloads 101 KB of data in 97 milliseconds.
That's it for now. Keep coding!