Bundling and Minification support within ASP.NET (Web Forms & MVC) finally arrived in .NET 4.0, and has had a good course of use over the past year. If you are anything like me and upgrading your projects from .NET 3.5 with already built-in custom minifiers and bundlers, you likely haven’t gotten a chance to explore the new hotness out of the box. Here are some thoughts and gotcha’s.
The Include method of a bundle is the key to adding all the files you wish to bundle together. However, this include MUST use a relative virtual path to your application. Behind the scenes the base Bundle classes uses MapPath and FileInfo objects to assemble the bundle. This means you can forget about adding multiple CDN or external assets to a single bundle. The application will throw an error if you provide a path that does not start with “~”.
This is a fantastic feature about the Bundling and Minification. When you are in debug mode you see the scripts non-minified, and separated by file for easy debugging in Chrome Tools or whatever. When you’re in release mode the code automatically switches to use the bundle – read on for more information on the gotcha’s!
The only difference between a ScriptBundle and a Bundle is that the ScriptBundle uses a “JsMinify” transform (a default one) – this is the same for the StyleBundle vs the Bundle as well (uses a CssMinify). This minification on the script bundle will ALWAYS happen, even in debug mode. This is contrary to what most people will inform you of. That’s because commonly in MVC you’ll use the @Scripts.Render HTML Helper to render your bundles. This helper will enumerate the bundle and add the direct paths to the files avoiding the bundling route altogether for debug mode. However, if you truly want to show a bundle that is not minified from the bundle route, you’ll need to use “Bundle” and not “ScriptBundle” (or clear the transformations from the ScriptBundle / StyleBundle).
Custom bundles is a fantastic addition that is super easy to use, and really allows you to take advantage of other resources such as LESS or SASS as an example. Simply create a “Bundle” and add transforms that you create: bundle.Transforms.Add(new Transform()) -> create your custom transform out of the IBundleTransform interface using the Process method (Google it). You can also create a new Bundle type that inherits from Bundle and apply your transforms directly in one re-useable class such as “Script2Bundle” (that’s only if your cool like that though J).
Yes it does cache! However, it uses a “v” URL token that indicates the current state of the files in that bundle. If they change, the token changes. AWESOME! But, always be aware of the cache and that you can set the Cache-ability using bundle.Cacheability.
Yes it does support CDNs. However, every CDN must consist of a single bundle. You cannot bundle multiple CDNs into a single local bundle. But, you can provide .Includes against a CDN bundle to which the Bundle will use if the CDN is not reachable, or if you are in debug mode. Also note that CDN content is never minified either – you get it as it comes from the source.
You can force the usage of actually using the bundled resources regardless of Debug or Release mode by setting this to true. This is really a must in order to test your bundles created from CDNs and ensure there are no issues with your bundled assets. If you decide to use a bundle that in turn uses a CDN with no .Include you must set this to true, otherwise your bundle will be empty as it will not use CDN sources while in debug by default.
If you need to turn off CDN usage altogether, even in Release mode, and fallback to your local .Include assets, you can do so by setting this to false.