Bundling And Minifying AngularJS JavaScript Code Within ASP.NET MVC 4

In ASP.NET MVC we have the concept of bundling and minification of our JavaScript and stylesheet files that help us to reduce the network calls and pages load size for a particular page request.

For more theoretical information about bundling in MVC you can have a look at the following articles:

In this article we are just going to concentrate about how do we bundle and minify our AngularJS javascript code. For demonstrating this I’m creating a new MVC 4 application with the name “MvcAngularDemo” and setting the project template to “Basic”.

Now I’ll be installing AngularJS package to my application through NuGet.

AngularJS

Click “Install” and this will add AngularJS files to our script folder.

I am adding a new folder inside the script folder with the name “app” which will hold my page specific script files. Also, adding a new script file to the app folder with the name “Home.js”.

The following is the code snippet for the “Home.js” file.

  1. var myApp = angular.module("myApp", []);  
  2.   
  3. myApp.controller("homeController", function ($scope) {  
  4.    $scope.yourName = "";  
  5. });  
It simply has a $scope injected and a model named “yourName” initially set to nothing associated on the $scope. We’ll try to create a minified version of our Home.js file by using the online JavaScript minifier and we’ll store it inside a new file name Home.min.js.

Home.min.js Code

var myApp=angular.module("myApp",[]);myApp.controller("homeController",function(n){n.yourName=""})

I’m adding a new controller with the “HomeController” and creating a view for the “Index” action method.

HomeController.cs
  1. public class HomeController : Controller  
  2. {  
  3.    public ActionResult Index()  
  4.    {  
  5.       return View();  
  6.    }  
  7.   
  8. }  
Index.cshtml
  1. @{  
  2.     ViewBag.Title = "Index";  
  3. }  
  4.   
  5. <link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" />  
  6. <!-- script files referenced-->  
  7. <script src="~/Scripts/angular.js"></script>  
  8. <script src="~/Scripts/app/Home.js"></script>  
  9. <div ng-app="myApp">  
  10.     <div class="container">  
  11.         <h2>Index</h2>  
  12.         <hr />  
  13.         <div ng-controller="homeController">  
  14.             <div class="row">  
  15.                 <div class="col-sm-3">  
  16.                     Enter your name:  
  17.                 </div>  
  18.                 <div class="col-sm-5">  
  19.                     <input type="text" ng-model="yourName" class="form-control" />  
  20.                 </div>  
  21.             </div>  
  22.             <div class="row">  
  23.                 <div class="col-sm-3">  
  24.                     Your Name is:  
  25.                 </div>  
  26.                 <div class="col-sm-5">  
  27.                     <h4>{{yourName}}</h4>  
  28.                 </div>  
  29.             </div>  
  30.         </div>  
  31.     </div>  
  32. </div>   
We here tried to do two way binding using the AngularJS in-built directive “ng-model”. And just trying to display the same value in the following “div”. Just try to run the application and everything would perfectly be working. The following is the output:

output

Now let’s try to bundle our application and also set the EnableOptimization to force bundling in MVC 4 to pick up the minified css and script files.

Let’s replace the code block from “BundleConfig.cs” with the following code snippet:
  1. namespace MvcAngularDemo  
  2. {  
  3.     public class BundleConfig  
  4.     {  
  5.         // For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkId=254725  
  6.         public static void RegisterBundles(BundleCollection bundles)  
  7.         {  
  8.               //Setting the bundle to use CDN path.  
  9.             bundles.UseCdn = true;  
  10.   
  11.             //Referencing the CDN path for the styleBundle (bootStrap).  
  12.             bundles.Add(new StyleBundle("~/bundle/css""http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css"));  
  13.   
  14.             //referencing the jQuery script file.  
  15.             bundles.Add(new ScriptBundle("~/bundles/jQuery").Include("~/Scripts/jquery-1.8.2.min.js"));  
  16.   
  17.             //referencing the angularJs script file.  
  18.             bundles.Add(new ScriptBundle("~/bundles/angularJs").Include("~/Scripts/angular.js"));  
  19.   
  20.             //referencing the our page specific javascript files.  
  21.             bundles.Add(new ScriptBundle("~/bundles/appJs").Include("~/Scripts/app/Home.js"));  
  22.   
  23.             //For enabling optimization forcefully.  
  24.      BundleTable.EnableOptimizations = true;  
  25.         }  
  26.     }  
  27. }  
Note: We’ve enabled our EnableOptimization property to true. So at runtime it will fetch all the minified files for our JavaScript file as well as for our css files.

So now our bundling for the application is done, now let’s try to make use of it inside our Index.cshtml file. I am removing the script and style reference added earlier with the following lines of code.
  1. @Styles.Render("~/bundles/css")  
  2. @Scripts.Render("~/bundles/jQuery")  
  3. @Scripts.Render("~/bundles/AngularJS")  
  4. @Scripts.Render("~/bundles/appJs")  
Now run the application and press F12 and the following is the snapshot for the same.

Now run the application

From the network tab we can say that our minified Home.js file downloaded from the server inside our BundleConfig.cs file, since we’ve enabled EnableOptimization to true.

Downloaded Home.min.js file code snippet is:

var myApp=angular.module("myApp",[]);myApp.controller("homeController",function(n){n.yourName=""});

Now let’s go to Console tab and there we’ve the following error.

index

We’ve an injector error that’s because our AngularJS doesn’t know what this n is? It was expecting a $scope object and so it gives us the injector error.

Now let’s try to update our Home.js file code snippet so that after minification it does not result in an error like the above case. Here is the updated snapshot for the Home.js file.

Home.js
  1. var myApp = angular.module("myApp", []);  
  2.   
  3. myApp.controller("homeController", ["$scope", function ($scope) {  
  4.    $scope.yourName = "";  
  5. }]);  
Note:
  1. Here I encapsulated our function ($scope) inside a JavaScript array. And for the first element of the array I’m expecting the AngularJS $scope defined in double quotes.

  2. Arrays in JavaScript can accept anything: String, integer, objects or even functions.

Now let’s try to minify our Home.js file again. Here is the updated code for the Home.min.js file.

Home.min.js code

  1. var myApp=angular.module("myApp",[]);myApp.controller("homeController",["$scope",function(o){o.yourName=""}]);  
Note: 
  1. As you can see that the javascript minifier just minified those variables names or values which are not enclosed in double quotes.

  2. And the variables names or values inside double quotes will be the same. For example, “homeController” or “$scope” values are not minified. This is because JavaScript minifier will not touch those values which are in double quotes.

  3. Declaring the controller function in this way will help AngularJS to inject the $scope object in the first parameter of our function (o).

Now let’s try to run the application and we’ll see the following output without any error.

run the application