Bundling and Minification of JS and CSS in ASP.NET Using GruntJS

Tarun Kumar Chatterjee
 
Net – Technology Specialist
May 23, 2019
 
Rate this article
 
Views
1568

In ASP.NET MVC project we can have BundleConfig.cs class within App_Start folder. In the class we generally have RegisterBundles method to bundle Scripts/CSS. To minify the Scripts and CSS at runtime we need to use BundleTable.EnableOptimizations = true;

Now we will see instead of using ASP.Net RegisterBundles how we can achieve bundling and minification functionalities by using NPM Grunt package.

So, first we need to install nodejs 32 bit installer from: https://nodejs.org/dist/v4.4.6/node-v4.4.6-x86.msi

Visual Studio 2015 has great support for managing packages via NPM and for running Grunt and Gulp tasks.

Let me first create a MVC project named as “GruntJSBundlingMinificationDemoMVC”

Install NPM Task Runner to run/watch the grunt task execution

 

Right click on the Solution and click on Quick Install Package and then type grunt and click on install

It will internally run npm command to install grunt component

After installation is successful one package.json file and gruntfile.js will be added within the solution

Another way is you can directly add the package.json file and gruntfile.js by right click on the solution — > add new item — > Add “NPM configuration file” and “Grunt configuration file”.

Within the Package.json I have added the below piece of code

 {
   "name": "myproject",
   "version": "1.0.0",
   "dependencies": {
     "time-grunt": "1.3.0"
   },
   "devDependencies": {
     "grunt": "^1.0.1",
     "grunt-contrib-clean": "~1.0.0",
     "grunt-contrib-uglify": "~1.0.1",
     "grunt-contrib-cssmin": "~1.0.1",
     "grunt-filerev": "~2.3.1",
     "grunt-filerev-assets": "~1.0.0",
     "grunt-contrib-watch": "~1.0.0",
     "grunt-timer": "0.6.0"
   },
   "-vs-binding": { "BeforeBuild": [ "install" ] }
 }
 

Package.json is nothing but the references we need to add to install the grunt components whatever is needed. “We have added “BeforeBuild” event which signifies that the grunt components will be installed before the solution build started.

Within the Gruntfile.js file I have added the below piece of code

 /// <binding BeforeBuild='build' Clean='clean' ProjectOpened='watch:bundles' />
 /*
 This file in the main entry point for defining grunt tasks and using grunt plugins.
 Click here to learn more. http://go.microsoft.com/fwlink/?LinkID=513275&clcid=0x409
 */
 
 module.exports = function (grunt) {    
     require('time-grunt')(grunt);
     grunt.initConfig({
         pkg: grunt.file.readJSON('package.json'),
 
         clean: {
             build: ['bundles']
         },
 
         uglify: {
             options: {
                 sourceMap: false
             },
 
          build: {
                files: {
                     'bundles/jquery.js': ['Scripts/jquery-*.min.js'],
                     'bundles/jqueryval.js': ['Scripts/jquery.validate*.min.js'],
                     'bundles/modernizr.js': ['Scripts/modernizr-*.js'],
                     'bundles/bootstrap.js': ['Scripts/bootstrap.js', 'Scripts/respond.js'],
                     'bundles/site.js': ['Scripts/site.js']
                 }
             }
         },
 
         cssmin: {
             options: {
                 sourceMap: true
             },
             build: {
                 files: {
                     'bundles/main.css': ['Content/bootstrap.css', 'Content/site.css']
                 }
             }
         },
         
         watch: {
             bundles: {
                 files: ['Scripts/**/*.js', 'Content/**/*.css'],
                 tasks: ['build']
             }
         }
 
     });
 
     grunt.loadNpmTasks('grunt-contrib-clean');
     grunt.loadNpmTasks('grunt-contrib-uglify');
     grunt.loadNpmTasks('grunt-contrib-cssmin');
     grunt.loadNpmTasks('grunt-filerev');
     grunt.loadNpmTasks('grunt-filerev-assets');
     grunt.loadNpmTasks('grunt-contrib-watch');
 
     grunt.registerTask('build', ['uglify', 'cssmin']);
 };
 

At the top of the files I have specified the bindings. It signifies that the Grunt Build task and clean task will be triggered before solution build started. And as soon as project is opened it will start watching on the bundles.

Clean task will be used to clean up the bundles.

Uglify task will be created the JS bundle.

Cssmin task will created the CSS bundle.

Now we are ready to build the Gruntfile.js from Task Runner Explorer

Right click on the solution and go to Task runner explorer

We can run any task by right click on the task and click on Run

Here I am running Build task which will run uglify and cssmin task to bundle and minify JS and CSS

We should Comment out all the default bundle configuration in BundleConfig.cs file as we are no more using Asp.Net bindings

So, our Bundles scripts and css will be created after running the above task. The above steps are for manually running Grunt Task. As we have already specified the bindings details on top of Grunfile.js, so accordingly before solution build start the Build task will be executed.

Now in _Layout.cshtml page changed the bundling references

 @using GruntJSBundlingMinificationDemoMVC
 <!DOCTYPE html>
 <html>
 <head>
     <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>@ViewBag.Title - My ASP.NET Application</title>
     @*@Styles.Render("~/Content/css")
     @Scripts.Render("~/bundles/modernizr")*@
             
     <link href="~/bundles/main.css" rel="stylesheet" />
     <script src="~/bundles/modernizr.js"></script>
 
 </head>
 <body>
     <div class="navbar navbar-inverse navbar-fixed-top">
         <div class="container">
             <div class="navbar-header">
                 <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                     <span class="icon-bar"></span>
                     <span class="icon-bar"></span>
                     <span class="icon-bar"></span>
                 </button>
                 @Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
             </div>
             <div class="navbar-collapse collapse">
                 <ul class="nav navbar-nav">
                     <li>@Html.ActionLink("Home", "Index", "Home")</li>
                     <li>@Html.ActionLink("About", "About", "Home")</li>
                     <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                 </ul>
             </div>
         </div>
     </div>
     <div class="container body-content">
         @RenderBody()
         <hr />
         <footer>
             <p>© @DateTime.Now.Year - My ASP.NET Application</p>
         </footer>
     </div>
     @*@Scripts.Render("~/bundles/jquery")
     @Scripts.Render("~/bundles/bootstrap")*@
         
     <script src="~/bundles/jquery.js"></script>
     <script src="~/bundles/bootstrap.js"></script>
     <script src="~/bundles/site.js"></script>
     
 </body>
 </html>
 

 

Now build the solution and run

 

In the output we can see that the page has been rendered with CSS and JS properly. While going to the page source we can see the scripts and css all are minified properly.

Hope this article helps you to understand the basic idea about NPM grunt package, purpose of using and the implementation.

Happy Coding

Tarun Kumar Chatterjee

 

 

Category : .Net

Author Info

Tarun Kumar Chatterjee
 
Net – Technology Specialist
 
Rate this article
 
Tarun has been working in IT Industry for over 12+ years. He holds a B-tech degree. He is passionate about learning and sharing the tricks and tips in Azure, .Net ...read more
 

Leave a comment