Zoompf's Web Performance Blog

Note: Archived Content

This is the archived version of the Zoompf blog. Since our acquisition by Rigor, all our new research and posts on web performance are being published on The Rigor Blog

How to Automatically Bundle Your CSS and Javascript in ASP.Net

 Mark Isham on January 22, 2015. Category: Guide
Downhill From Here! (CCO Public Domain License)

Downhill From Here! (CCO Public Domain License)

Last year I wrote a beginner’s guide to using mod_pagespeed in Apache that allows the Apache developer to recognize significant performance optimizations for their site with very little effort. I thought it might be fun to revisit this topic, but this time focus on a great library for ASP.Net developers: System.Web.Optimization.

In this post I am going to present a simple step by step tutorial for using Microsoft’s Web Optimization library to automatically optimize your site’s CSS and Javascript. If you haven’t heard of this library, you’re in for a treat: it automates three key (and historically tedious) components of front end website performance optimization:

  1. Combine your CSS and JS to make fewer requests.
  2. Minify your CSS and Javascript
  3. Use caching with versioning on all your static resource includes

For this guide I utilized ASP.Net MVC Version 5 with the .net 4.5.1 framework on Visual Studio 2013, but this library is available to older versions as well. You can also utilize System.Web.Optimizations with ASP.Net WebForms, an article we may dive into at a future time. While I don’t assume any ASP.Net MVC expertise for this article, I would highly recommend checking out this YouTube series by PragimTech.com if you want to learn more, it’s quite excellent.

You can also download the source code for this tutorial here (you will still need to add the Microsoft.AspNet.Web.Optimization package via NuGet from the step below).

Let’s Get Started

Let’s start at the beginning. Fire up Visual Studio and create a new ASP.Net Web Application project. Select an ‘Empty’ template and add a reference to MVC:


Now go ahead and add a controller named “HomeController” (right click the Controller folder and click “Add Controller”), and then right click on the Index method and select “Add View” to create a default view.

Build and run the application. You may see this error:


This is a known issue with a recent security update. If you see it, simply open up your project references, right-click-properties the System.Web.Mvc dependency and change the “Copy Local” setting to true.


Do a full clean/rebuild/rerun of the solution and you should see something like this.


Okay great, let’s look under the hood. Right click and “view source” on that page. Scroll to the bottom and look at the javascript includes. You’ll see that the the MVC wizard automatically added dependencies for jquery and bootstrap:


Let’s say we want to combine together these third party references, as well as any new ones we may add in the future. The System.Web.Optimization library makes this super easy, and throws in automatic minification and file versioning as well!

Let’s see how.

Adding System.Web.Optimization

First we’ll need to install Web Optimization package. Go to Tools > NuGet Package Manager > Package Manager Console. This should open up a console window like below.


Enter in the following command:

Install-Package Microsoft.AspNet.Web.Optimization


Some magic happens, and you’re ready to go!

Well not quite, there is one additional step. Open up your web.config file (not the one under the project folder, but the one under the “Views” folder) and add this entry to the namespaces tag:

<add namespace="System.Web.Optimization" />

This will allow our views to access this library without typing the full namespace each time.


Not go to your App_Start folder and create a new class called “BundleConfig”. This class is going to allow us to define “groups” of CSS and Javascript files from your web project that you want to be automatically combined into a single file include on the rendered page. Each bundle will map to exactly one script or stylesheet include on the rendered webpage.

You can add as many CSS and JS files as you want to each bundle, and the library is smart enough to automatically combine, minify and version all the files ONLY when a file inside the bundle gets changed. This is a godsend to programmers, as they can once again divide out their code to multiple files based on functional areas, but still benefit from the performance gains of bundling and minifying. In addition, the auto-versioning allows you to utilize “far future caching” (setting Expires at least 1 year in advance) so browsers only download these resources once, but then automatically re-download if any new changes occur. It’s pretty slick.

For this tutorial, let’s just combine the jquery and bootstrap javascript includes into one.

Add this code to your new BundleConfig class:

    public class BundleConfig
        public static void RegisterBundles(BundleCollection bundles)

            ScriptBundle thirdPartyScripts = new ScriptBundle("~/Scripts/ThirdParty");

            BundleTable.EnableOptimizations = true;			

If you were combining CSS files (and you should) you would simply use a “StyleBundle” class instead of “ScriptBundle” in the above example. You can add as many bundles as you want, but we recommend a balance as each new bundle results in an additional download for the browser. Ideally you should bundle by areas that commonly get changed together. For example, your third party library includes are likely updated very infrequently, so you may want to put those in one bundle. Your site code is likely updated more frequently, so put that in a different bundle. That way your users aren’t downloading your larger third party includes every time a site specific file is changed.

Note also the {version} wildcard in the example. There are many interesting features you can explore here which we may dive into in a future post. For now, here’s a great reference to learn more.

Now that you’ve defined your bundles, you need to make sure they are loaded when the website starts up. To do so, edit your Global.asax file and add this line to your Application_Start method:


You’ll also need to add these Using statements to the top (adjust for your project name as needed):

using WebOptimizationMvc.App_Start;  // Or your project path
using System.Web.Optimization;

It should look like this:


And finally we need to use the script bundler in your layout page in place of the direct script includes inserted by the project wizard. Edit the _Layout.cshtml file under Views > Shared in your project and replace your code like this:


Here’s the new line to add:


Rebuild and rerun the project. You should see the same page as before, but now right click and “View Source”. Scroll down and you should see something like this:


Voila! Your libraries have been combined! If you click the link, you’ll notice the content is minified too (okay bad example here since the original files were also minified, but trust me this will also minify your un-minified inputs).

If you wanted to combine your CSS files, you’d follow the same process but instead use a “StyleBundle” class in your RegisterBundles method and then use the @Styles class when rendering in your view, like this:


Obviously you should do both!

There’s a lot more great features under the hood here, but this should be enough to get you started. With these tools in place, you can now split your CSS and Javascript into many different files, then use the build system to automatically combine, minify and version any changes you make for fast download performance by the browser. This is a huge timesaver for the developer.

If you want to make sure your CSS and Javascript stay optimized, consider signing up for Zoompf Alerts. Zoompf Alerts monitors your site throughout the day, notifying you if your CSS, Javascript, HTML or Images ever change in a manner that hurts your website performance. It’s free and you can opt-out at any time!


Have some thoughts, a comment, or some feedback? Talk to us on Twitter @zoompf or use our contact us form.