Let's suppose I have these two script bundles configured:
bundles.Add(new ScriptBundle("~/Scripts/Bootstrap").Include(
"~/Content/Scripts/jQuery/jquery-2.1.1.js",
"~/Content/Scripts/Bootstrap/bootstrap.js"));
bundles.Add(new ScriptBundle("~/Scripts/jQuery").Include(
"~/Content/Scripts/jQuery/jquery-2.1.1.js"));
As you can see, ~/Scripts/Boostrap
uses a jQuery JavaScript file and a Bootstrap one. This is because the Bootstrap one requires jQuery to work.
On the other hand, ~/Scripts/jQuery
is composed of only the jQuery file.
I want to have two bundles in case a view only needs jQuery and not Bootstrap.
However, I am replicating code here, I am defining the jQuery JavaScript file path twice.
Is there a way to tell the ~/Scripts/Boostrap
bundle to use or "inject" another bundle?
Something like this:
bundles.Add(new ScriptBundle("~/Scripts/Bootstrap").UseBundle("~/Scripts/jQuery").Include(
"~/Content/Scripts/Bootstrap/bootstrap.js"));
Both bundling and minification are the two separate techniques to reduce the load time. The bundling reduces the number of requests to the Server, while the minification reduces the size of the requested assets.
To enable bundling and minification, set the debug value to "false". You can override the Web. config setting with the EnableOptimizations property on the BundleTable class. The following code enables bundling and minification and overrides any setting in the Web.
Bundling reduces the number of individual HTTP requests to server by combining multiple CSS files and Javascript files into single CSS file and javascript file. Minification reduces the file download size of CSS and javascript files by removing whitespace, comments and other unnecessary characters.
Make a script bundle include another script bundle
Not directly using the Bundling class.
Let say in your scenario that the business decides to only send a single bundle to the client for every request. You've decided to bundle all the scripts needed for each controller (in this magical world). You might start off with something like this:
bundles.Add(new ScriptBundle("~/Scripts/Home")
.Include("~/Content/Scripts/jQuery/jquery-2.1.1.js",
"~/Content/Scripts/Bootstrap/bootstrap.js"
"~/Content/Scripts/Home.js"));
bundles.Add(new ScriptBundle("~/Scripts/Account")
.Include("~/Content/Scripts/jQuery/jquery-2.1.1.js",
"~/Content/Scripts/Bootstrap/bootstrap.js"
"~/Content/Scripts/Account.js"));
Then realizing that .Include(string[]) simply takes an array of string, you could DRY your code into something like:
var commonScripts = new List<string>()
{
"~/Content/Scripts/jQuery/jquery-2.1.1.js",
"~/Content/Scripts/Bootstrap/bootstrap.js"
};
var homeScripts = new List<string>()
{
"~/Content/Scripts/Home.js"
};
bundles.Add(new ScriptBundle("~/bundles/home/")
.Include(commonScripts.Concat(homeScripts).ToArray()));
var accountScripts = new List<string>()
{
"~/Content/Scripts/Account.js"
};
bundles.Add(new ScriptBundle("~/bundles/account/")
.Include(commonScripts.Concat(accountScripts).ToArray()));
I don't recommend the business reasons behind this solution, but I think the logic that solves it could be used similarly to solve your problem.
If you think you're going to possibly have duplicates you could also:
.Include(commonScripts.Concat(accountScripts)
.Distinct()
.ToArray()));
Personally I wouldn't include jQuery or BootStrap in bundles, as they are available from many CDNs online for free which; A means I use less of my bandwidth, and B the client may have already downloaded the scripts I need (The reasons CDNs exist for common scripts/styles anyway).
You could also consider creating a ComposableBundle
wrapper class that allows you to compose bundles with the .UseBundle(someBundle)
syntax.
For example the following class and extensions methods:
public class ComposableBundle<T> where T : Bundle
{
private T _bundle;
private List<string> _virtualPaths = new List<string>();
public ComposableBundle(T bundle)
{
_bundle = bundle;
}
public string[] VirtualPaths
{
get { return _virtualPaths.ToArray(); }
}
public T Bundle
{
get { return _bundle; }
}
public ComposableBundle<T> Include(params string[] virtualPaths)
{
_virtualPaths.AddRange(virtualPaths);
_bundle.Include(virtualPaths);
return this;
}
public ComposableBundle<T> UseBundle(ComposableBundle<T> bundle)
{
_bundle.Include(bundle.VirtualPaths.ToArray());
return this;
}
}
public static class BundleExtensions
{
public static ComposableBundle<T> AsComposable<T>(this T bundle) where T : Bundle
{
return new ComposableBundle<T>(bundle);
}
public static ComposableBundle<T> Add<T>(this BundleCollection bundles, ComposableBundle<T> bundle) where T: Bundle
{
bundles.Add(bundle.Bundle);
return bundle;
}
}
Would allow you to configure your bundles like this:
var jQueryBundle = bundles.Add(new ScriptBundle("~/bundles/jquery").AsComposable()
.Include("~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryui").AsComposable()
.UseBundle(jQueryBundle)
.Include("~/Scripts/jquery-ui-{version}.js"));
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