Enabling bundling and minification support in a .NET 4 application

.NET 4.5 is going to offer support for bundling and minifying content on the server before passing that down to the client.

If you want detailed information on what this is, go and read Scott Gu’s blog post about the features. In a nutshell, bundling is combining several files into one combined file and minification is the compressing of a file to make it as small as possible. The goal for both of these are to reduce the time taken for your content to get to the client browser.

ASP.NET Optimization – Bundling

The implementation of this new feature is, as the majority of new .NET features will be going forward, available as a separate package from .NET itself. In the case of the bundling support, this is contained within a NuGet package.

The good news is that this package can be used in .NET 4 applications right now.

Bundling and Minifying CSS files

Okay, to begin with we need some files to minify.

Project Set-up

Let’s set up a project with the following structure:

  • default.aspx
  • content/css/colours.css
  • content/css/layout.css
  • content/css/reset.css

So, we have a single page (default.aspx) and three CSS files in a sub-folder called under content/css.

Normally, we’d just reference these three files separately in the page, creating three requests for the resources. But, this time, we’ll bundle them up and serve them down as a single file.

Grabbing the package

Open up NuGet and add the ASP.NET Optimization – Bundling package. You’ll want to allow for pre-release software to get the latest updates to this.

ASP.NET Optimization - Bundling NuGet package

This will pull down the required package files along with dependencies like WebGrease and Microsoft.Web.Infrastructure. If you get a pop-up to agree to the licence terms, have a read through then click to agree.

In .NET 4.5 projects, the package will hook into the App_Start scripts that are a new feature of those. Since we don’t have them in our .NET 4 project, all the package will do is add the required references.

Create a bundle

The App_Start folder in .NET 4.5 takes functionality out of the Global.asax.cs Application_Start method. We’ll just use the .NET 4 approach and add our files to Global.asax.cs directly.

If you don’t already have a Global.asax.cs file, right click your project and select to add a new Global Application Class. Inside the Application_Start method, create your CSS bundle:

var cssBundle = new StyleBundle("~/css");
cssBundle.IncludeDirectory("~/content/css", "*.css");

Here, we’re specifying that we want to create a new bundle that will be made available at ~/css (line 1).

This will contain all of the files matching [anything].css in the directory ~/content/css (line 2).

Next, we just need to add that to the bundle table (line 6 below). Our full code looks like:

protected void Application_Start(object sender, EventArgs e)
{
    var cssBundle = new StyleBundle("~/css");
    cssBundle.IncludeDirectory("~/content/css", "*.css");

    BundleTable.Bundles.Add(cssBundle);
}

If you want to check that the CSS bundle has been created successfully, rebuild your project and navigate to ~/css in your browser (nothing gets created on disk; this is all in memory). You should see a combined and minified version of your CSS files.

Rendering the link

We have the bundle, now all that remains to do is add a reference to the file from our web page. Luckily there are helper methods to do this. These take in our virtual path from the bundle specification (in this case that’s ~/css) and generates a link to that file. So, our CSS link is:

<%= Styles.Render("~/css") %>

This renders in the source as:

<link href="/css?v=UyfbhDwEqcWkiFmaG3_cBOqhfMLMF9xlylL3rQnVvVM1" rel="stylesheet"/>

The query string value at the end of the href is a hash of the file contents. So, if the contents of any of our files change, then the URL will automatically update, forcing clients to download the latest version of the file.

Switching it on and off

You maybe don’t want to have your files compressed when you’re running locally or deploying to a dev server. By default, the BundleTable will only enable compression when the project is running with debugging disabled.

If you want to override this, you can do so by setting the value of EnableOptimizations like so:

protected void Application_Start(object sender, EventArgs e)
{
    var cssBundle = new StyleBundle("~/css");
    cssBundle.IncludeDirectory("~/content/css", "*.css");

    BundleTable.Bundles.Add(cssBundle);
    BundleTable.EnableOptimizations = true;
}

And that’s it. If you want to create a JavaScript bundle, you can just use ScriptBundle instead of StyleBundle and point it at some JS content.

Sample Code

Sample code showing this in action for both CSS and JavaScript in Webforms and MVC is available on GitHub.

Kevin Wilson

.NET developer, JavaScript enthusiast, Android user, Pebble wearer, sometime musician and occasional cook.

2 thoughts on “Enabling bundling and minification support in a .NET 4 application

  1. StyleBundle() does not appear to be available given .Net4.0 and the Microsoft.Web.Optimization -Version 0.1.0 package and ASP.NET Optimization – Bundling NuGet Package listed above. Also included “using Microsoft.Web.Optimization”.

    I was not able to get bundling working, and spent several hours trying – what’s missing?

  2. Kevin – your post was very useful for me!
    Abraham – I don’t have any problems (VS 2010) – steps:

    1) install Nuget:
    http://visualstudiogallery.msdn.microsoft.com/27077b70-9dad-4c64-adcf-c7cf6bc9970c

    2) install Nuget package (with dependencies):
    PM> Install-Package Microsoft.AspNet.Web.Optimization

    3)
    void Application_Start(object sender, EventArgs e)
    {
    RegisterRoutes(RouteTable.Routes);

    ScriptBundle scriptBundle = new ScriptBundle(“~/js”);
    scriptBundle.IncludeDirectory(“~/scripts”, “*.js”);
    BundleTable.Bundles.Add(scriptBundle);

    StyleBundle styleBundle = new StyleBundle(“~/css”);
    styleBundle.Include(“~/StyleSheet.css”);
    BundleTable.Bundles.Add(styleBundle);
    }

    4) !!! ignore js and css paths !!!
    public static void RegisterRoutes(RouteCollection routes)
    {
    routes.Add(new Route(“WebResource.axd”, new StopRoutingHandler()));
    routes.Add(new Route(“js”, new StopRoutingHandler()));
    routes.Add(new Route(“css”, new StopRoutingHandler()));

    routes.Add(new Route(“{page}”, new PageRouteHandler(“~/{page}.aspx”)));
    }

    5) usage:
    a) in head tag:

    b) before closing body tag:

    Hope that helps!

Leave a Reply

Your email address will not be published. Required fields are marked *