Automate JavaScript workflow with Gulp

Automate JavaScript workflow with Gulp

  • 2016-08-09
  • 932

When developing a web application there are repetitive tasks we do every-time we change or upgrade our code.  These tasks are usually not difficult but do take away our crucial development time. This is where Gulp comes into picture.

Gulp is a task runner/builder and a node.js build tool which automates these repetitive tasks and hence saves time. This also allows us to completely focus on what we are supposed to do, i.e.  Coding and leave the rest to Gulp. Minifiction, concatenation, browser refresh, server restart etc are some of the tasks that Gulp can take care for us.

DOWNLOAD

Note. Download the code, navigate to working directory via terminal/cmd and run npm install to install all the gulp plugins. Then you can run gulp to see it in action.

Other Options?

There are quite a few other task runners out there, Grunt being the most popular. Grunt was the tool most of the developers used until Gulp arrived and then Gulp vs Grunt became a topic of discussion. Although both of them have there pros and cons. Below are the few reasons to choose Gulp over Grunt.

Gulp is code over configuration, meaning that gulp tasks are written in code, unlike grunt which uses a configuration hash to create tasks. This approach makes writing tasks easier and manageable and also adds better readability.

Also Gulp uses **NodeJS streams ** for writing files, this means it does not write temporary files on disks, there by speeding up the process.

Gulp allows us to pipe the output of one plugin as an input to another, hence allowing us to use multiple plugins in single tasks. In grunt we would have had to configure each plugin separately each of which having source and destination paths. For Example – In gulp we can minify and concat in one tasks and write the final output, on the other hand in Grunt we will have to write the out put of one plugin first and then take it as an input for another plugin and write the final output.

Installation

To use Gulp we need node installed in our machine. If you don’t have Node.js download it from here.

Install Gulp globally

$ npm install gulp -g

Save it as a developer dependency

$ npm install gulp --save-dev

Note. you should have a package.json file existing to save it as a dependency.

Next we need to create a file named gulpfile.js in our working directory. gulpfile.js is the configuration file Gulp uses. This is where we will load gulp plugins and define tasks.

Installing Gulp plugins

We will be installing the below gulp plugins for this tutorial.

  1. gulp-jshint (Looks up for errors in your js code and reports the same)
  2. gulp-sass (Compiles your sass into css)
  3. gulp-uglify (Minifies js files)
  4. browser-sync (For synchronized browser testing)

Run the below commands to install these plugins.

$ npm install gulp-jshint --save-dev  

$ npm install gulp-sass --save-dev  

$ npm install gulp-uglify --save-dev  

$ npm install browser-sync --save-dev

Writing Gulp Tasks

Using Gulp tasks (gulp.task) we can use Gulp plugins to perform the desired operation on the source files and then pipe them into the destination folder.

gulp.task takes in three arguments name (string), dependencies (array)(optional) and a function that performs our tasks.

Before we proceed to writing our first Gulp tasks have a look at the directory structure that we are using for this demo.

Directory Structure
 bower_components/  
    node_modules/  
    src/  
        app/  
            app.js  
        assets/  
            scss/  
                style.scss  
        index.html  
    public/  
    gulpfile.js  
    package.json

Now let’s require the necessary gulp plugins into our gulpfile.js file. Open up gulpfile.js and add the below.

gulpfile.js
var sass = require('gulp-sass');
var gulp = require('gulp');
var jshint = require('gulp-jshint');
var uglify = require('gulp-uglify');
var browserSync = require('browser-sync').create();

Now let’s write our first task.

gulpfile.js
gulp.task('lint', function() {
  return gulp.src('./src/**/*.js')
    .pipe(jshint())
    .pipe(jshint.reporter('default'));
});

In the above task, we are using the gulp-jshint plugin to validate our javascript code. We have named our task as lint.
The above task takes in the source files from the specified directory pipes them through jshint and then reports us the errors.

Save the file. To run this task open up your terminal, navigate to your working directory(where gulpfile is located) and run gulp lint. This command will run our lint task.

Automate JavaScript workflow with Gulp

Now let’s add a few more tasks, one to minify our javascript files using gulp-uglify and other to compile our scss file into css using gulp-sass. While doing so we will pipe our resultant files into the public folder. Public folder will be used to serve our files to the web browser.

Append the below code into your gulpfile.js

gulpfile.js
gulp.task('scss', function() {
    gulp.src('./src/assets/scss/*.scss')
        .pipe(sass().on('error', sass.logError))
        .pipe(gulp.dest('./public/assets/stylesheets/'));
});

gulp.task('scripts', function() {
    return gulp.src('./src/**/*.js')
        .pipe(uglify())
        .pipe(gulp.dest('./public'));
});

Now let’s copy the html files into our serving directory.

gulpfile.js
gulp.task('copy', function() {
    gulp.src('./src/**/*.html')
        .pipe(gulp.dest('./public'))
});

Specifying dependent tasks

