ASP.NET Bundling: Fewer is better

The ASP.NET MVC bundling feature enables you to create a single file from multiple files and can be done on CSS, JavaScript, and custom bundles. By itself, bundling does not reduce the amount of data being downloaded (although the ASP.NET implementation of bundling provides minification as well, but that is another article). Instead, it is designed to limit the number of connections needed for downloading files. This is important because modern browsers only allow 6 simultaneous connections to the same hostname/server. There are even fewer connections when using a mobile browser or are trying to connect over dial-up or over a VPN. Even when using a broadband connection a list of 20 files that need to be downloaded will require all connections 3 times. By putting all of the files into a single bundle you only use one connection, allowing the other connections to be used to download items such as graphics or other items/objects. If you already have a minimal number of external files you are downloading, there is no need for bundling, but you should consider bundling if you have a lot of add-ins.

There is a cost to using bundling, however. Although you will save some download time, this savings is realized only the first time the file is downloaded. The browser generally caches the information as it comes down, so it is not downloaded on every visit. However, by bundling multiple scripts into a single file, you have slightly increased the amount of time it takes to find the necessary function or other item from within that file, and this increase takes place every time the file is accessed, not just the first time it is downloaded. You get a onetime gain in download speed for some continual impact on access performance. It becomes a balancing act as you determine which scripts make sense to be bundled together and how many to bundle together, until you start seeing a discernible impact on the performance on the client side.

Updating one file in a bundle ensures that a new token is generated for the bundle query string parameter. This change means that the bundle must be downloaded the next time a client requests a page containing that particular bundle. When not using bundling, each asset is listed in the page individually, so that only the changed file would get downloaded by the browser. This implies that files that change a lot may not necessarily be the most suited for bundling.

The Bundle class Include method takes an array of strings, where each string is a virtual path to the resource. The Bundle class IncludeDirectory method is provided to add all the files in a directory (and optionally all subdirectories) which match a search pattern. If you determine that your application will benefit from bundling, you can create bundles in the BundleConfig.cs file with the following code:

With this code you are telling the server to create a new script, myBundle, made up of myScript1.js, myScript2.js, and myScript3.js; and add this new bundle to the bundle collection. The bundle collection is a set of the bundles that are available to your application. Although you can refer to the new script in a direct script link, just as you would one of the scripts being bundled, the bundle functionality gives you another path to put this script into your page:

@BundleTable.Bundles.ResolveBundleUrl("~/bundles/myBundle")

This code not only has the benefit of creating the script link for you but it also has the added benefit of generating the hashtag for the script. This means the browser will store the script longer and the client will have to download it fewer times. With the hashtag, browsers get the new script only if the hashtag is different, such as when content in the bundle is completed, or if it hits the internal expiration date, which is generally one year.

Bundles are referenced in views using the Render method, ( @Styles.Render for CSS and @Scripts.Render for JavaScript). The following markup from the Views\Shared\_Layout.cshtml file shows how the default ASP.NET Internet project views reference CSS and JavaScript bundles.

Using bundling in the framework has other advantages as well. If you have both debug and minified versions of a script in your project in the same directory the framework will make a decision on which version to include based on your DEBUG mode (though you only need to provide minified versions for those cases where the default ASP.NET minification does not work). If you are using the built-in minification, by adding the default version of the script to a bundle you can send a minified version when in RELEASE mode and a regular, un-minified, version of the script when in DEBUG mode.

The framework also understands the difference between script.debug.js and script.js. This means that when you have both files in the same folder, and script.js is referenced in your bundle; running in DEBUG mode ensures that the framework will pick up the .debug version of the file and use that rather than the non-debug version; perhaps this version has alert windows in crucial areas, or other items to aid in the debugging of the application. Debugging the application in non-DEBUG mode is more complicated, however, as any errors that are thrown relate to the line number in the bundled file and not the files that you work with while in DEBUG mode.

If you want to put the application in DEBUG mode, set the debug attribute in the compilation element of the web.config to true as shown below:

Bundling is a feature that is provided by the ASP.NET framework that allows the combination of multiple files into a single file automatically. This helps limit the amount of files that need to be downloaded from the server and can enhance performance because it eliminates the need to make multiple connections with the server. It also supports automatically selecting the appropriate script type, whether DEBUG or RELEASE, based on the compilation node within the web.config file. With this robust and built-on functionality it is difficult to conceive of a time when a JavaScript-rich site would not benefit from its use. Be fruitful and de-multiply…