A Gulp.js Tutorial

Published:

Gulp is a build tool that helps you automate your development workflow. In this article, we will dive deep into Gulp to show you how to use it effectively to create a simple workflow.

Let’s get started.

Note: This article is outdated. The latest version can be found here

Installing Gulp

We’ll start off the process by installing Gulp onto your computer. Gulp requires you to have Node.js and Node Package Manager (NPM) installed on your system, so if you haven’t gotten them yet, just head over to Node.js’s website and download the installer.

Once you’re done installing Node.js and NPM, you can install Gulp by typing the following command in the command line:

$ sudo npm install gulp -g
# Note: Only Mac users require the `sudo` keyword

Oh btw, you can opt not to use the sudo keyword by following these instructions

This command installs gulp globally and allows you to use the gulp command anywhere on your computer.

We’re now done with installing Gulp and we can move on to create a new project that uses Gulp.

Creating a Gulp Project

Let’s create a folder named project as we work through this article. Once you have created the folder, you’ll want to run npm init in it.

$ npm init

This npm init command asks you a few questions and creates a package.json file to store information about dependencies that you’ll use in this project.

The first dependency in our project is Gulp since we’re using it as our build tool. You’ll have to install gulp within the project folder by augmenting the install code slightly:

$ npm install gulp --save-dev

See that we have removed sudo from the command and replaced the -g flag with the --save-dev flag?

This --save-dev flag tells NPM to install gulp locally in (a dev term for within) the project, and save this dependency information in the package.json file.

Since we’re installing a package locally, we don’t have a need for administrator rights and hence the sudo was dropped. Removing this sudo is important and could potentially cause errors if you don’t.

Now, if you take a look at your package.json file, you should see that Gulp has been added as a dev dependency.

You should also see a gulp folder within the new node_modules folder that was created when you ran the npm install gulp --save-dev command.

Next, we’ll have to create a gulpfile.js file to store all our Gulp configurations.

There’s one more thing to do before we start configuring Gulp to create a workflow. We have to make sure we’re clear on how the project is structured.

Determining Project Structure

Let’s start off with a generic structure for a webapp:

project/
  |- app/
      |- css/
      |- fonts/
      |- images/
      |- index.html
      |- js/
      |- scss/
  |- dist/
  |- gulpfile.js
  |- node_modules/
  |- package.json

In this structure, the app folder will store all our written code, and the dist folder will be used to store code that’s production-ready.

Don’t worry if your actual projects has a structure that’s different from the current one we’re using right now. Once you’ve gotten the hang of Gulp, you’ll see how to tweak the gulpfile to work with your structure easily. So let’s work with this structure for now.

Once you’ve created the project structure with the corresponding folders, we can proceed on to writing your first Gulp task.

Writing Your First Task

To configure Gulp, you’ll first have to require gulp within your gulpfile.js:

// Requiring Gulp
var gulp = require('gulp')

This require statement tells Node.js to look under the node_modules folder, find a package named gulp and pass it to the gulp variable.

Once we have this gulp variable, we can use it to write different Gulp tasks. Here’s the basic syntax of a gulp task.

// Basic Gulp task syntax
gulp.task('task-name', function () {
  // Stuff here
})

Let’s write a task named ‘hello’ for a start, and let the task do a log that says “Hello Zell!“.

// Basic Gulp task syntax
gulp.task('hello', function () {
  console.log('Hello Zell!')
})

The task name is important since you’ll be able to use the task anywhere else in the Gulpfile to run the task.

You can also use run a task with the command line by using gulp plus the name of the task.

$ gulp hello

You should see a log from the terminal saying “Hello Zell!” once you ran the code in the terminal.

In reality, gulp tasks are slightly more complex that what we have written so far. You’ll have to use two other gulp methods, gulp.src and gulp.dest.

Creating a Real Task

Here’s what a real task may look like:

gulp.task('task-name', function () {
  gulp
    .src('src') // Get source files with gulp.src
    .pipe(somePlugin()) // Sends it through a gulp plugin
    .pipe(gulp.dest('dest')) // Outputs the file in the destination folder
})

Let’s put this template to use with a real example where we compile Sass to CSS. I’ll explain how to set up the task while we’re at it.

First, we’ll need to install a gulp plugin, gulp-sass, to compile Sass to CSS. We can install it with the npm install command with the --save-dev flag like what we did above.

$ npm install gulp-sass --save-dev

We will then need to require this plugin in the gulpfile.

