Automate it with Grunt

As a developer you will realize that there are a lot of operations that you are doing every day, several times a day.
You start cloning down your repo, than you have to install all the npm and bower dependencies, than you have maybe to
start your mysql database and sometimes you realize that you also have to rebuild it because you changed your schema.
But there is more to do. You have to start your node server, you have to add, commit, and push all time, you have to lint your file and, if you are doing your job properly, you should also run your tests.

A lot of things to be done, huh?

But i have two pieces of good news for you.
The first one is that you can do all these things using only one command (mostly), the second one is that i’ll show you how to do that in just a moment

Your new friend is Grunt.
Grunt is a super simple, super customizable and super extendable task runner that allows you to automate almost everything (nope, you still have to make coffe by yourself, sorry).

If you want to learn more about it see the official page otherwise follow me and build with me your first Grunt file

This post it's not meant to be a line by line code explanation, the idea is showing what you can do with Grunt and how cool and easy it is.

In order to be able to run grunt task you need to install some stuff, but don't worry, it's super fast and easy, as easy as this two lines:

npm install -g grunt-cli  
npm install grunt --save-dev  

Note that we are using —save-dev to save our dependencies as a dev dependencies in our package.json file

Now that our environment is ready we can start creating our first Gruntfile.js, that should have this structure:

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

    });
};

As you can see is just a very simple node module! Cool, right?

But the cooler part has to come!

Let's say that you want to concatenate your files... Just add the following code to your initConfig function!

concat: {  
  'whatever/YourConcatenatedFile.js': [
    'public/lib/underscore.js',
    'public/lib/jquery.js'
    // and so on..
  ]
}

And what if you want some minification?

cssmin: {  
  target: {
    files: [{
      expand: true,
      cwd: 'public',
      src: ['*.css', '!*.min.css'],
      dest: 'public/dist',
      ext: '.min.css'
    }]
  }
}

Not impressed yet? Wouldn't be cool to be able to use git commands from grunt and automate some boring operations that usually you have to do all the time (especially when deploying)?

gitadd: {  
  task: {
    options: {
      verbose: true,
      all: true
    }
  }
},
gitcommit: {  
  task: {
    options: {
      message: grunt.option('message')
    }
  }
},
gitpush: {  
  task: {
    options: {
      verbose: true,
      remote: 'yourRemote'
    }
  }
}

Now, before being able to run your super cool grunt file you have to install the npm module that we added one second ago. The good news is that is super easy!

Run:

npm install grunt-contrib-concat --save-dev  
npm install grunt-contrib-cssmin --save-dev  
npm install grunt-git --save-dev  

and then add this to your Gruntfile:

grunt.loadNpmTasks('grunt-contrib-concat');  
grunt.loadNpmTasks('grunt-contrib-cssmin');  
grunt.loadNpmTasks('grunt-git');  

Almost done! Now, everything is ready to go, you just have to register your task. This last step is absolutely trivial, but very powerful because allows you to combine all the module that you installed in several different ways, with different behaviours and purposes.

Let's see an example:

grunt.registerTask('git', [  
  'gitadd',
  'gitcommit',
  'gitpush'
]);

grunt.registerTask('uglify, [  
  'cssmin',
  'concat'
]);

grunt.registerTask('build', function (n) {  
  grunt.task.run([ 'uglify' ]);
  if (grunt.option( 'prod' )) {
    grunt.task.run([ 'git' ]);
  }
});

You see? Isn't awesome?
What we did is creating some tasks with a name, so when we type grunt git we execute all the modules called inside that task. But that's not all because you can also put tasks inside other tasks, like what we did in the last registerTask function.
In this last example we introduced another cool feature: grunt.option()

What grunt is doing is looking for the -prod option in the grunt command. This means that if you launch your build task using grunt build, only the uglify task will run, but if you run grunt build grunt build -prod --message 'Your commit message'

And that's all!
Keep playing with Grunt, look at the HUGE amount of modules than you can find out here and if you want to go more into details check the official documentation.

DISCLAIMER: Automating can cause dependency