Getting Started with Javascript Gulp Task Runner

Javascripts Gulp Task Runner helps you be productive by automating build tasks like SCSS, image processing and minificaion.

By Tim Trott(Java|Type)Script / jQuery • June 19, 2015
1,724 words, estimated reading time 6 minutes.
Getting Started with Javascript Gulp Task Runner

Gulp is a JavaScript Task Runner that automates most, if not all, of the tedious tasks that web developers traditionally do. Gulp task runner lets you automate tasks such as bundling and minifying libraries and stylesheets, Less/Sass to CSS compilation, compressing and optimising images, and copying modified files to an output directory. It can even reload the browser window when files are changed.

The Gulp Task Runner Workflow

Gulp works using tasks. Each task takes a set of files loaded into the Gulp stream to be processed. Each file is processed and sent to the destination file—a simple input, process, and output workflow.

Tasks can also be chained together so a file can be processed; another action can be performed before it is written to the output.

Installing Gulp Task Runner via NPM and Grunt

Grunt can easily be installed using the Node.js Package Manager. If you do not have it installed already, head over to the npm website where you can download and install it.

Gulp is installed globally and is also included in your project. Global installation is only required once.

npm install gulp -g

Next, we need to change the directory to your project folder and install Gulp on the project. This will install the modules and packages we will use and create the default project settings.

When creating a new project, you must first run the node init command to create files and folder structures.

cd webproject1
npm init

Then, you can install gulp into the project.

npm install gulp --save-dev

Installing Gulp Task Runner Plugins

Next, we need to install a few plugins we will use in our tasks. I will install some of the most frequently used plugins here. You can find a list of all the available plugins for Gulp here.

These can all be installed on the command line using npm.

npm install gulp-ruby-sass gulp-autoprefixer gulp-casino jshint gulp-jshint gulp-concat gulp-uglify gulp-image in gulp-notify gulp-rename gulp-live-reload gulp-cache gulp-htmlmin del --save-dev

Creating a gulpfile to Manage Tasks

Next, we must create a gulpfile.js and load the plugins. The gulpfile is a plain javascript file.

javascript
var gulp = require('gulp'),
    sass = require('gulp-ruby-sass'),
    autoprefixer = require('gulp-autoprefixer'),
    cssnano = require('gulp-cssnano'),
    jshint = require('gulp-jshint'),
    uglify = require('gulp-uglify'),
    imagemin = require('gulp-imagemin'),
    rename = require('gulp-rename'),
    concat = require('gulp-concat'),
    notify = require('gulp-notify'),
    cache = require('gulp-cache'),
    livereload = require('gulp-livereload'),
    htmlmin = require('gulp-htmlmin'),
    del = require('del');

This is a standard header for the file; as you can see, it simply loads in the plugin files. Feel free to change this accordingly. If you don't intend to use a plugin, comment it out or delete the line.

Windows users will also need to install Ruby as well as the sass gem.

Creating Tasks in Gulp Task Runner

Next, we need to create a few tasks since that is the whole point of the exercise. A Task takes in a source file, runs an action on the contents of the file, and then outputs the result either to another plugin or to a file.

We must first create a default task in which gulp runs automatically. This task will launch all the other tasks we define.

In this example, we will transform a source SCSS stylesheet into a CSS file for distribution.

This code goes into the gulpfile.js after the plugins.

javascript
gulp.task('default', function() {
    gulp.start('styles');
});

I will create a very basic SCSS file in src/styles/main.scss with the following contents.

scss
$font-stack:    Helvetica, sans-serif;
$primary-color: #333;

body {
  font: 100% $font-stack;
  color: $primary-color;
}

Next, I will create the task to transform this into CSS so we can upload it to our web server.

This goes in after the default task.

javascript
gulp.task('styles', function() {
  return sass('src/styles/main.scss', { style: 'expanded' })
    .pipe(gulp.dest('dist/assets/css'));
});

