Using Grunt JavaScript Minification
We will continue from our last blog post on Grunt: using less and css minification to JavaScript minification using a plugin called Uglify.
JSHint
To begin we will use a linting tool called jshint, to help us in taming our JavaScript with some static code analysis to flags suspicious usage.
We can use the command line npm install for it or we can use the visual studio tool to install
npm install grunt-contrib-jshint --save-dev
Now that we have jshint lets add our grunt task for jshint in our Gruntfile.js
module.exports = function (grunt) {
grunt.initConfig({
cssmin: {
target: {
files: {
'deploy/style.min.css': 'public/stylesheets/mystyle.css'
}
}
},
less: {
compile: {
files: {
'deploy/compiled.css': 'public/stylesheets/layout.less'
}
}
},
jshint: {
jsFiles: ['public/javascripts/**/*.js']
}
});
// Next one would load plugins
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-jshint');
// Here is where we would define our task
grunt.registerTask('default', ['cssmin:target', 'less:compile', 'jshint:jsFiles']);
};
You may realize that something different in our jshint section, there are some ** inside the file name. The pattern of /**/ basically mean traverse through all the children levels of the directory hierarchy, and the *.js means all the file with extension of js. By doing so, our script will always scan through any subdirectory for any future js files we may add.
Lets add a file inside of public/javascripts/ directory and call it myapp.js, our file will look something like this.
"use-strict";
var myapp = {};
myapp.name = 'This is a sample app';
myapp.isNull = function (a) {
return a == null;
};
When we run our task using TaskRunner in Visual Studio or command line for jshint, we will get back a fail task and some suggestion on our JavaScript.
$ grunt jshint:jsFiles
//output
Running jshint:jsFiles (jshint) task
public\javascripts\myapp.js
7 | return a == null;
^ Use '===' to compare with 'null'.
1 error in 1 file
Aborted due to warnings.
Process terminated with code 3.
In order to fix the script jshint already suggest us to use the “===” for compare. Let’s now add another file called myapp2.js and also fix our myapp.js file.
"use-strict" ;
var myapp2 = {};
myapp2.sayHello = function () {
return "Hello";
};
When we rerun our task we should have no more errors.
$ grunt jshint:jsFiles
>> 2 files lint free.
Done, without errors.
Concat
We will now like to concat the file together and there is yet another plugin for grunt to concat files for us grunt-contrib-concat, as always we can use the npm tool in visual studio or the command line to install it.
$ npm install grunt-contrib-concat --save-dev
And in our Gruntfile.js we will add our concat task
module.exports = function (grunt) {
grunt.initConfig({
cssmin: {
target: {
files: {
'deploy/style.min.css': 'public/stylesheets/mystyle.css'
}
}
},
less: {
compile: {
files: {
'deploy/compiled.css': 'public/stylesheets/layout.less'
}
}
},
jshint: {
jsFiles: ['public/javascripts/**/*.js']
},
concat: {
js: {
files: {'deploy/bundle.js': 'public/javascripts/**/*.js' }
}
}
});
// Next one would load plugins
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-concat');
// Here is where we would define our task
grunt.registerTask('default', ['cssmin:target', 'less:compile', 'jshint:jsFiles', 'concat:js']);
};
From the script we will see that it will add the bundle.js file into the deploy directory.
and if we open the file, we will see that both scripts are combined into one file.
Uglify
Lastly, we would like to uglify the file, as in minification of the Javascript files. As always we will install our plugin and modify our Gruntfile.
$ npm install grunt-contrib-uglify --save-dev
Our new Gruntfile.js would look like
module.exports = function (grunt) {
grunt.initConfig({
cssmin: {
target: {
files: {
'deploy/style.min.css': 'public/stylesheets/mystyle.css'
}
}
},
less: {
compile: {
files: {
'deploy/compiled.css': 'public/stylesheets/layout.less'
}
}
},
jshint: {
jsFiles: ['public/javascripts/**/*.js']
},
concat: {
js: {
files: {'deploy/bundle.js': 'public/javascripts/**/*.js' }
}
},
uglify: {
bundle: {
files: {'deploy/bundle.min.js': 'deploy/bundle.js'}
}
}
});
// Next one would load plugins
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
// Here is where we would define our task
grunt.registerTask('default', ['cssmin:target', 'less:compile', 'jshint:jsFiles', 'concat:js', 'uglify:bundle']);
};
And now our bundle.min.js file is a minified javascript file (Uglified).
Summary
In this post we covered quite an area of grunt where we used multiple plugins to accomplish javascript related task (minification, concat, etc), in the next post we use grunt to automate our testing and clean up task.