Using GruntJS in a MEAN Stack Application

Free Course

Getting Started with Angular 2

Angular 2 is the shiny new framework that comes with a lot of new concepts. Learn all the great new features.

If you’ve used a fully fledged MEAN stack like mean.io or meanjs.org, then you’ve probably noticed you can use Grunt to start up your Node server by running a simple: Instead of running:
$ node server.js

We can just run a simple:

$ grunt

Your server will be up and running and will

watch for file changes to run tasks and restart the server! We’ll be looking at how to set up our MEAN stack apps so that we can start them with and use Grunt. For more information on getting started with Grunt, check out our simple guide.

What are the benefits?

Grunt is a great tool for automating many things in our applications. From minifying files, processing LESS, linting our JS files, and so much more,

it is just easier to have Grunt start and watch our Node server for changes, process those changes/run tasks, and keep our restart our server for us. We don’t have to run separate Grunt and node (or nodemon) commands and having just telling people to run grunt is simple enough. We’ll be setting up a simple MEAN stack application and then using Grunt to streamline our workflow. If you want to skip the MEAN stuff and go straight to the Grunt, here you go. Otherwise, let’s get started.

What We’ll Be Building

Let’s look at how a simple MEAN app can use Grunt. Our app will consist of:

  • A simple view
  • An Angular controller, service, and main Angular module
  • Use Grunt to process CSS (LESS and minify)
  • Use Grunt to process JS (jshint and minify)
  • Use Grunt to watch for file changes and process them
  • Use Grunt to start the Node server

Make sure you have Grunt installed first.

$ npm install -g grunt-cli

Let’s get the easy stuff out of the way. We’re not really here to mess with the views or Angular parts so we’ll just create those files quickly. For a more in depth look at creating MEAN apps, here is a

starter tutorial and a tutorial on how to build a MEAN to do application.

Setting Up Our Files

One of the biggest changes we’ll have when using Grunt is our file structure. We will use a

src and a dist folder. The files we work in will be in the src folder. The files we will use for our application will be in the dist folder. Here is the file structure with some comments explaining what they do.


- publci

----- dist
---------- css
--------------- style.css           // generated from the src/style.less file
--------------- style.min.css       // generated from the style.css file above
---------- js
--------------- app.min.js          // generated from all the src/js files

----- src
---------- css 
--------------- style.less
---------- js
--------------- controllers
-------------------- MainCtrl.js
--------------- services
-------------------- TestService.js
--------------- app.js

----- views
---------- index.html

- Gruntfile.js
- package.json
- server.js

I know this seems like a lot, but don’t worry, Grunt will create the files in the

dist folder for us. Let’s get the files in src out of the way since our focus will be the Gruntfile.js, package.json, and server.js.

Application Files

We’ll just run through the files real quick and the comment on the first line will tell you what the file is.

// public/src/js/controllers/MainCtrl.js
angular.module('MainCtrl', [])

.controller('mainController', ['$scope', function($scope) {

    $scope.message = 'Look at me go!';

}]);
// public/src/js/services/TestService.js
angular.module('TestService', [])

.factory('Test', ['$http', function($http) {
    
    return {
        get: function() {
            // this returns something 
        }
    };

}]);
// public/src/js/app.js
angular.module('gruntApp', ['MainCtrl', 'TestService']); 
/* public/src/css/style.less */
@primaryColor : #EFEFEF;

body            { background:@primaryColor; }
<!-- public/views/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Grunt for MEAN!</title>

    <link rel="stylesheet" href="src/css/style.less">

    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js"></script>
    <script src="src/js/controllers/MainCtrl.js"></script>
    <script src="src/js/services/TestService.js"></script>
    <script src="src/js/app.js"></script>
</head>
<body ng-app="gruntApp" ng-controller="mainController">
    This is some cool stuff!    

    <p>{{ message }}</p>
</body>
</html>

Okay. Enough of the boring stuff! Let’s go through setting up our actual Node server and Grunt itself.

Server Setup

Express will be used to setup our server. Let’s create a quick

server.js file to serve up that index.html file to our user.


var express = require('express');
var app     = express();

app.use(express.static(__dirname + '/public'));

app.get('/', function(req, res) {
    res.sendfile('./public/views/index.html');
});

app.listen(8080);
console.log('Magic happens on 8080');

Quick and easy. Once we have our packages, we can start up our server and see our files at

http://localhost:8080. Let’s move onto the packages.

Getting the Required Packages package.json

Let’s look at our

package.json file and get the dependencies we will need.


{
  "name": "mean-grunt",
  "main": "server.js",
  "scripts": {
    "start": "grunt"
  },
  "dependencies": {
    "express": "~4.5.1"
  },
  "devDependencies": {
    "grunt": "~0.4.5",
    "grunt-contrib-jshint": "~0.9.2",
    "grunt-contrib-uglify": "~0.4.0",
    "grunt-contrib-less": "~0.11.0",
    "grunt-contrib-cssmin": "~0.10.0",
    "grunt-contrib-watch": "~0.6.1",
    "grunt-nodemon": "~0.3.0",
    "grunt-concurrent": "~0.5.0"
  }
}

