d
Amit DhamuSoftware Engineer
 

Use Gulp

9 minute read 00000 views

I was a long-time GruntJS user and enjoyed the benefits it provided. It's a great build tool that I used primarily for my front end development such as compiling SASS, minifying etc. I didn't see a need to change until GulpJS came on the scene.

The main difference between the two is that when using Grunt, each task is separate. That means if you were compiling 3 SASS stylesheets and then wanted to minify the 3 resulting files, these would be all be handled as separate tasks synchronously. Grunt would then create a temporary file for each source file, do the task you wanted to, write the new file and then delete the temporary file. This would happen for each single task and the source files would be IO'ed each time. As a result, the performance of completing all of these tasks would take a beating.

GulpJS on the other hand allows you to pipe tasks to a glob of files as you would do on the command line. This means I could say for these 3 SASS files, compile them and minify them like I would with Grunt but...the beauty is that all of this happens asychronously, I could do this all in one task and the source files are held in memory until all of the tasks associated with it are complete.

Let me show you how I use Gulp to do a series of common front end development tasks. I'll assume you have Node installed on your machine.

To begin, let's install Gulp globally.

$ npm install -g gulp

Installing Gulp globally means we have access to the gulp command anywhere on our system. To get it working with a project though, we need to install it within our project. Before we do that, we need to ensure that we have a package.json file in our project root so that's what the first command does.

$ npm init
$ npm install gulp --save-dev

The --save-dev flag adds gulp as a dev dependency to our package.json file and allows any other users that come on board with the project to simply do a npm install which will install of the project's dependencies.

Once you have run the above command, you'll notice that gulp has created a node_modules folder to which it installs all of these dependencies. Think of this as the vendor directory you would have if you were using something like Composer. If you are using Git (which I would strongly advise), then you would tend not to commit this node_modules directory and therefore should add it to your .gitignore file.

Now we have Gulp installed, let's install a few packages that we might use.

$ npm install gulp-ruby-sass gulp-concat gulp-rename gulp-jshint gulp-load-plugins gulp-minify-css gulp-uglify --save-dev

Now we have our project setup let's go ahead and create our gulpfile.js

$ touch gulpfile.js

At this point, I'd advise you to switch over to your code editor where we can start playing with our Gulp file. You may see a lot of tutorials online that add each task to it's own variable in the Gulp file. This is fine but if you notice above, we installed a package called gulp-load-plugins. This loads all of the plugins in your package.json and will allow us a sort of shortcut to access these tasks.

var gulp = require('gulp'),
  pkg = require('./package.json'),
  p = require('gulp-load-plugins')()

Notice how I have "aliased" p as a variable for me to access all my installed tasks. Let me show you how to use it by creating our first task that will compile 3 SASS files, minify them and then write the resulting files to a dist directory.

gulp.task('styles', function () {
  return gulp
    .src(['scss/variables.scss', 'scss/mixins.scss', 'scss/main.scss'])
    .pipe(p.rubySass({ style: 'expanded' }))
    .pipe(p.rename({ suffix: '.min' }))
    .pipe(p.minifyCss())
    .pipe(gulp.dest('dist'))
})

Believe it or not, that is it. We take our three SASS files from the scss directory, compile them (non-minified), minify them, change the filenames of the minified stylesheets so they have a .min suffix and then write the results to our dist directory.

You might be wondering why the rename task occurs before the minifying tasks; this is just a weird quirk which I could only get working by doing it this way.

Now we have configured the task, we can run gulp styles on the command line and it will do the business.

Let's make it so that all we need to do is type gulp on the command line to fire this task. We do this by creating a default task and to do that, simply add the following to your Gulp file.

gulp.task('default', ['styles'])

Now just type gulp and your styles task will run.

Next, let's add a task for a script we need to check through jshint, minify it and then write the result to our dist folder. While we're at it, we might as well add it to our Gulp default task.

gulp.task('scripts', function () {
  return gulp
    .src(['main.js'])
    .pipe(p.jshint())
    .pipe(p.jshint.reporter('default'))
    .pipe(p.uglify())
    .pipe(gulp.dest('dist'))
})
gulp.task('default', ['styles', 'scripts'])

You should now be able run gulp on the command line to see it work through both the styles and the scripts tasks.

Ok cool. So the last thing which I think you'll find useful is have Gulp watch your files so that it will perform tasks when certain files change.

gulp.task('watch', function () {
  gulp.watch(
    ['scss/variables.scss', 'scss/mixins.scss', 'scss/main.scss'],
    ['styles']
  )
  gulp.watch(['main.js'], ['scripts'])
})

I also tend to add watch to my default task so that when I run gulp on the command line, it will go through all of the tasks first and then wait for any new changes. That's optional but I'd recommend doing it.

The completed Gulp file should look like below.

var gulp = require('gulp'),
  pkg = require('./package.json'),
  p = require('gulp-load-plugins')()

gulp.task('styles', function () {
  return gulp
    .src(['scss/variables.scss', 'scss/mixins.scss', 'scss/main.scss'])
    .pipe(p.rubySass({ style: 'expanded' }))
    .pipe(p.rename({ suffix: '.min' }))
    .pipe(p.minifyCss())
    .pipe(gulp.dest('dist'))
})

gulp.task('scripts', function () {
  return gulp
    .src(['main.js'])
    .pipe(p.jshint())
    .pipe(p.jshint.reporter('default'))
    .pipe(p.uglify())
    .pipe(gulp.dest('dist'))
})

gulp.task('watch', function () {
  gulp.watch(
    ['scss/variables.scss', 'scss/mixins.scss', 'scss/main.scss'],
    ['styles']
  )
  gulp.watch(['main.js'], ['scripts'])
})

gulp.task('default', ['styles', 'scripts', 'watch'])

That's pretty much it for a crash course in using Gulp. I'll add some helpful links that I found useful at the bottom of this article. To make things more DRY, I tend to use a config.json file to house all my source file paths and load them in like var config = require("./config.json); and then use that to say something like config.sources.stylesheets to give me my glob of files for a task instead of providing an array of filenames.

As opposed to using Grunt, I noticed that my Gulp file shrunk from 100s of lines to about 40 which is always a good thing. It can look slightly more daunting at first but it appeals more to the coder in you rather than messing around with a bunch of config.

I hope you found this article helpful and check out the links below for some helpful Gulp resources.