15

I am working on an ASP.Net MVC 4 application and using Bundling and minifiction to render styles and script files.

I have a script file (File A) that call function in another file (File B) , when I am using
@Scripts.Render() method it render link tag for File A before File B so it fire an error and the script not work correctly.

Is there any way to force @Script.Render() to render link tags in certain order without using separate bundle for each file????

EDIT

I am using IncludeDirectory method to include all script files in that folder

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        bundles.Add(new ScriptBundle("~/bundles/js").IncludeDirectory(
                    "~/Scripts/js",
                    "*.js"));
    }
}
MikeSmithDev
  • 15,731
  • 4
  • 58
  • 89
Amir Ismail
  • 3,865
  • 3
  • 20
  • 33
  • Please show how you are adding the scripts to your page and bundle. You can create your own bundles and add the scripts in the order you want. http://stackoverflow.com/questions/14544277/how-to-load-the-latest-javascript-files-every-time-the-user-visits-the-website/14544347#14544347 – MikeSmithDev Jan 28 '13 at 13:50
  • @MikeSmithDev thanks, the post you provided is helpful but I am greedy :) and want to know if there is another approach to do that – Amir Ismail Jan 28 '13 at 14:03
  • 2
    From www.asp.net: "Adding scripts by wildcard defaults to loading them in alphabetical order, which is typically not what you want. CSS and JavaScript files frequently need to be added in a specific (non-alphabetic) order. You can mitigate this risk by adding a custom IBundleOrderer implementation, but explicitly adding each file is less error prone." – MikeSmithDev Jan 29 '13 at 13:59
  • @MikeSmithDev even with not using * I still get the downloads in random order – Nikos Mar 01 '13 at 11:47
  • @Nikos without seeing your code, IDK. Both methods I showed work to specify the order. Note that even if you specify an order, it *will* move certain known scripts to the front (like jquery), so that could be it. Otherwise, I haven't had problems setting what scripts go where. – MikeSmithDev Mar 01 '13 at 14:20
  • @MikeSmithDev opps I had the wrong js link – Nikos Mar 01 '13 at 15:08

4 Answers4

9

Bundling by default will add the scripts alphabetically. It will move around known libraries and add them in the correct order (it will put jQuery in first, and then jQuery-ui, for example).

The easiest way is to order the scripts yourself. One way is to move off your custom scripts to a different folder, and then add all the scripts into their own bundle in the order you want:

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        bundles.Add(new ScriptBundle("~/bundles/js").IncludeDirectory(
                    "~/Scripts/js","*.js"));

        bundles.Add(new ScriptBundle("~/bundles/myScripts").Include(
            "~/Scripts/custom/scriptB.js",
            "~/Scripts/custom/scriptA.js"));
    }
}

One other option is wildcards. This option still includes moving your custom scripts to their own folder, but only having one bundle (source):*

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {       
        bundles.Add(new ScriptBundle("~/bundles/js").Include(
            "~/Scripts/*.js",
            "~/Scripts/custom/scriptB.js",
            "~/Scripts/custom/scriptA.js"));
    }
}

Also concerning your comment "Is there any way to force @Script.Render() to render link tags in certain order without using separate bundle for each file" -- note that separate link tags is only happening in debug mode. Once you do deploy in release mode, there will only be one link tag and one file.

TotPeRo
  • 6,561
  • 4
  • 47
  • 60
MikeSmithDev
  • 15,731
  • 4
  • 58
  • 89
6

Write your own orderer as Darin Dimitrov answer in this question: How can I specify an explicit ScriptBundle include order?

public class MyBundleOrderer : IBundleOrderer
{
    public virtual IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files)
    {
        //any ordering logic here

        return files;
    }
}
Community
  • 1
  • 1
webdeveloper
  • 17,174
  • 3
  • 48
  • 47
  • 1
    I took my [custom IBundleOrderer](http://havethunk.wordpress.com/2013/04/22/javascript-dependency-order-and-asp-net-mvc-bundles) a step further and had it process each file and determine the dependency chain. A bit late, but it might help future searchers. – HaveThunk Apr 23 '13 at 07:28
1

Have a look at BundleCollection.FileSetOrderList for ordering of bundeled files. I found this blog post about it: http://weblogs.asp.net/imranbaloch/archive/2012/09/30/hidden-options-of-asp-net-bundling-and-minification.aspx which explains it pretty good.

Example code for JQuery ordering:

BundleFileSetOrdering bundleFileSetOrdering1 = new BundleFileSetOrdering("jquery");
bundleFileSetOrdering1.Files.Add("jquery.js");
bundleFileSetOrdering1.Files.Add("jquery-min.js");
bundleFileSetOrdering1.Files.Add("jquery-*");
bundleFileSetOrdering1.Files.Add("jquery-ui*");
bundleFileSetOrdering1.Files.Add("jquery.ui*");
bundleFileSetOrdering1.Files.Add("jquery.unobtrusive*");
bundleFileSetOrdering1.Files.Add("jquery.validate*");
bundles.FileSetOrderList.Add(bundleFileSetOrdering1);
Arne H. Bitubekk
  • 2,963
  • 1
  • 27
  • 34
0

You should consider using Cassette http://getcassette.net/ It supports auto detection of script dependencies based on script references found inside each file.

If you prefer sticking to MS Web Optimization solution but like the idea of arranging scripts based on script references you should read my post blog at http://blogs.microsoft.co.il/oric/2013/12/27/building-single-page-application-bundle-orderer/

Ori Calvo
  • 426
  • 5
  • 6