var gulp = require('gulp')
// Requires the gulp-sass plugin
var sass = require('gulp-sass')

Now, create a styles.scss file within the app/scss folder and give it some styles to convert from Sass to CSS.

// Scss
.testing {
  display: flex;
  width: percentage(5/7);
  // Percentage is a Sass function that will be evaluated to CSS when compiled
}

This styles.scss file will be converted into CSS by passing through the gulp-sass plugin we installed. After passing through the plugin, it’ll be created as styles.css in the app/css folder.

Here’s how the task would look like:

gulp.task('sass', function () {
  gulp
    .src('app/scss/styles.scss') // Gets the styles.scss file
    .pipe(sass()) // Passes it through a gulp-sass task
    .pipe(gulp.dest('app/css')) // Outputs it in the css folder
})

We can test this sass task by running it in the command line.

$ gulp sass

Now, if you take a look at the styles.css file in app/css, you’ll see that the percentage() function has been evaluated into the following code:

.testing {
  display: flex;
  width: 71.42857%;
}

This means our styles.scss file has successfully been compiled into CSS.

Adding more functionality to the sass task

Just compiling from Sass to CSS isn’t good enough. Sometimes it makes more sense to add more plugins to make thing simpler for us. One of the best plugins that you’ll ever use when converting from Sass to CSS is autoprefixer,which helps you write vendor prefixes according to caniuse.

Let’s try adding autoprefixer to our sass task.

To do so, we’ll have to install the gulp plugin for autoprefixer.

$ npm install gulp-autoprefixer --save-dev

Then we’ll have to require autoprefixer.

var gulp = require('gulp')
var sass = require('gulp-sass')
// Requiring autoprefixer
var autoprefixer = require('gulp-autoprefixer')

Autoprefixer is usually placed after Sass is compiled into CSS. In Gulp, we’ll want to add another .pipe() so the resultant CSS gets passed through autoprefixer before it’s created as styles.css in app/css.

The modified code is hence:

gulp.task('sass', function () {
  gulp
    .src('app/scss/styles.scss')
    .pipe(sass())
    .pipe(autoprefixer()) // Passes it through gulp-autoprefixer
    .pipe(gulp.dest('app/css'))
})

Now if you run gulp sass again, you’ll notice that the output in the styles.css file has changed to include vendor prefixes for the display flex property:

.testing {
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  width: 71.42857%;
}

Another task that’ll help you out during development is to add sourcemaps.

A sourcemap is a string of information that tells the browser where different sections of the code is stored. With a CSS sourcemap, you can easily locate the original source code of specific lines of CSS just by checking out the inspector.

To add sourcemaps to the sass task, we’ll have to install the gulp-sourcemaps plugin.

$ npm install gulp-sourcemaps --save-dev
// Requiring Sourcemaps
var sourcemaps = require('gulp-sourcemaps')

The process to adding sourcemaps to our sass task is slightly different from adding autoprefixer. We’ll have to add two pipes instead of one.

First, we’ll need to initialize the sourcemap plugin right after getting source files from gulp.

Then, we’ll have to let the files pass through gulp-sass and gulp-autoprefixer before writing the sourcemaps at the end of the css file.

gulp.task('sass', function () {
  gulp
    .src('app/scss/styles.scss') // Gets the styles.scss file
    .pipe(sourcemaps.init()) // Initialize sourcemap plugin
    .pipe(sass())
    .pipe(autoprefixer())
    .pipe(sourcemaps.write()) // Writing sourcemaps
    .pipe(gulp.dest('app/css'))
})

Now if you run gulp sass on the terminal, you should be able to see that Gulp has written a sourcemap at the end of your CSS file.

.testing {
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  width: 71.42857%;
}

/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0eWxlcy5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0VBQ0UscUJBQWM7RUFBZCxzQkFBYztFQUFkLHFCQUFjO0VBQWQsY0FBYztFQUNkLGlCQUFpQixFQUZUIiwiZmlsZSI6InN0eWxlcy5jc3MiLCJzb3VyY2VzQ29udGVudCI6WyIudGVzdGluZyB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIHdpZHRoOiBwZXJjZW50YWdlKDUvNyk7XG59Il0sInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 */

Automatically update the CSS file when you save

Now it’s quite some work to run the gulp sass task whenever we want to compile Sass to CSS. Wouldn’t it be awesome if Gulp would run it automatically?

