Gruntfile by Example

Introduction

 

What’s Grunt used for? Automating front-end and JavaScript workflow tasks. Refreshing the browser when you change a script.
Automate creation of you project environment configurations and many more.

Grunt is just a task runner. Every unit of functionality that you would want is usually achieved with a separate npm package (a grunt “plugin”).

npm search grunt  -> to view literally every grunt plugin available.

Get the command line interface:

npm install -g grunt-cli

 

For this article we will tackle only on how grunt file is very useful in automating the creation of our configuration files based on different environments.

How to start?

 

* First we need to know our npm version (node package manager) or if it is installed in our linux server by typing

 

npm -v

 

* Next go to our project root directory so we can create a grunt file and package.json file.

 

2 ways to create package.json needed for grunt:

1. Most grunt-init templates will automatically create a project-specific package.json file by issuing this command on terminal:

npm install -g grunt-init

 

2. The npm init command will create a basic package.json file by typing this command on terminal:

npm init -f -y

 

Example package.json file:

1 {
2  "name": "Web.Kepo",
3  "version": "0.0.0",
4  "description": "An Indonesian Social News Site",
5  "main": "index.js",
6  "scripts": {
7    "test": "echo \"Error: no test specified\" && exit 1"
8  },
9  "repository": {
10    "type": "git",
11    "url": "https://github.excite.media/Excite/Web.kepo"
12  },
13  "author": "",
14  "license": "BSD-2-Clause",
15  "devDependencies": {
16    "grunt": "~1.0.1",
17    "grunt-contrib-copy": "~0.8.0",
18    "grunt-text-replace": "~0.4.0",
19    "grunt-exec": "~0.4",
20    "grunt-contrib-jshint": "~1.0.0"
21  }
22 }

 

Note:

On line 1 to 8, it defines the your project details, name, version etc.
On line 9 to 12, its the repository path of your project but this can be optional.
On line 15 onward, that is the important part which we defined our plugins dependencies and its compatible version.

 

* Now we need to install the actual grunt task runner as a development dependency to our project :

 

npm install grunt  --save-dev

Note: 
 --save-dev adds the package as a dependency to package.json

 

we also need to install other plugins like jshint, contrib-copy, text-replace and exec to be use on our example later. we  just run the following commands:

npm install grunt-contrib-jshint --save-dev
npm install grunt-contrib-copy --save-dev
npm install grunt-text-replace --save-dev
npm install grunt-exec --save-dev

 

* After installing the plugins we will now create an empty Gruntfile.js file in your project root. This will contain all of your task configuration.

 

On your linux terminal or command line type the following: touch Gruntfile.js

For example this is my project root directory, this is where I will create the empty grunt file:

/home/someone/MyProjectRoot/$  touch Gruntfile.js

 

Example Gruntfile.js

1 'use strict';
2
3 module.exports = function(grunt) {
4    // load config
5    grunt.initConfig({
6        pkg: grunt.file.readJSON('package.json'),
7
8        // rename and copy files
9        copy: {
10            dev: {
11                files: [
12                    {
13                        expand: true,
14                        dot: true,
15                        src: 'app/App.php',
16                        dest: 'app/',
17                        rename: function(dest, src) {
18                            return dest + 'App.php_dev';
19                        }
20                    }
21                ]
22            },
23            test: {
24                files: [
25                    {
26                        expand: true,
27                        dot: true,
28                        src: 'app/App.php',
29                        dest: 'app/',
30                        rename: function(dest, src) {
31                            return dest + 'App.php_test';
32                        }
33                    }
34                ]
35            },
36            stage: {
37                files: [
38                    {
39                        expand: true,
40                        dot: true,
41                        src: 'app/App.php',
42                        dest: 'app/',
43                        rename: function(dest, src) {
44                            return dest + 'App.php_stage';
45                        }
46                    }
47                ]
48            },
49            live: {
50                files: [
51                    {
52                        expand: true,
53                        dot: true,
54                        src: 'app/App.php',
55                        dest: 'app/',
56                        rename: function(dest, src) {
57                            return dest + 'App.php_live';
58                        }
59                    }
60                ]
61            }
62        },
63
64        // replace {someone} to exec user account
65        replace: {
66            dev_app: {
67                src: ['app/App.php'],
68                overwrite: true,
69                replacements: [{
70                    from: '{someone}',
71                    to: process.env.USER
72                }]
73            }
74        },
75
76        // chmod tmp and logs
77        exec: {
78            chmod_tmp: {
79                command: 'chmod -R 777 app/tmp'
80            },
81            chmod_logs: {
82                command: 'chmod -R 777 app/logs'
83            }
84        },
85
86    });
87
88    // load plugins
89    grunt.loadNpmTasks('grunt-contrib-copy');
90    grunt.loadNpmTasks('grunt-text-replace');
91    grunt.loadNpmTasks('grunt-exec');
92
93    // define task 'default'
94    grunt.registerTask('default', 'Log some stuff.', function() {
95        grunt.log.write('Logging some stuff...').ok();
96    });
97
98    // task for setup develop environment
99    grunt.registerTask('dev_build', [
100        'copy:dev',
101        'replace:dev_app',
102        'exec:chmod_tmp',
103        'exec:chmod_logs'
104    ]);
105
106    // task for setup test environment
107    grunt.registerTask('test_build', [
108        'copy:test',
109        'exec:chmod_tmp',
110        'exec:chmod_logs'
111    ]);
112
113    // task for setup stage environment
114    grunt.registerTask('stage_build', [
115        'copy:stage',
116        'exec:chmod_tmp',
117        'exec:chmod_logs'
118    ]);
119
120    // task for setup live environment
121    grunt.registerTask('live_build', [
122        'copy:live',
123        'exec:chmod_tmp',
124        'exec:chmod_logs'
125    ]);
126 };

Let’s break down the codes!

 

On line 3, Grunt is just a javascript file running on a node.
On line 5, All upfront configs goes in a massive nested object.
On line 6, We read and get the configs on package.json file
On line 9, Grunt tasks are associated with specific properties. These names generally match their npm package name and that is ‘copy’.
On line 10 to 61, You can see that it is defined here the path of the file that we need to copy and the target path based on what environment we are whether on dev, test, stage or live environment.
On line 65, however we used another plugin ‘replace’, wherein we replace here the text based of the current environment user in App.php file
On line 77, we also used ‘exec’ plugin, basically what this command do is to add permission to /tmp and /logs directory
On line 89 to 91, We’ve set up each task’s configuration. Now actually load the tasks. This will do a lookup similar to node’s require() function.
On line 99, 107, 114 and 121, We register our own custom task alias.

 

Now I hope you learned the parts of the grunt file. We will proceed next on how to run it.

 

How to Run Grunt

 

* Now after everything we discussed, its now time to learn how to run the grunt on shell. Just issue one of the commands below depending on your current environment where you are in.

grunt dev_build
grunt test_build
grunt stage_build
grunt live_build

 

Sample results after run:

samplegrunt

 

Note:

Based from what I experienced regarding giving permission to file you need to clear first the /tmp and /logs that we used on our sample, retain only the default files there so that it will not generate an error when you run grunt.

 

And that’s it!, we were able to automate creation of App.php file, replaced necessary text there and add permission on a directory in just running 1 command. It saves you time in doing all this 3 tasks.

 

For more advanced concepts, read the Grunt docs! They’re pretty good.
Some are excerpts from Brian Chu Post on Jul 11th, 2013 in javascript, tutorials