Gulp from 0 to 60

-21 Nov 2014-

Gulp is a JavaScript task runner. It can automate tasks in your development environment like running tests, linting code, compiling sass, and much, much, more. If all of that doesn’t make a ton of sense to you, don’t worrry. In this post, I plan on outlining how to get Gulp up an running for someone with no knowledge of task runners or node.

Tasks

In this example environment we are about to set up, we will have Gulp handle 4 tasks for us.

  1. Opening a local webserver.
  2. Processing our scss files into one style.css file.
  3. Watching our files for changes and running tasks accordingly.

These are just what I needed for a project I am working on. Gulp is capable of many dozens of tasks, but for right now we will stick with these.

Setup

The first necessary step is to install Node if you have not already. Their website has good instructions for installation through their site or a package manager like brew. If you are not familiar, Node is basically the innards of Google Chrome’s JavaScript interpreter in a standalone application. This allows us to write JavaScript programs that can perform console-style tasks like spinning up servers, parsing files, and editing their output.

Installing node will automatically install npm which stands for ‘Node package manager’. This program will allow you to install node modules (programs) from the npm repository. It is very similar to brew, apt-get, or ruby gems if you have ever used any of these.

After installing node, we need to make a configuration file in our current project for node. This is one simple command, npm init. Running this will ask a few questions and then output a file in your root directory called package.json. This file is how Node keeps track of your project and its dependency modules. If you get a project with a package.json, you can install all of its dependencies via npm install.

To install a single module with npm, you use the command npm install <options> <package-names>, where ‘package-names’ is a space-separated list of package names. There are quite a few options you can pass in, but the 3 that are important in this post are:

Since this is our first time installing gulp, we will need to instal it globally so we can use the gulp command from the terminal and also locally on our project as a development dependency. So this far, we should have run these commands…

npm init
#Answer questions for package.json initialization
npm install --global gulp
npm install --save-dev gulp

That’s it as far as getting the basics set up for Node. Now we need to configure gulp with our Gulpfile

Gulpfile

Go ahead and make a file in your root directory called Gulpfile.js this is the file that gulp uses to configure its tasks. We can make a basic skeleton gulpfile that will look like this.

var gulp = require('gulp');

gulp.task('default', function(){
  console.log("Gulp is running!");
});

Now if you jump back into your console and run gulp, the console should print out

[10:26:12] Using gulpfile ~/myCoolSite/Gulpfile.js
[10:26:12] Starting 'default'...
Gulp is running!
[10:26:12] Finished 'default' after 72 μs

Awesome! We got Gulp to print out to the console. Now, let’s talk about that Gulpfile, because there is some Node-specific stuff that might be confusing. So here in the first line…

var gulp = require('gulp');

This require keyword is a Node method that will import a module. It will look in your node_modules folder (which was created when you npm installed gulp) for the module and put it into the gulp variable so that we can use the gulp methods in our JavaScript. Using and creating node modules is a pretty deep subject, but for now all you need to know is that require pulls in a module that we installed with npm install.

gulp.task('default', function(){
  console.log("Gulp is running!");
});

This is the way in which gulp will make tasks. The first argument it takes in is the name of the task we are defining and the second argument is the function that will run in the task. Here we are just calling a console.log. In browsers, console.log will output to the JavaScript console, but in node it will output to the terminal. Alright, time to start making this actually useful.

Webserver

To get our webserver running, we need to first install the module for doing so. Jump out to your terminal and run npm install -D gulp-webserver. This is a module that lets us spin up a localhost server from a directory and use livereload if we want. There are a multitude of server modules for gulp, but this is a dead simple one and you can always switch to a different one later.

Now to get the webserver accessible in our gulp we need to require it, so add the line var webserver = require('gulp-webserver'); at the top of your Gulpfile. note that I called the variable ‘webserver’ instead of ‘gulp-webserver’. This is a pretty common convention, and also just helps you avoid having to write ‘gulp-‘ all over the place.

Now change your default gulp task to be…