Gulp can do that! You’ll just have to let Gulp check whether the styles.scss file was changed when you save it. This checking process is called watching in programming terms.

Gulp does this watching by providing us with a watch method that allows you to run any task whenever a file is changed.

// Gulp watch syntax
gulp.watch('files-to-watch', ['tasks', 'to', 'run'])

Instead of just watching the Sass files alone, you’ll often want to watch many types of files and run different tasks during a development process. In order to achieve that, we can create a watch gulp task that watches different files.

gulp.task('watch', function () {
  gulp.watch('app/scss/styles.scss', ['sass'])
  // ... Other watchers
})

Now if you run the watch command you’ll see that gulp immediately starts watching your files for changes.

And if you change a line in styles.scss, Gulp will automatically run the sass task.

There’s only one thing that’s lacking here. Gulp didn’t run the sass task first before running watch, which means the CSS might not be the most updated one. Hence, we’ll want to make sure the watch task runs after the sass task.

We can do so by adding a second parameter to the watch task. This second parameter is an array of tasks that must be completed before Gulp runs watch.

gulp.task('watch', ['sass'], function () {
  gulp.watch('app/scss/styles.scss', ['sass'])
  // ... Other watchers
})

Now if you run the watch task, you’ll see that Gulp tells the command line to first run the sass task, followed by the watch task.

Since we’re already watching and recompiling Sass files when it’s changed, why not bring it further and reload the browser each time the file is saved?

Automatically Refreshing the Browser when you save

Having the browser automatically refreshing when you save a file is a task that saves you lots of time and hand-ache.

The best project for refreshing the browser right now is Browser Sync, and we can use with Gulp easily.

First, we’ll have to install Browser Sync.

$ npm install browser-sync --save-dev

You’ll notice that there’s no more gulp- prefix when installing Browser Sync. This is because Browser Sync can be made to work with Gulp right out of the box; you don’t need a Gulp plugin.

We’ll have to require Browser Sync, as usual.

var browserSync = require('browser-sync')

Browser Sync spins up a local server to load static HTML files. We’ll have to provide it with some initial configurations so it knows where to find our index.html file.

Let’s make a browserSync task for spinning up this server.

// Start browserSync server
gulp.task('browserSync', function () {
  browserSync({
    server: {
      baseDir: 'app',
    },
  })
})

Next, we’ll need to change the sass task slightly to allow Browser Sync to inject new CSS into the HTML. To do so, we’ll hav eto add a return before gulp.src and we’ll have to .pipe() a Browser Sync reload method.

gulp.task('sass', function () {
  return (
    gulp
      .src('app/scss/styles.scss') // added return
      .pipe(sourcemaps.init())
      .pipe(sass())
      .pipe(autoprefixer())
      .pipe(sourcemaps.write())
      .pipe(gulp.dest('app/css'))
      // Reloading the stream
      .pipe(
        browserSync.reload({
          stream: true,
        }),
      )
  )
})

We’ll also have to make sure the browserSync task runs before the watch task.

gulp.task('watch', ['browserSync', 'sass'], function () {
  gulp.watch('app/scss/styles.scss', ['sass'])
})

If you run gulp watch in the terminal now, you’ll see that browserSync and sass runs concurrently, followed by watch. In addition, a browser pops up to show you the current index.html file.

So if you change the styles.scss file and save…

Viola! :)

Since we’re already watching for changes and refreshing the browser when we save styles.scss, why not do it for index.html as well?

gulp.task('watch', ['sass'], function () {
  gulp.watch('app/scss/styles.scss', ['sass'])
  gulp.watch('app/index.html', browserSync.reload)
})

Now that’s an example of a decent workflow that converts Sass to CSS. Of course, there’s a lot of improvements you can make to it. For instance, you can configure options for each of the plugins used, and you can also watch more files with some node globbing knowledge.

We’ll cover those in the next article :)

Now let’s do a quick summary.

Wrapping Up

So in this article we learned how to install Gulp and we learn to set up a basic task with Gulp.

Then we went ahead and setup a real task by adding different gulp plugins to the mix.

Eventually, we made it much better by watching the files for change and refreshing the browser whenever possible.

There’s still a whole lot more to configuring Gulp, but we’ll pause here for now. Let’s continue in the next article.

What is one thing you’ve learned about Gulp in this tutorial? Let me know in the comments below!

Learn to use Gulp

Save hours everyday building and deploying your website because you have a good web development system backing you up.

Start reclaiming your free time with 10 free chapters.