All this is going to do is transform the SCSS into CSS.

We can run gulp by simply running the command gulp in the command line in the project folder.

Once it has been completed, the folder dist/assets/css should contain a file called main.css. This will have pure CSS.

css
body {
  font: 100% Helvetica, sans-serif;
  color: #333;
}

Now, we will use some of the power of gulp and chain some plugins together to transform this file further. We will automatically add vendor prefixes to CSS properties, minify the output, rename the output file and show a message in the console when the command is complete. This is useful when many tasks are to be run so you know what is being run.

We can modify our styles task to include the following:

javascript
gulp.task('styles', function() {
  return sass('src/styles/main.scss', { style: 'expanded' })
    .pipe(autoprefixer('last 2 version'))
    .pipe(gulp.dest('dist/assets/css'))
    .pipe(rename({suffix: '.min'}))
    .pipe(cssnano())
    .pipe(gulp.dest('dist/assets/css'))
    .pipe(notify({ message: 'Styles task complete' }));
});

When we run gulp, we will see a main.min.css generated with the minified CSS contents.

css
body{font:100% Helvetica,sans-serif;color:#333}

You may have noticed that we have a main.css and a main.min.css in the dist folder. Could we clear out old files each time gulp is run? Let's create a task for that.

javascript
gulp.task('clean', function() {
    return del(['dist/assets/css', 'dist/assets/js', 'dist/assets/img']);
});

Next, we must modify the default task to include a clean task. We will add clean as a dependency since we want it to always run before anything else. This is done by adding an array as the second argument.

javascript
gulp.task('default', ['clean'], function() {
    gulp.start('styles');
});

Now, we can add a task to do the same thing for some Javascript. This will take all the javascript files in all subfolders, combine them into one file, minify, run jshint to validate the javascript code and then write out main.js (unminifed) and main.min.js (minified) to the dest folder.

javascript
gulp.task('scripts', function() {
  return gulp.src('src/scripts/**/*.js')
    .pipe(jshint('.jshintrc'))
    .pipe(jshint.reporter('default'))
    .pipe(concat('main.js'))
    .pipe(gulp.dest('dist/assets/js'))
    .pipe(rename({suffix: '.min'}))
    .pipe(uglify())
    .pipe(gulp.dest('dist/assets/js'))
    .pipe(notify({ message: 'Scripts task complete' }));
});

Again, this task has been added to the default task runner.

javascript
gulp.task('default', ['clean'], function() {
    gulp.start('styles', 'scripts');
});

The next task to add will be to optimise and copy images from our source folder to the assets folder.

javascript
gulp.task('images', function() {
  return gulp.src('src/images/**/*')
    .pipe(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true }))
    .pipe(gulp.dest('dist/assets/img'))
    .pipe(notify({ message: 'Images task complete' }));
});

This is OK if there are only a small number of images, but if your site has many images, it is better to cache the results so that only modified images get reprocessed. This saves a lot of time during the build process. Again, this task will take all pictures of all subfolders and output them to the dist/assets/img folder.

javascript
gulp.task('images', function() {
  return gulp.src('src/images/**/*')
    .pipe(cache(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true })))
    .pipe(gulp.dest('dist/assets/img'))
    .pipe(notify({ message: 'Images task complete' }));
});

No website would be complete without HTML, so we will take our HTML pages, minify them and copy them to the dist folder.

javascript
gulp.task('minify', function() {
  return gulp.src('src/*.html')
    .pipe(htmlmin({collapseWhitespace: true}))
    .pipe(gulp.dest('dist'));
});

Gulp Task Runner and Live Reload Plugin

One of the most powerful features of Gulp Task Runner is the ability to add file watchers. These will trigger when files are changed and automatically rebuild the output files. They will refresh the browser window, meaning you change the code and save the file. Automatically, the browser refreshes with the new code.

To configure this, we need to add a new task for a watch and install the browser plugin from LiveReload.

Download for Firefox Download for Chrome