gulp.task('default', function(){
  console.log("Gulp is running!");
  gulp.src('./')
    .pipe(webserver());
});

So there are a couple new things here, first of all is gulp.src(). This is a gulp function that will take in one argument, a string, that will be a file or directory that can then feed in to other processes. This string can use glob matching so that *.js will match any .js file and app/**/*.js will match any .js in any folder in the app directory.

The second new thing is .pipe this is a method on the object that gulp.src returns. This will take the files and directories selected in src and then pass or ‘pipe’ them into a function. We pipe the source (which here ./ is our root directory) into the webserver function. So the basic gulp work flow looks like this:

gulp.src(files)
  .pipe(doStuffWithFiles())
  .pipe(doMoreStuffWithFiles());

Sass Processing

Next up is Sass. If you aren’t familiar, Sass is a language that looks like CSS with some added functionality which compiles down into CSS. So go ahead and install some more modules with npm install -D gulp-sass gulp-concat. ‘gulp-sass’ will translate our .scss files into .css and ‘gulp-concat’ lets us concatenate a bunch of files together into one. So we will take all of the .scss files we have and then smoosh them all together in one style.css file.

First make sure you require your new modules in your Gulpfile, so the beginning should now look like this.

var gulp = require('gulp');
var webserver = require('gulp-webserver');
var sass = require('gulp-sass');
var concat = require('gulp-concat');

alright, now we need to make a new task for compiling the Sass and then also include as part of our default task. This code will look like this.

gulp.task('sass', function(){
  gulp.src('sass/*.scss')
    .pipe(sass())
    .on('error', console.log)
    .pipe(concat('style.css'))
    .pipe(gulp.dest('.'));
});

gulp.task('default', ['sass'], function(){
  console.log("Gulp is running!");
  gulp.src('./')
    .pipe(webserver());
});

In the default task, we passed in an array after the first argument. This is an array of all of the tasks we have previously defined that we need to run before we run the task we are currently defining. In this case, gulp will run the task sass and create our stylesheet before running the default task and loading the server.

So in the sass task, after we pipe all of our .scss files (sass/*.scss as long as you are storing your .scss files in a directory called ‘sass’) we handle errors by passing any possible errors from the sass process into console.log so that we can see them. Then we pipe that into the concat function which takes one argument, the name of the file that the concatenated files should have. So our new file will be called style.css.

After this, we see a new function, gulp.dest(). This function is the yin to gulp.src’s yang. It will take all of the files from source, now modified by whatever they have been piped into, into a destination folder, in this case, our root folder. Now we are getting somewhere, but still have one more task to implement.

Watching Files

Watching files for changes and then running tasks is a key feature of a task runner, and it could not be simpler with gulp. We don’t even need a new module for this one, gulp includes its own watch method. All we have to do is add a single line to our default task.

gulp.task('default', ['sass'], function(){
  console.log("Gulp is running!");
  gulp.src('./')
    .pipe(webserver());
  gulp.watch('sass/*.scss', ['sass'] )
});

After our webserver, we call gulp.watch. The first argument here is a file glob like in our gulp.src call, and the second argument is an array of tasks to run when any of the files in the first argument change. So any time an .scss file in our sass directory gets changed, gulp will automatically render it to css, it’s pretty neat. So now our final gulpfile looks like this.

var gulp = require('gulp');
var webserver = require('gulp-webserver');
var sass = require('gulp-sass');
var concat = require('gulp-concat');


gulp.task('sass', function(){
  gulp.src('sass/*.scss')
    .pipe(sass())
    .on('error', console.log)
    .pipe(concat('style.css'))
    .pipe(gulp.dest('.'));
});

gulp.task('default', ['sass'], function(){
  console.log("Gulp is running!");
  gulp.src('./')
    .pipe(webserver());
  gulp.watch('sass/*.scss', ['sass'] );
});

From here there are limitless ways to use Gulp to make your life easier. It can compile coffeescript, lint your code, minify, prettify, optimize images, run test suites and probably 100 other things. And if there is something that you want to do that isn’t available, you can always build it.

Go back