I was wondering if anybody can help me with bundling and minifying using the new optimization namespace shipped with MVC 4. I have a Multitenant-application in which I want to decide which js files should be loaded based on settings per user. One approach would be to create all bundles upfront and change the virtual path of resolvebundleurl based on the setting of the user, but that feels not really the right way. Also I have dynamic css in a cshtml view based on user-settings, which I would like to have minified in runtime.
Any suggestions? I also see a lot of reactions in other questions to check out Requestreduce, but they are all from the same user.
What would be the best approach to handle both situations?
Thanks in advance!
Bundling and Minification are two performance improvement techniques that improves the request load time of the application. Most of the current major browsers limit the number of simultaneous connections per hostname to six. It means that at a time, all the additional requests will be queued by the browser.
Bundling and minification are two techniques you can use in ASP.NET 4.5 to improve request load time. Bundling and minification improves load time by reducing the number of requests to the server and reducing the size of requested assets (such as CSS and JavaScript.)
Bundle TypesScriptBundle: ScriptBundle is responsible for JavaScript minification of single or multiple script files. StyleBundle: StyleBundle is responsible for CSS minification of single or multiple style sheet files.
The MVC provides us the two features to reduce the number of requests to access the resource file on the server i.e. Bundling and Minification. Bundling is one of the features of MVC. By implementing this, we can improve performance request load time.
One approach you can take is building the bundle dynamically when the application starts. So if your scripts are located in ~/scripts
you can do:
Bundle bundle = new Bundle("~/scripts/js", new JsMinify());
if (includeJquery == true) {
bundle.IncludeDirectory("~/scripts", "jquery-*");
bundle.IncludeDirectory("~/scripts", "jquery-ui*");
}
if (includeAwesomenes == true) {
bundle.IncludeDirectory("~/scripts", "awesomeness.js");
}
BundleTable.Bundles.Add(bundle);
Then your markup can look like this
@Scripts.Render("~/Scripts/Libs/js")
Note: I'm using the latest nuget package for system.web.optimization (now Microsoft.AspNet.Web.Optimization) located here. Scott Hanselman has a good post about it.
i wrote a helper function to dynamic minify my css & js
public static IHtmlString RenderStyles(this HtmlHelper helper, params string[] additionalPaths)
{
var page = helper.ViewDataContainer as WebPageExecutingBase;
if (page != null && page.VirtualPath.StartsWith("~/"))
{
var virtualPath = "~/bundles" + page.VirtualPath.Substring(1);
if (BundleTable.Bundles.GetBundleFor(virtualPath) == null)
{
var defaultPath = page.VirtualPath + ".css";
BundleTable.Bundles.Add(new StyleBundle(virtualPath).Include(defaultPath).Include(additionalPaths));
}
return MvcHtmlString.Create(@"<link href=""" + HttpUtility.HtmlAttributeEncode(BundleTable.Bundles.ResolveBundleUrl(virtualPath)) + @""" rel=""stylesheet""/>");
}
return MvcHtmlString.Empty;
}
public static IHtmlString RenderScripts(this HtmlHelper helper, params string[] additionalPaths)
{
var page = helper.ViewDataContainer as WebPageExecutingBase;
if (page != null && page.VirtualPath.StartsWith("~/"))
{
var virtualPath = "~/bundles" + page.VirtualPath.Substring(1);
if (BundleTable.Bundles.GetBundleFor(virtualPath) == null)
{
var defaultPath = page.VirtualPath + ".js";
BundleTable.Bundles.Add(new ScriptBundle(virtualPath).Include(defaultPath).Include(additionalPaths));
}
return MvcHtmlString.Create(@"<script src=""" + HttpUtility.HtmlAttributeEncode(BundleTable.Bundles.ResolveBundleUrl(virtualPath)) + @"""></script>");
}
return MvcHtmlString.Empty;
}
usage
~/views/Home/Test1.cshtml
~/Views/Home/Test1.cshtml.css
~/Views/Home/Test1.cshtml.js
in Test1.cshtml
@model object
@{
// init
}@{
}@section MainContent {
{<div>@{
if ("work" != "fun")
{
{<hr/>}
}
}</div>}
}@{
}@section Scripts {@{
{@Html.RenderScripts()}
}@{
}@section Styles {@{
{@Html.RenderStyles()}
}}
but ofcoz, i put most of my sripts,styles in ~/Scripts/.js, ~/Content/.css
and register them in Appp_Start
We considered supporting dynamic bundles early on, but the fundamental issue with that approach is multi server scenarios (i.e. cloud) won't work. If all bundles are not defined in advance, any bundle requests that get sent to a different server than the one that served the page request will get 404 response(as the bundle definition would only exist on server that handled the page request). As a result, I would suggest creating all bundles up front, that's the mainline scenario. Dynamic configuration of bundles might work as well, but that is not a fully supported scenario.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With