GRUNT - Task Manager

- install Node.js
(easiest way is to just get the installer from nodejs.org)

- in the terminal type
>> sudo npm install -g grunt-cli 

In your project create a Gruntfile.js and package.json.
The package.json file describes the project and lists it’s dependencies the Grunt file has to successfully run. 

In the following example the dependencies are Grunt itself,
grunt-contrib-watch : A watching agent, which checks file changes and runs other tasks accordingly
grunt-contrib-uglify : A JS minify task
grunt-sass : Because we like Sass

package.json example:

{
  "name": "your-application-name",
  "version": "0.0.1",
  "devDependencies": {
    "grunt": "~0.4.1",
    "grunt-contrib-watch": "~0.5.3",
    "grunt-contrib-uglify": "~0.4.0",
    "grunt-sass": "~0.8.0",
  }
}

- To automatically install these dependencies go to the terminal and type
>> sudo npm install 

The Gruntfile.js is the file where you actually define the tasks you want available for either development or distribution

module.exports = function(grunt) {
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),

		uglify: {
			options: {
				sourceMap : true,
				banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
				'<%= grunt.template.today("yyyy-mm-dd") %> */'
			},
			my_target: {
				files: {
					'assets/dist/js/output.min.js': ['assets/source/js/input1.js', 'assets/source/js/input2.js']
				}
			}
		},

		sass: {
			options: {
				includePaths: ['bower_components/foundation/scss']
			},
			dist: {
				options: {
					outputStyle: 'compressed'
				},
				files: {
					'assets/dist/css/app.css': 'assets/source/scss/app.scss'
				}
			}
		},

		watch: {
			grunt: { 
				files: ['Gruntfile.js'] 
			},
			sass: {
				files: 'source/scss/**/*.scss',
				tasks: ['sass']
			},
		}
	});

	grunt.loadNpmTasks('grunt-sass');
	grunt.loadNpmTasks('grunt-contrib-watch');
	grunt.loadNpmTasks('grunt-contrib-uglify');

	grunt.registerTask('build', ['sass','uglify']);
	grunt.registerTask('default', ['build','watch']);
}

Let’s go through it step by step.

First we start with the initialisation and read the package file to see if we have the dependencies and get some variables from the package including name and version

module.exports = function(grunt) {
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),

Then we start defining our available tasks.
In this case we have three simple tasks.
Every task has it’s own specific configuration options and are documented on their own website.

		uglify: {
			options: {
				sourceMap : true,
				banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
				'<%= grunt.template.today("yyyy-mm-dd") %> */'
			},
			my_target: {
				files: {
					'assets/dist/js/output.min.js': ['assets/source/js/input1.js', 'assets/source/js/input2.js']
				}
			}
		},

The uglify task is fairly straightforward but has a lot of options available (https://github.com/gruntjs/grunt-contrib-uglify)
In the options we define that we want a sourceMap and add a banner with the application name and version number (from the package.json).
The target defines which files are added to which minified file and can have multiple inputs and outputs. 

		sass: {
			dist: {
				options: {
					outputStyle: 'compressed'
				},
				files: {
					'assets/dist/css/app.css': 'assets/source/scss/app.scss'
				}
			}
		},

The sass task will compile the SCSS files defined to vanilla CSS.

		watch: {
			grunt: { 
				files: ['Gruntfile.js'] 
			},
			sass: {
				files: 'assets/source/scss/*.scss',
				tasks: ['sass']
			},
		}
	});

In your watch task you can define all the tasks you want to have run on file change.
You define the tasks and tell which files/folder to watch. Any change on these files will run the associated task.
(All the file paths defined are changeable and depend on how you prefer to set up your front-end project).

In the end we load all the necessary packages we installed earlier in the process…

	grunt.loadNpmTasks('grunt-sass');
	grunt.loadNpmTasks('grunt-contrib-watch');
	grunt.loadNpmTasks('grunt-contrib-uglify');

…and define our tasks.
This is actually a very important part of the process as here we define how we interact with all the different actions we implemented earlier.

	grunt.registerTask('build', ['sass','uglify']);
	grunt.registerTask('default', ['build','watch']);
}

I register two tasks commands here. The build command and a default command.
The default command first runs the build command and then starts running our watch task.
You can define as many different tasks as you want.

Simply going to the command line and typing

>> grunt 

will start first make a distribution build of all the JS defined in the uglify task and create a compressed CSS version for the SCSS.
After this it will start our watch task.

typing 

>> grunt build 

Will make the distribution versions of JS and CSS.

To find more available tasks you can check the plugin directory at http://gruntjs.com/plugins
some really useful ones are:

https://www.npmjs.org/package/grunt-bower - External Library management
https://www.npmjs.org/package/grunt-contrib-jshint - JSHint Validation
https://www.npmjs.org/package/grunt-contrib-cssmin - Vanilla CSS minifier
https://www.npmjs.org/package/grunt-contrib-livereload - Live reload your changes in the browser when editing files
https://www.npmjs.org/package/grunt-bake - For HTML includes in bigger static projects