Normally gulp runs tasks asynchronously. However we can specify other tasks as a dependency for our task to run. We can do this by passing an array of tasks as second argument to our current task. Lets see and example below.

gulpfile.js
gulp.task('build', ['lint', 'scss', 'scripts', 'copy'], function(){
    console.log('Build complete');
})

Here above we have defined a task as build and we have added [‘lint’, ‘scss’, ‘scripts’, ‘copy’] as dependent tasks to for our build task. Save your gulpfile.js and run gulp build, you will notice that all the dependent tasks are completed first and then our build task logs the console message.

Browser Sync

Browser Sync is an awesome tool that cuts out some of our manual browser testing work. It enables us to create a server and run our application in multiple browser simultaneously. We can also hook it with gulp.watch to reload all browsers when ever there is a new build. Believe me, this save a heck of our lot of time.

We have already installed the browser sync plugin and required it into our Gulp file. Now lets configure a static server using browser-sync as a new gulp task.

gulpfile.js
gulp.task('browser-sync', ['build'], function() {
    browserSync.init({
        server: {
            baseDir: "./public",
            // The key is the url to match
            // The value is which folder to serve (relative to your current working directory)
            routes: {
                "/bower_components": "bower_components"
            }
        },
        browser:"firefox"
    });
});

baseDir is the directory from which the server will server our files. We have added bower_components as routes, this because bower_components is out side our baseDir and hence it won’t be accessible from the browser when the server runs. Adding it as routes will make the folder available at the URL we define as key in our route. The value would be the folder name (relative to our current working directory) to serve on that URL.

Note, we have added build as a dependent task.

Default task


In Gulp we can also define a default task. For that we have to create a task with name as default. The default task runs when we don’t specify a task name while running Gulp.

Gulp Watch


gulp.watch allows us to watch files for changes and run other gulp tasks whenever those files are changed. See code below.

gulpfile.js
gulp.task('default', ['browser-sync'], function(){

    gulp.watch('./src/**/*.*', ["build"]);

    gulp.watch('./public/**/*.*').on('change', browserSync.reload);

})

Above we are watching for changes in src directory and running build task whenever any of the files changes. We are also watching for changes in the public directory and listening to the change event and triggering browserSync.reload to reload our browsers.

Save gulpfile.js and run gulp from command line. Gulp will build the project and run it on localhost:3000 using browser-sync.

Final files

Lets have a look at the final gulpfile.js.

gulpfile.js
var sass = require('gulp-sass');
var gulp = require('gulp');
var jshint = require('gulp-jshint');
var uglify = require('gulp-uglify');
var browserSync = require('browser-sync').create();

gulp.task('lint', function() {
  return gulp.src('./src/**/*.js')
    .pipe(jshint())
    .pipe(jshint.reporter('default'));
});

gulp.task('scss', function() {
    gulp.src('./src/assets/scss/*.scss')
        .pipe(sass().on('error', sass.logError))
        .pipe(gulp.dest('./public/assets/stylesheets/'));
});

gulp.task('scripts', function() {
    return gulp.src('./src/**/*.js')
        .pipe(uglify())
        .pipe(gulp.dest('./public'));
});

gulp.task('copy', function() {
    gulp.src('./src/**/*.html')
        .pipe(gulp.dest('./public'))
});

gulp.task('build', ['lint', 'scss', 'scripts', 'copy'], function(){
    console.log('Build complete');
})

gulp.task('browser-sync', ['build'], function() {
    browserSync.init({
        server: {
            baseDir: "./public",
            // The key is the url to match
            // The value is which folder to serve (relative to your current working directory)
            routes: {
                "/bower_components": "bower_components"
            }
        },
        browser:"firefox"
    });
});

gulp.task('default', ['browser-sync'], function(){
    gulp.watch('./src/**/*.*', ["build"]);
    gulp.watch('./public/**/*.*').on('change', browserSync.reload);
})

And here is the package.json

package.json
gulp.task('scss', function() {
    gulp.src('./src/assets/scss/*.scss')
        .pipe(sass().on('error', sass.logError))
        .pipe(gulp.dest('./public/assets/stylesheets/'));
});

gulp.task('scripts', function() {
    return gulp.src('./src/**/*.js')
        .pipe(uglify())
        .pipe(gulp.dest('./public'));
});

Conclusion

Gulp is a task automater and a node.js build tool that cuts out your manual repetitive work. This saves your crucial time and lets you focus on coding. This tutorial showed how we can configure Gulp to carry out some basic tasks. However, we have only scratched the surface of Gulp. Gulp can automate much more complex tasks for us which we can look at in further tutorials.

Watch Video

Suggest

JavaScript for Absolute Beginners

JavaScript For Beginners - Learn JavaScript From Scratch

JavaScript for Beginners

JavaScript Bootcamp - 2016

JavaScript Tutorials: Understanding the Weird Parts

ES6 Javascript: The Complete Developer’s Guide