These are the packages we will use for this application.

  • Express is what we’ll use for our server
  • jshint and uglify for JavaScript files
  • less and cssmin for CSS files
  • watch will run every time we make changes
  • nodemon is the magic package so that we can start our server with grunt
  • concurrent is used so that we can run watch and nodemon at the same time

Here’s some more information on

popular Grunt packages.

Grunt Nodemon

grunt-nodemon will help us run our Node server. For those of you who have not used nodemon yet, it will monitor any changes in your Node application and restart the server. This is very useful when developing MEAN applications.

Get Our Packages

With our

package.json file created, let’s get those packages. Simply run:

$ npm install

Now that we have our packages in the newly created

node_modules folder and our server file ready to go, let’s move on to the important part: using Grunt to start our application.

Using Grunt to Start Our Server

The package we got earlier (grunt-nodemon) will allow us to start the server, so let’s run through the barebones setup of how that will work.

Simplest Configuration

This is a Gruntfile for just using Grunt to start the server.

// Gruntfile.js
module.exports = function(grunt) {

  grunt.initConfig({

    // configure nodemon
    nodemon: {
      dev: {
        script: 'server.js'
      }
    }

  });

  // load nodemon
  grunt.loadNpmTasks('grunt-nodemon');

  // register the nodemon task when we run grunt
  grunt.registerTask('default', ['nodemon']);  

};

Now if we run

grunt, we can see it start our server!

grunt-nodemon-start-server-simple
grunt-nodemon-browser-test

Let’s move onto a more fully fledged Gruntfile for an actual workflow we could use when developing MEAN stack apps.

Full Configuration

Here is a Gruntfile that uses all the packages we got earlier and a good setup for the workflow we described earlier. We will process files from our

src folder into our dist folder.

// Gruntfile.js
module.exports = function(grunt) {

  grunt.initConfig({

    // JS TASKS ================================================================
    // check all js files for errors
    jshint: {
      all: ['public/src/js/**/*.js'] 
    },

    // take all the js files and minify them into app.min.js
    uglify: {
      build: {
        files: {
          'public/dist/js/app.min.js': ['public/src/js/**/*.js', 'public/src/js/*.js']
        }
      }
    },

    // CSS TASKS ===============================================================
    // process the less file to style.css
    less: {
      build: {
        files: {
          'public/dist/css/style.css': 'public/src/css/style.less'
        }
      }
    },

    // take the processed style.css file and minify
    cssmin: {
      build: {
        files: {
          'public/dist/css/style.min.css': 'public/dist/css/style.css'
        }
      }
    },

    // COOL TASKS ==============================================================
    // watch css and js files and process the above tasks
    watch: {
      css: {
        files: ['public/src/css/**/*.less'],
        tasks: ['less', 'cssmin']
      },
      js: {
        files: ['public/src/js/**/*.js'],
        tasks: ['jshint', 'uglify']
      }
    },

    // watch our node server for changes
    nodemon: {
      dev: {
        script: 'server.js'
      }
    },

    // run watch and nodemon at the same time
    concurrent: {
      options: {
        logConcurrentOutput: true
      },
      tasks: ['nodemon', 'watch']
    }   

  });

  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-nodemon');
  grunt.loadNpmTasks('grunt-concurrent');

  grunt.registerTask('default', ['less', 'cssmin', 'jshint', 'uglify', 'concurrent']);

};

Using Processed Grunt Files

Now, in our view, we won’t need to load up all those JavaScript files we created. We can just load the one final file and use that. Our application will work the same. Just run grunt, let it build all of our files and we can use them in our application. Instead of loading this:

<!-- public/views/index.html -->
<link rel="stylesheet" href="src/css/style.less">

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js"></script>
<script src="src/js/controllers/MainCtrl.js"></script>
<script src="src/js/services/TestService.js"></script>
<script src="src/js/app.js"></script>

We just load the compiled files:

<!-- public/views/index.html -->
<link rel="stylesheet" href="dist/css/style.min.css">

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js"></script>
<script src="dist/js/app.min.js"></script>

You can imagine when your applications start getting larger with more JavaScript and CSS files, this will come in handy. Another benefit of this is that if we add another controller or service, they will get minified and added to the final output.

Testing

Let’s make sure that our entire setup works so that we can hit the ground running when developing our applications. Let’s run:

$ grunt

Now we can see Grunt run our tasks and start up our server. If we start to make changes to our files, it will run the tasks again (thanks to

watch), and it will also restart our server (thanks to nodemon).

grunt-nodemon-start-server-monitor-changes

We can see our server start and if we make changes, magic happens! All good here!

Conclusion

If you’ve ever wondered how those great starter apps like

mean.io and meanjs.org let you start your application with GruntJS, then hopefully this article has been helpful. There are many benefits to Grunt and to have it help you create MEAN apps is a great thing we can utilize. If you want more information on Grunt, read our article on Getting Started with Grunt and as always, have fun creating those MEAN apps!

Also, very important to note, when minifying Angular modules, they must be written a certain way so that the minification does not ruin your modules. For more information: Declaring AngularJS Modules For Minification

Want More MEAN?

This article is part of our

Getting MEAN series. Here are the other articles.

Chris Sevilleja

Co-founder of Scotch.io. Slapping the keyboard until something good happens.