Do not let the bundles ruin your life

  • Tutorial

Recently I encountered a problem of conflict of bundles in an MVC project, it happened that some scripts turned out to be connected several times in different bundles. Separating an extra script from one of them can lead to a serious headache, because the same bundle can be used on different layouts.

I saw different ways of grouping scripts, but to be honest, I did not like any of them to the end. How to group scripts in such a way that it is most difficult to get confused in them and not have to bother about conflicts of different bundles on one page? For myself, I came up with an approach that, in my opinion, will simplify life. I will be very glad for healthy criticism and useful tips.



To begin with, let's try to analyze a couple of approaches for grouping scripts:
The first approach is to group scripts for general purposes.

bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
    "~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
    "~/Scripts/jquery-ui-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
    "~/Scripts/jquery.unobtrusive*",
    "~/Scripts/jquery.validate*"));


It is simple enough and there should not be any problems, but this approach is not enough. Custom scripts also need to be grouped somehow. This is where the second approach arises - combining scripts into some kind of basic bundle.

bundles.Add(new ScriptBundle("~/Scripts/base").Include(
    "~/Scripts/placeholder.js",
    "~/Scripts/modernizr-*",
    "~/Scripts/my-custom-script-1",
    "~/Scripts/my-custom-script-2));


And then the question arises what to include here. Jquery seems to be a basic script, but for it we already have a separate bundle. The same story can happen with any other script that one of the developers in a large team considers that it needs to be included there. Thus, the more opinions - the more unexpected problems with the grouping of scripts.

I chose the following path for myself:
1. For each layout - 1 bundle.
I call the bundle the same name as the layout itself and solve the headache with what to connect, where to connect and how much to connect.

2. Bundles are connected only on layouts.
In the end: how many layouts - so many bundles of the same name.

If here you have a storm of indignation, then hold them to the end of the path, when a complete picture develops.

3. We introduce the concept of groups, which will be just an array of strings.
We group all the necessary scripts for a specific functionality into a group. Here is an example of a group of scripts for rendering reports with graphs on svg canvases:

var reportScriptGroup = new[]
{
    "~/Scripts/jquery-{version}.js",
    "~/Scripts/raphael.js",
    "~/Scripts/Custom/charts.js",
    "~/Scripts/Custom/report.js"
};


Suppose that you need client validation in the same layout, we add a group for validation:

var validationScriptGroup = new[]
{
    "~/Scripts/jquery-{version}.js",
    "~/Scripts/jquery.validate.js",
    "~/Scripts/jquery.validate.unobtrusive.js",
    "~/Scripts/Custom/jquery.custom.validate.js"
};


Pay attention to the presence of jquery- {version} .js in both groups, but this does not prevent us from adding both groups to the same bundle. He will take care of himself to make a distinction.

bundles.Add(new ScriptBundle("~/Scripts/_DashboardLayout")
        .Include(baseScriptGroup)
        .Include(validationScriptGroup)
        .Include(reportScriptGroup)
    )
);


4. I also needed to exclude the script from the group so as not to create a new one.
For example, a script that shows a page gradually blotting it out. It is located in the baseScriptGroup. I absolutely do not need it on the layout to prepare any good for printing or converting to pdf, etc.

Let's write a simple method to exclude a script from the group:

EDITED : according to the user lair, you can use the Except method

private static string[] Exclude(this IEnumerable input, params string[] items)
{
    var output = input;
    foreach (var item in items)
    {
        output = output.Where(x => x != item).ToArray();
    }
    return output.ToArray();
}


And the bundle for him will look like this:

bundles.Add(new ScriptBundle("~/Scripts/_PrintLayout")
        .Include(baseScriptGroup.Exclude("~/Scripts/Custom/fading.js"))
        .Include(reportScriptGroup)
    )
);


That's all. Thus, you can simply merge groups into bundles. I wanted to connect charts - I added a group with charts to the bundle. Wanted validation - add it too.

Only registered users can participate in the survey. Please come in.

Do you find this approach useful?

  • 12.9% Yes, I use something like that. eleven
  • 27% Yes, it’s worth a try. 23
  • 14.1% No, I do not like him. 12
  • 28.2% No, I have no such problems. 24
  • 27% What is a bundle? 23

Also popular now: