Gotcha’s ASP.NET MVC Bundling and Minification

This post in not about how to  minify and bundle your js and css files. It is about some of the gotcha’s that I came across about bundling and minification.

The take away here is-

  1. Keep in mind while creating the route path of your bundles carefully as it starts looking for resources with respect to the root path. This will also help you to understand that what all files you can put in one bundle.
  2. Do not use minified files in your bundle as it will create problems while loading them in Development mode, let MVC do the minification for you.

Just a brief , bundling and minification is used to bundle your js and css files so that the server do not sends multiple individual requests to fetch these files and instead sends one single request to fetch the bundle of your js/css files that you have bundled together.

One interesting thing that I came across about bundling and minification today that I wanted to share was –

using System.Web;
using System.Web.Optimization;

namespace ProWorldz.Web
{
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{

               //this is a bundle
bundles.Add(new ScriptBundle(“~/bundles/jquery”).Include(
“~/Scripts/jquery-{version}.js”));

              }

        }

}

Now here are the Gotcha’s

  1.    Your files will not be minified until you have set compilation debug = false in your web.config file.You can override this parameter by adding BundleTable.EnableOptimizations = true in your BundleConfig.cs file which will set debug = false in web.config file or you can set it to false manually .Which means that you are now in Production mode and not in Development mode.
  2. @using System.Web.Optimization is a must .
  3. Interesting part bundling looks for the minified version of the files that you have referenced, in case of BundleTable.EnableOptimizations = true or compilation debug = false and if  no minfied files are present it will automatically minify the files.
    The catch here is that if you have set BundleTable.EnableOptimizations = false and you referenced minified files in your bundle it will ignore these files assuming that you are in Development mode and will not load these files.
    So the best practice would be  to always refer unminifed files in your BundleConfig.cs file and it will automatically look for the minifed file and if not found it will minify the file on its own.

Example

bundles.Add(new ScriptBundle(“~/bundles/jqueryval”).Include(
“~/Scripts/jquery.unobtrusive.min.js”,
“~/Scripts/jquery.validate.js”));

In this case only validate.js file will be loaded in the browser and jquery.unobtrusive.min.js will be ignored in case of  BundleTable.EnableOptimizations  set to false and this is because it will assume that you are not in Production mode and minified files will not be loaded.

4. In case of Style bundle(css bundling) if you are bundling a css file that is referencing  an image inside a class by its relative path like ../images/img1.png then you have to be careful while naming your Style Bundle.

Example

bundles.Add(new StyleBundle(“~/Content/loginstyles”).Include( //root path here is “~/Content/loginstyles”
“~/Content/themes/social-3/css/theme-core.min.css”,
“~/Content/themes/social-3/css/module-layout.min.css”,
“~/Content/themes/custom/Proworldz.login.css”));

In the above case module-layout.min.css was refering to an image inside ~/Content/themes/social-3/images using this relative path ../images/img1.png when I named my bundle as mentioned above it was unable to find the image as it was looking into ~/Content/images.

Then I changed it to

bundles.Add(new StyleBundle(“~/Content/themes/social-3/login/loginstyles”).Include(
“~/Content/themes/social-3/css/theme-core.min.css”,
“~/Content/themes/social-3/css/module-layout.min.css”,
“~/Content/themes/custom/Proworldz.login.css”));

Now it moved one step back i.e. it skipped the login folder and looked for an image folder inside “~/Content/themes/social-3/ for as image folder which was the location of the image.

I hope this saves your time.

JavaScript call vs bind vs apply

All these methods are used for similar use but with very small difference.They are used to set the context (i.e set which object will be bound to this)during a function call.

bind() – Problem 1

var user = {
    data        :[
        {name:"T. Woods", age:37},
        {name:"P. Mickelson", age:43}
    ],
    clickHandler:function (event) {
        $ ("input").val (this.data[0].name + " " + this.data[0].age);
    }

}

// Assign an eventHandler to the button's click event​
$ ("button").click (user.clickHandler);

When you click the button, you get an error because this in the clickHandler () method is bound to the button HTML element, since that is the object that the clickHandler method is executed on.

Solution :

$ ("button").click (user.clickHandler.bind (user));

Problem 2

// This data variable is a global variable​
var data = [
    {name:"Samantha", age:12}
]

var user = {
    // local data variable​
    data    :[
        {name:"T. Woods", age:37}
    ],
    showData:function (event) {
        console.log (this.data[0].name + " " + this.data[0].age);
    }

}

// Assign the showData method of the user object to a variable​
var showDataVar = user.showData;

showDataVar (); // Samantha 12 (from the global data array, not from the local data array)​

This happens because showDataVar () is executed as a global function and use of this inside showDataVar () is bound to the global scope, which is the window object in browsers.

Solution :

// Bind the showData method to the user object​
var showDataVar = user.showData.bind (user);

// Now the we get the value from the user object because the this keyword is bound to the user object​
showDataVar (); // P. Mickelson 43​

apply() vs call() vs bind()

The apply and call methods are almost identical when setting the this value except that you pass the function parameters to apply () as an array, while you have to list the parameters individually to pass them to the call () method.

They can be used for method borrowing

call()

var anArrayLikeObj = {0:"Martin", 1:78, 2:67, 3:["Letta", "Marieta", "Pauline"], length:4 };
var newArray = Array.prototype.slice.call(anArrayLikeObj , 0);
console.log (newArray);  //["Martin", 78, 67, Array[3]

This could have also done with bind and apply

apply() 

var newArray = Array.prototype.slice.apply(anArrayLikeObj , [0]);
console.log (newArray);  //["Martin", 78, 67, Array[3]

bind()

var newArray = Array.prototype.slice.bind(anArrayLikeObj , 0);
console.log (newArray); //function b()

This is the main difference between these three functions – 

apply takes array as argument list

Call takes simple list of arguments

Both call and apply returns value whereas bind returns function that has to be invoked.


call() vs apply()

Call can be used for  variable-arity, also known as variadic functions.
These are functions that accept any number of arguments instead of a fixed number of arguments.

var allNumbers = [23, 11, 34, 56];
// We cannot pass an array of numbers to the Math.max method like this​
console.log (Math.max (allNumbers)); // NaN
var allNumbers = [23, 11, 34, 56];
// Using the apply () method, we can pass the array of numbers:​
console.log (Math.max.apply (null, allNumbers)); // 56

Well I guess the differences are pretty clear now.


References

JavaScriptIsSexy Call Apply Bind