The Web optimization framework has gone through some major changes between the Visual Studio 11 Beta and Release Candidate releases. The changes coalesce around 2 primary goals:
- Enable greater control over the default bundles that are registered with the Web application templates.
- Support different debug and release modes so that resources will not be bundled while developing and debugging, but will be bundled and minified when the application is deployed into production.
Specific Changes
In order to achieve these goals, several changes were introduced in both the way that bundles are declared and registered and in the way that bundles are referenced from within a view.
Changes in bundle registration and declaration
EnableDefaultBundles has been deprecated and will be removed for RTM.
When you create a new project, one of the first changes that you may notice is the addition of a .cs or .vb file called BundleConfig. This file has a single method called RegisterBundles and is called from global.asax’s Application_Start method. This class method now performs all of the creation and registration logic for bundles that are used by the default templates. In beta, we performed all of this registration by calling a method which was built into the framework assembly such as RegisterTemplateBundles or EnableDefaultBundles. Having this method included as code in your project now gives you greater visibility into what bundles are available to your views as well as gives you more flexibility in modifying the configuration. In RC, we also create separate bundles for jQuery, jQuery UI, etc. in the default bundle configuration to enable more fine-grained control over what assets are included on a page and where they are included.
Additionally, we’ve simplified the code that declares and registers the bundles. For example, consider the following Beta registration:
In RC, this code is now written as:
As you can see, some of the improvements here include:
- Creating strongly-typed bundle classes for styles and scripts which automatically wire up the appropriate default bundle transformer (minifier)
- Enabling method chaining to avoid the 3-step process of create/configure/add to collection
- Enable file inclusion via a params array to avoid multiple calls to AddXxX
Changes in how bundles are referenced within views
In addition to streamlining the workflow for declaring bundles and registering them with the bundle manager, we’ve also improved how bundles are included in views. These changes will greatly simply the task of reconfiguring how bundling and minification works when switching between different development configurations such as debug and release.
In beta, a bundle was referenced in a view by using a helper method to generate the appropriate bundle URL inside of a script tag, as follows:
<link href=’@BundleTable.Bundles.ResolveBundleUrl(“~/Content/themes/base/css”)’ rel=”stylesheet” type=”text/css” />
<script src=’@BundleTable.Bundles.ResolveBundleUrl(“~/Scripts/js”)’></script>
While this approach works fine, for resolving the bundle URL – even for getting a version-stamped bundle URL – it becomes limiting when working in a debugging scenario. In this case, it is likely that the bundle should be expanded into a set of assets, and that each one of those should render an individual script or link element on the page.
As such, for RC, this behavior can be achieved with the Styles.Render and Scripts.Render helper methods. For example, the code above can be rewritten as:
@Styles.Render(“~/Content/themes/base/css”)
@Scripts.Render(“~/Scripts/js”)
Additionally, these helper methods accept a params array of URLs to render, so you can pass references to several bundles in the same helper method call:
@Styles.Render(“~/Content/themes/base/css”, “~/Content/css”)
Using this approach, when in debug mode ((<compilation debug=”true” />), script and styles that are registered into bundles will be expanded into individual script or CSS elements on the page. When releasing the site, those files will be bundled and minified. By default, this property looks at the IsDebuggingEnabled property of the current HttpContext, meaning that it can be controlled in Web.config by setting the debug attribute in the compilation Element to false as shown below:
<compilation debug=”false” />
You can override the Web.config setting with the static EnableOptimizations property on the BundleTable class.
While these helper methods provide support for switching between debug and release modes, there may be times where you still want more direct control over your HTML markup and retain the previous behavior or having the optimization framework simply generate the correct bundle URL. In RC, we continue to make that scenario possible through the URL helper method on the Styles and Scripts classes, as follows:
<script type=”text/javascript” src=’@Scripts.Url(“~/bundles/modernizr”)’></script>
This approach provides complete control over the script or link markup elements, though at the expense of debug support.
Plugging in custom minification libraries
As in previous release, the framework continues to enable custom transformation libraries to participate in rendering bundles, in addition to the default JsMinify and CssMinify transformation classes. In RC, however, the framework enables multiple transformations to be applied to a single bundle (whereas in Beta, this was accomplished by creating a custom composite transform class). For example, consider the following custom bundle transform class that converts LESS script into CSS using the dotless library.
This transformation can be chained together with the default CssMinify bundle transform and configured for a bundle using the following:
The order of transform execution is based on the order the transform instances are added to the bundle’s Transforms collection. In the code above, LessTransform is run before CssMinify.
Pingback: MVC 4 @Scripts "does not exist"
Pingback: June 4th What’s Happening Around Visual Studio | MSDN Blogs