Build Tool

Build tools are programs that automate a series of pre-defined tasks for compiling, linking and packaging the code into a usable or executable form. When people mentioned “build tool” in early year, they probably mean things like Make or Ant (and we still use them). Build tools became really popular in Java community as tools like Maven and Gradle greatly help developers to build their large enterprise-level project, as well as help to manage package dependencies. After that, as the raise of Front-end technologies, front-end projects are no longer things like just writing JavaScript in the HTML file. It became more complex, more systematic, as well as extremely problematic.

What to automate for the front-end

Morden front-end projects usually make use of the following technologies:

  • A mature JavaScript framework (like Angular)
  • Package management with Node
  • A CSS preprocessor (Sass, less)
  • Code quality check (lint)
  • Testing framework

In development, a particular workflow may be:

  1. Write some code
  2. When saved, run style and code quality check
  3. Compiled Sass/less into CSS if changed
  4. Refresh the browser and update for changes

If a developer run the following tasks by hand in CLI, hundreds of hour are probably wasted in running those tests. Therefore, we need some tools to help automate the process.

Also, as the front-end project become larger in size, our users will experience longer loading time as well. Therefore, performance became another important consideration. Usually, before launch our project in production, we will use JavaScript minifier/compressor to minify our code, and combine source files into a single file. Same minification is applied to CSS files as well. This will make our source code smaller in size and faster when load, and also a great place to apply automation.

Luckily, with the help of Node.js, automation in the front-end is easier than ever.

Grunt

Grunt is a task runner built over Node.js that can be used to automate certain tasks in almost any project, in any language. Grunt and Grunt plugins are installed and easily managed via npm. Famous fan of Grunt is Bootstrap, who uses grunt to build their source code.

(Installation details is omitted here, please refer to Getting Start)

You could download various Grunt plugins from NPM. Grunt plugins usually starts with grunt-. Plugins are some well-encapsulated process packages that you could use them for specific tasks such as compile Sass.

Grunt use a special configuration file named Gruntfile for you to defined your own tasks and configure the project. Let’s take a look at one example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
build: {
src: 'src/<%= pkg.name %>.js',
dest: 'build/<%= pkg.name %>.min.js'
}
}
});
// Load the plugin that provides the "uglify" task.
grunt.loadNpmTasks('grunt-contrib-uglify');
// Default task(s).
grunt.registerTask('default', ['uglify']);
};

In the above Gruntfile, project metadata is imported into the Grunt config from the project’s package.json file and the grunt-contrib-uglify plugin’s uglify task is configured to minify a source file. Now if you run

1
grunt

in the command-line, the default task that will be executed is the uglify we just defined.
However, the syntax might took some time for a developer to understand because all tasks are wrapped as configuration objects. That’s actually the feature of Grunt: configuration over implementation.

Gulp

Gulp is a new Node based task runner that grows quickly in the industry. It’s similar to Grunt: it can run all kinds of tasks, has quite a lot of plugins, and also uses a special config file named gulpfile.js. But the difference is Gulp makes use of the Node stream to group task together and process them sequentially in the memory. The direct benefit of using stream is it is fast: to run four tasks on a group of files, Gulp only require one write in file system as it directly modify data in memory.

Famous user of Gulp: Google, Foundation

A typical task defined in Gulp would look like this:

1
2
3
4
5
6
gulp.task('scripts', function() {
return gulp.src('src/**/*.js')
.pipe(jshint('.jshintrc'))
.pipe(uglify())
.pipe(gulp.dest('dist/assets/js'))
});

If you are familiar with stream in Node or pipeline in Linux, this may looks familiar for you. We first use gulp.task to define the task named “scripts”. Then, we first convert all JavaScript files in src/ folder a stream, and do some code checking with jshint, then we uglify the resulted files, and in the end we put them in the dist/assets/js folder. The code already clearly explain what you did in this task, isn’t it? That’s the feature of Gulp: code over configuration.

Grunt VS Gulp

Let’s compare the setup of same tasks in Grunt and Gulp.

Grunt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
sass: {
dist: {
files: {
'sass/styles.scss': 'css/styles.css'
}
}
},
watch: {
sass: {
files: 'sass/*.scss',
tasks: ['sass'],
}
},
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
// Default task
grunt.registerTask('default', ['watch']);
};
Gulp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var gulp = require('gulp');
sass = require('gulp-sass');
// Styles
gulp.task('styles', function() {
gulp.src('sass/styles.scss')
.pipe(sass())
.pipe(gulp.dest('css'));
});
// Watch the sass files
gulp.task('watch', function() {
gulp.watch('sass/*.scss', ['styles']);
});
gulp.task('default', ['styles', 'watch']);
  1. As we can see, Gulp has a shorter configuration file. Its syntax is also easier to understand because the API is quite simple. Also, since both of them are based in Node.js and NPM, Gulp’s syntax to import plugin is more consistent with Node code. On the other hand, you don’t need to care about code detail to achieve the same goal in Grunt.
  2. As Gulp uses stream, it is relatively faster in speed. The difference might be small for smaller projects, but when the project size grows, you may benefit a few seconds from using Gulp. Another benefit for using Gulp is you have full control on your process, so it might be easier to debug where goes wrong.
  3. As of plugins and community, Grunt has 5574 plugins comparing with 2256 on Gulp (as 2016.03.16). And the Grunt community is still quite huge as it has been around longer than Gulp. In addition, Grunt has been tested in big production projects so we might say it is somehow stable.

Should I use Gulp or Grunt?

Both of them are good tool for automation, and it’s all up to you to decide which one to use in your project. Personally I use Gulp for all my recent projects because as a developer, I preferred to have more control on hand, and Gulp’s simple API and stream-syntax just suits my need. But if Grunt already serves you well in your project, why bother to change :)
For those newcomers, I think it’s still worth a try for Gulp. Remember when Node.js just created, those old debates on whether we should try Node.js? Look at how Node is affecting our world now. It may be the same case for Gulp in the next one or two years.