javascript
gulp.task('watch', function() {
    gulp.watch('src/styles/**/*.scss', ['styles']);
    gulp.watch('src/scripts/**/*.js', ['scripts']);
    gulp.watch('src/images/**/*', ['images']);
    gulp.watch('src/*.html', ['minify']);
    
    livereload.listen();
    gulp.watch(['dist/**']).on('change', livereload.changed);
});

This will watch for changes to styles, scripts, images and HTML and fire off the relevant task. If a file changes in the dist folder, it will fire off the browser reload.

To run the gulp watcher, enter this command in the project folder.

gulp watch

Full Practical Example of Gulp Javascript Task Runner

Below is the complete gulpfile.js, which I use for most web templates. It should be more than enough to get you started.

javascript
var gulp = require('gulp'),
    sass = require('gulp-ruby-sass'),
    autoprefixer = require('gulp-autoprefixer'),
    cssnano = require('gulp-cssnano'),
    jshint = require('gulp-jshint'),
    uglify = require('gulp-uglify'),
    imagemin = require('gulp-imagemin'),
    rename = require('gulp-rename'),
    concat = require('gulp-concat'),
    notify = require('gulp-notify'),
    cache = require('gulp-cache'),
    htmlmin = require('gulp-htmlmin'),
    livereload = require('gulp-livereload'),
    del = require('del');

gulp.task('default', ['clean'], function() {
    gulp.start('styles', 'scripts', 'images', 'minify');
});

gulp.task('watch', function() {
    gulp.watch('src/styles/**/*.scss', ['styles']);
    gulp.watch('src/scripts/**/*.js', ['scripts']);
    gulp.watch('src/images/**/*', ['images']);
    gulp.watch('src/*.html', ['minify']);
    
    livereload.listen();
    gulp.watch(['dist/**']).on('change', livereload.changed);
});

gulp.task('clean', function() {
    return del(['dist/assets/css', 'dist/assets/js', 'dist/assets/img']);
});

gulp.task('styles', function() {
  return sass('src/styles/main.scss', { style: 'expanded' })
    .pipe(autoprefixer('last 2 version'))
    .pipe(gulp.dest('dist/assets/css'))
    .pipe(rename({suffix: '.min'}))
    .pipe(cssnano())
    .pipe(gulp.dest('dist/assets/css'))
    .pipe(notify({ message: 'Styles task complete' }));
});

gulp.task('scripts', function() {
  return gulp.src('src/scripts/**/*.js')
    .pipe(jshint('.jshintrc'))
    .pipe(jshint.reporter('default'))
    .pipe(concat('main.js'))
    .pipe(gulp.dest('dist/assets/js'))
    .pipe(rename({suffix: '.min'}))
    .pipe(uglify())
    .pipe(gulp.dest('dist/assets/js'))
    .pipe(notify({ message: 'Scripts task complete' }));
});

gulp.task('images', function() {
  return gulp.src('src/images/**/*')
    .pipe(cache(imagemin({ optimizationLevel: 5, progressive: true, interlaced: true })))
    .pipe(gulp.dest('dist/assets/img'))
    .pipe(notify({ message: 'Images task complete' }));
});

gulp.task('minify', function() {
  return gulp.src('src/*.html')
    .pipe(htmlmin({collapseWhitespace: true}))
    .pipe(gulp.dest('dist'))
    .pipe(notify({ message: 'Minify task complete' }));
});

Do you use Gulp? Do you have any helpful tasks we can add to the collection? Do you use another task runner? Let us know in the comments below!

Related ArticlesThese articles may also be of interest to you

CommentsShare your thoughts in the comments below

My website and its content are free to use without the clutter of adverts, popups, marketing messages or anything else like that. If you enjoyed reading this article, or it helped you in some way, all I ask in return is you leave a comment below or share this page with your friends. Thank you.

There are no comments yet. Why not get the discussion started?

New comments for this post are currently closed.