How to automate all the things with Gulp
Tags: gulp, startup, node, softwaredevelopment
Published: 2018-02-10 22:20:39

---
title: "How to automate all the things with Gulp"
published: true
tags: gulp,startup,nodejs,software-development
canonical_url: https://hackernoon.com/how-to-automate-all-the-things-with-gulp-b21a3fc96885
cover_image: https://thepracticaldev.s3.amazonaws.com/i/7g2uzm7ofsuzvf469dyh.png
---

Have you ever been tired of hitting the F5 key once too often? Yeah, I understand the pain. Here’s where task automation shines. Writing scripts to continuously handle the time-consuming tasks you actually need in your development workflow. Don’t get cold feet on me here. It’s a lot less scary than it sounds. Trust me. Once you get the hang of it, you’ll never want to write code without&nbsp;it.

So why Gulp? Because you’re writing the tasks with your best buddy, plain old JavaScript. It doesn’t get any better than&nbsp;that.

## [gulp.js](http://gulpjs.com/)

#### Blowing up the Death&nbsp;Star.

In comes Gulp. The hero you need, and most definitely deserve. There are several key features regarding the use of Gulp which would make you want to use it. The one I hold as the most important is the way it can **simulate** the server environment where you will ultimately be hosting your code. This includes moving files around your project directory, and more importantly placing them in a **development directory** where you will be running a web server. Gulp also enables you to **compile** , **minify** and **concatenate** any files you want. All with the sole goal of getting your code base’s footprint down to the absolute minimum. In this process making it ready for **shipping to production**. It’s perfectly fine if you don’t know any of the terms above, we’ll go through them in more detail a bit further&nbsp;down.

#### TLDR;

You can severely hurt my feelings by only reading this TLDR; or be awesome instead, and read the whole article. Have&nbsp;fun!

1. Three main Gulp commands: gulp.task, gulp.src, gulp.dest.
2. pipeing is freaking awesome! The pipe() method is built into Node.js and is used to copy files from one folder to&nbsp;another.
3. Have a logical folder structure, with three main folders. The **_src_** folder for pre-processed files, **_tmp_** for the local development server and **_dist_** for processed and minified&nbsp;files.
4. Create separate tasks for pipeing HTML, CSS and JavaScript files from **_src_** to&nbsp; **_tmp_**.
5. Combine the HTML, CSS and JavaScript tasks into one main **_â€˜copy’_** task. This will let you copy all the files with one&nbsp;command.
6. After all files have been copied you want to reference them automatically in your main **_index.html_**. This is done with an **_â€˜inject’_** task and is called injecting dependencies.
7. When the files have been copied and injected it’s time to run a development server on the **_tmp_** &nbsp;folder.
8. While the server is running you **_â€˜watch’_** for changes, and enable live reloading on the local development server.
9. Satisfied with your code? Go ahead and **_â€˜build’_** the production files and place them in the **_dist_** directory.
10. Delete **_tmp_** and **_dist_** before pushing to GitHub. (Or just add them to your&nbsp;.gitignore)
11. The code you will be writing during this tutorial is on GitHub and will be linked at the bottom of the article. Sorry, but you have to scroll to the bottom.&nbsp;:)

#### Install the&nbsp;tools

First of all, you will need to have Node installed on your machine. To check if you do, open up a command prompt and type node -v. The version number of Node you have installed will be shown as output on the command line. If not, you do not have Node installed on your machine. Not to worry, head over to Node’s official site to get&nbsp;started.

## [Download Node.js](https://nodejs.org/en/download/)

All done? Now you’re set to install the necessary tool regarding the actual task automation. Go back to your command prompt and&nbsp;run:

```bash
npm install -g gulp
```

_Note: Linux and Mac users will most likely need to run this command with_ **_sudo_** _, to enable the required permissions._

You’ve now installed Gulp globally on your machine. This step is important as it is required for Gulp to be visible in your command line regardless of which directory you are in. The more technical explanation would be that Gulp has now been added to the&nbsp; **PATH**.

You’re now ready to get started with writing&nbsp;tasks.

#### Introduce yourself

There are three main commands Gulp provides:

- gulp.taskâ€Š–â€Šdefines a new task giving it a name, an array of dependencies and a callback function, which will be called when the task is&nbsp;run.
- gulp.srcâ€Š–â€Šsets the source folder where files are&nbsp;located.
- gulp.destâ€Š–â€Šsets the destination folder where files will be&nbsp;placed.

The backbone of using Gulp at all lies in the interaction between gulp.src and gulp.dest with the&nbsp;.pipe method as a&nbsp;bridge.

The&nbsp;.pipe method is a default method in Node.js, not to delve deeper into this particular subject, view it as a means to copy files from one directory to&nbsp;another.

What does this&nbsp;mean?

Gulp by itself only provides the basis needed for task automation. The bulk of the work you would need in a development workflow lies in the vast plug-ins created for Gulp. Without them, you only have a shell. Of course, you could write your own, but with more than 3000 available for download on [**npm**](https://www.npmjs.com/), I would advise against this. Do not reinvent the wheel. Use the resources which are already at your disposal. Feel free to take a look [here](http://gulpjs.com/plugins/), or just Google “gulp _whatever_ and witness the&nbsp;magic.

#### Baby steps

Let’s code up a very basic backbone, just to wrap our heads around the concept. We’ll incrementally progress further down this&nbsp;article.

First of all create a new directory giving it a super inspiring name, something like _super-awesome-gulp-tutorial_ should be fine. Once you’ve done this open up a command prompt within this directory. As Gulp is a package on **npm** you will need to initialize **npm** to have a link to the package&nbsp;manager.

Not familiar with **npmâ€Š–â€Šthe Node Package Manager**? Take a look&nbsp;here.

## [npm](https://www.npmjs.com/)

After you’ve done this, you will also need to install Gulp locally. Why? Gulp will always use the local version of itself in project&nbsp;folders.

```bash
npm init
npm install gulp --save-dev
```

Installing it with the _--save-dev_ flag will include it in the **_package.json_** beneath the development dependencies. Great job, ready for some code? Let’s jump in. Create a new file, name it **_gulpfile.js_** _._ This file is the entry point for Gulp, here’s where you will be writing all the code to automate tasks. Go ahead and write this in your **_gulpfile.js_** :

```javascript
var gulp = require('gulp');

gulp.task('default', function () {
  console.log('Hello World!');
});
```

Congratulations. You’ve just written your first Gulp task. I bet this seems familiar to you, an event listener followed by a callback function. Let’s try it out. Jump back to your command prompt, and just&nbsp;type:

```bash
gulp
```

Hit enter and you will see something like this get logged back to the command&nbsp;line:

```bash
[19:41:16] Using gulpfile ~/super-awesome-gulp-tutorial/gulpfile.js
[19:41:16] Starting 'default'...
Hello World!
[19:41:16] Finished 'default' after 162 Î¼s
```

By using the keyword gulp you told Gulp to interpret a particular task, and as nothing was written after the keyword, the **_â€˜default’_** task was run. Let’s say you have a task named â€˜ **_build_** _’_ and you wish to run it. Writing gulp build will trigger that particular Gulp task. You can even run multiple tasks, which is also perfectly fine. It looks like&nbsp;this.

```bash
gulp sometask anothertask
```

Have you been following along? Great, you’re now ready to code some serious stuff. Let’s get a development environment up and&nbsp;running.

#### Full hacker mode,&nbsp;ON

I’ll start by outlining a basic folder structure of a sample project. One of many best practices is to have three main folders, **_src_** for all of your source files, **_dist_** for the bundled and minified files, and finally a **_tmp_** directory which will be used as the sandbox for our local web&nbsp;server.

- **src** â€Š–â€Šsource files, pre-processed, un-minified.
- **tmp** â€Š–â€Šdevelopment files, pre-processed, un-minified. The directory where you will be running the web&nbsp;server.
- **dist** â€Š–â€Šproduction files, processed, minified.

Create the **_src_** folder, but do **not** create the **_dist_ nor the _tmp_** folder yet. You will see a bit further down how you can create it dynamically and incorporate it into an automated task. Let’s add some files to the **_src_** folder, to finally have something to play with. An **_index.html_** , a **_script.js_** and a **_style.css_** should be more than enough. These will serve as your source files, the only files you will be editing. Gulp will handle everything else.

Let’s get started with the Gulping of all the&nbsp;things!

#### Step 1â€Š–â€ŠSet up the folder structure

First of all you need a **_paths_** variable to store all the file and directory paths of your project. Place this right under where you required&nbsp;gulp.

```javascript
// gulpfile.js
var gulp = require('gulp');
var paths = {
  src: 'src/**/*',
  srcHTML: 'src/**/*.html',
  srcCSS: 'src/**/*.css',
  srcJS: 'src/**/*.js',

tmp: 'tmp',
  tmpIndex: 'tmp/index.html',
  tmpCSS: 'tmp/**/*.css',
  tmpJS: 'tmp/**/*.js',

dist: 'dist',
  distIndex: 'dist/index.html',
  distCSS: 'dist/**/*.css',
  distJS: 'dist/**/*.js'
};

gulp.task('default', function () {
  console.log('Hello World!');
});
```

Specifying the /\*\*/\* part is equivalent to including all files within the folder and any possible subfolders.

#### Step 2â€Š–â€ŠSet up the HTML&nbsp;task

Now you need to create a task to copy all HTML files from the **_src_** directory to the **_tmp_** directory where you’ll be running the web&nbsp;server.

```javascript
gulp.task('html', function () {
  return gulp.src(paths.srcHTML).pipe(gulp.dest(paths.tmp));
});
```

#### Step 3â€Š–â€ŠSet up the CSS&nbsp;task

Same thing for the CSS&nbsp;files.

```javascript
gulp.task('css', function () {
  return gulp.src(paths.srcCSS).pipe(gulp.dest(paths.tmp));
});
```

#### Step 4â€Š–â€ŠSet up the JavaScript task

Yup, same thing for the JavaScript files.

```javascript
gulp.task('js', function () {
  return gulp.src(paths.srcJS).pipe(gulp.dest(paths.tmp));
});
```

#### Step 5â€Š–â€ŠCombine all tasks into one&nbsp;task

This part is fun. Gulp allows you to combine tasks, and add tasks to other tasks as dependencies. This feature is incredibly useful because you can tell Gulp to run and complete certain tasks before even starting other&nbsp;tasks.

```javascript
gulp.task('copy', ['html', 'css', 'js']);
```

Try it out! Here’s what you’ll see after running gulp&nbsp;copy.

```bash
[19:39:08] Using gulpfile ~/super-awesome-gulp-tutorial/gulpfile.js
[19:39:08] Starting 'html'...
[19:39:08] Starting 'css'...
[19:39:08] Starting 'js'...
[19:39:08] Finished 'css' after 19 ms
[19:39:08] Finished 'html' after 30 ms
[19:39:08] Finished 'js' after 18 ms
[19:39:08] Starting 'copy'...
[19:39:08] Finished 'copy' after 4.67 Î¼s
```

Jump back to your project folder and take a look. Now you have a **_tmp_** directory. It was created dynamically. Magic! (Just kidding, not really.)  
The **_tmp_** directory contains the same files you have in the **_src_** directory. The&nbsp;.pipe() command has copied files from the source to the given destination.

#### Step 6â€Š–â€ŠInject files into the index.html

What’s this? Well, you’ve copied the files over to the **_tmp_** folder. Now you need to tell the **_index.html_** which CSS and JavaScript files you want to reference. This is done quite easily with a Gulp plug-in called [gulp-inject](https://www.npmjs.com/package/gulp-inject). Go ahead jump back to the command prompt and&nbsp;run:

```bash
npm install gulp-inject --save-dev
```

Now, you need to add a reference in the **_index.html_** where you wish to inject the&nbsp;files.

```html
<!DOCTYPE html>
<html>
  <head>
    <!-- src/index.html -->
  
    <!-- inject:css -->
    <!-- endinject -->
  </head>
  <body>

<!-- inject:js -->
    <!-- endinject -->
  </body>
</html>
```

After gulp-inject has been run, there will be files between these comments. Keep in mind they need to look exactly like what is written&nbsp;above.

Jump back to the **_gulpfile.js_** and add&nbsp;this:

```javascript
var inject = require('gulp-inject');
```

Keep in mind, you’ve already added the reference to the files within the tmp folder. It should look like&nbsp;this:

```javascript
var paths = {
  src: 'src/**/*',
  srcHTML: 'src/**/*.html',
  srcCSS: 'src/**/*.css',
  srcJS: 'src/**/*.js',

tmp: 'tmp', // tmp folder
  tmpIndex: 'tmp/index.html', // index.html in tmp folder
  tmpCSS: 'tmp/**/*.css', // css files in tmp folder
  tmpJS: 'tmp/**/*.js', // js files in tmp folder

dist: 'dist',
  distIndex: 'dist/index.html',
  distCSS: 'dist/**/*.css',
  distJS: 'dist/**/*.js'
};
```

Now you’re ready to add another task to inject the&nbsp;files.

```javascript
gulp.task('inject', ['copy'], function () {
  var css = gulp.src(paths.tmpCSS);
  var js = gulp.src(paths.tmpJS);
  return gulp.src(paths.tmpIndex)
    .pipe(inject( css, { relative:true } ))
    .pipe(inject( js, { relative:true } ))
    .pipe(gulp.dest(paths.tmp));
});
```

Look at this now. You’ve added the **_â€˜copy’_** task as a dependency for the **_â€˜inject’_** task. Gulp will first copy all the files to the **_tmp_** directory, only then will it do the injecting. Let’s break this down. You’re placing the gulp.src of the files copied to the **_tmp_** folder into two respective variables. One for the CSS, the other for the JavaScript files. In the return statement you grab the **_index.html_** which has already been piped to **_tmp_** with the **_â€˜copy’_** task and&nbsp;.pipe() the inject() function with the variables where you placed the respective files from the **_tmp_** directory. The second parameter you pass to the inject() function is an options object. Here, relative:true means that the file paths to be referenced in the **_index.html_** will be relative. You want this. Trust me. It’ll save you so much headache.

Toggle back to the command prompt and run gulp inject. The **_index.html_** within your **_tmp_** directory should now look like&nbsp;this.

```html
<!DOCTYPE html>
<html>
  <head>
    <!-- tmp/index.html -->
  
    <!-- inject:css -->
    <link rel="stylesheet" href="style.css">
    <!-- endinject -->
  </head>
  <body>

<!-- inject:js -->
    <script src="script.js"></script>
    <!-- endinject -->
  </body>
</html>
```

#### Step 7â€Š–â€ŠServe the development web&nbsp;server

I bet you’d like to see the fruits of your labor. I would too. Let’s get a server up and running to quench that&nbsp;thirst.

Go ahead and switch back to the command line and&nbsp;run:

```bash
npm install gulp-webserver --save-dev
```

This is a Gulp plug-in which allows you to run a web server on your local machine. Exactly what you need. After you’ve installed it, go ahead and require it at the top of your **_gulpfile.js_**.

```javascript
var webserver = require('gulp-webserver');
```

Great! Let’s get the **_â€˜serve’_** task coded&nbsp;up.

```javascript
gulp.task('serve', ['inject'], function () {
  return gulp.src(paths.tmp)
    .pipe(webserver({
      port: 3000,
      livereload: true
    }));
});
```

Once again you need to include a dependency. Here you want the **_â€˜inject’_** task to finish before running the web server. Simply reference the **_tmp_** directory and&nbsp;.pipe() it to the web server. The gulp-webserver plug-in takes an options object as a parameter. You will need to specify the port on which it will run, and tell the server to reload if it senses any changes. Once you get used to this. There’s no going&nbsp;back.

Let’s test this out. Add some lines of code to the files in the **_src_** directory. Here’s a simple&nbsp;example:

**_index.html_**

```html
<!DOCTYPE html>
<html>
  <head>
    <!-- inject:css -->
    <!-- endinject -->
  </head>
  <body>
    <div class="awesome">This is awesome!</div>

<!-- inject:js -->
    <!-- endinject -->
  </body>
</html>
```

**_style.css_**

```css
.awesome {
  color: red;
}
```

**_script.js_**

```javascript
console.log('Awesome!');
```

Jump back to the command line and run gulp serve. You should see this get logged back to&nbsp;you.

```bash
[23:50:44] Using gulpfile ~/super-awesome-gulp-tutorial/gulpfile.js
[23:50:44] Starting 'html'...
[23:50:44] Starting 'css'...
[23:50:44] Starting 'js'...
[23:50:44] Finished 'html' after 30 ms
[23:50:44] Finished 'js' after 19 ms
[23:50:44] Finished 'css' after 22 ms
[23:50:44] Starting 'copy'...
[23:50:44] Finished 'copy' after 4.77 Î¼s
[23:50:44] Starting 'inject'...
[23:50:44] gulp-inject 1 files into index.html.
[23:50:44] gulp-inject 1 files into index.html.
[23:50:44] Finished 'inject' after 16 ms
[23:50:44] Starting 'serve'...
[23:50:44] Webserver started at http://localhost:3000
[23:50:44] Finished 'serve' after 18 ms
```

By running the serve task all of the tasks specified as dependencies have been run first. Exactly what you want. Head over to your browser of choice and open up [http://localhost:3000](http://localhost:3000). Hopefully, you’ll see something like&nbsp;this.

![](https://cdn-images-1.medium.com/max/1024/1*0Z_ZjxwF-8qoje6cn0OzJQ.png)

#### Step 8â€Š–â€ŠWatch for&nbsp;changes

Watching for changes means Gulp will constantly be checking for changes among your files. You only have to specify which files it has to&nbsp;watch.

```javascript
gulp.task('watch', ['serve'], function () {
  gulp.watch(paths.src, ['inject']);
});
```

The **_â€˜watch’_** task will first wait for the **_â€˜serve’_** task to finish, only then will it start the watching. You tell Gulp to watch the files in the **_src_** directory. If it senses any changes it will fire the **_â€˜inject’_** Gulp task. Now whenever you save the changes in any of the specified files, Gulp will fire the **_â€˜inject’_** task. Awesome stuff! You can even go ahead and link the **_â€˜watch’_** task to the default&nbsp;task.

```javascript
gulp.task('default', ['watch']);
```

Now you can just run gulp which will in turn run all of the tasks you have already built. I guess you just did Gulp all the&nbsp;things.

#### Step 9â€Š–â€ŠBuilding the&nbsp;dist

With the development environment up and running you’ve come to the point where you want to pack up your files to make them ready for production. Here’s where Gulp really flexes its muscles. Go ahead and install the following Gulp plug-ins.

```bash
npm install gulp-htmlclean --save-dev
npm install gulp-clean-css --save-dev
npm install gulp-concat --save-dev
npm install gulp-uglify --save-dev
```

And require them at the top of the **_gulpfile.js_**.

```javascript
var htmlclean = require('gulp-htmlclean');
var cleanCSS = require('gulp-clean-css');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
```

You can now re-use the majority of the already written tasks to create the build&nbsp;tasks.

```javascript
gulp.task('html:dist', function () {
  return gulp.src(paths.srcHTML)
    .pipe(htmlclean())
    .pipe(gulp.dest(paths.dist));
});

gulp.task('css:dist', function () {
  return gulp.src(paths.srcCSS)
    .pipe(concat('style.min.css'))
    .pipe(cleanCSS())
    .pipe(gulp.dest(paths.dist));
});

gulp.task('js:dist', function () {
  return gulp.src(paths.srcJS)
    .pipe(concat('script.min.js'))
    .pipe(uglify())
    .pipe(gulp.dest(paths.dist));
});

gulp.task('copy:dist', ['html:dist', 'css:dist', 'js:dist']);

gulp.task('inject:dist', ['copy:dist'], function () {
  var css = gulp.src(paths.distCSS);
  var js = gulp.src(paths.distJS);
  return gulp.src(paths.distIndex)
    .pipe(inject( css, { relative:true } ))
    .pipe(inject( js, { relative:true } ))
    .pipe(gulp.dest(paths.dist));
});

gulp.task('build', ['inject:dist']);
```

The added plug-ins are piped between the gulp.src and gulp.dest commands. Everything else remains the&nbsp;same.

Only one more thing to add to you **_index.html_** &nbsp;:

```html
<!DOCTYPE html>
<html>
  <head>
    <!--[htmlclean-protect]-->
    <!-- inject:css -->
    <!-- endinject -->
    <!--[/htmlclean-protect]-->
  </head>
  <body>
    <div class="awesome">This is awesome!</div>

<!--[htmlclean-protect]-->
    <!-- inject:js -->
    <!-- endinject -->
    <!--[/htmlclean-protect]-->
</body>
</html>
```

The htmlclean plug-in cleans all comments out of your templates by default. You need to disable this behavior only for the inject comments.

Go ahead and run the **_â€˜build’_** &nbsp;task.

```bash
gulp build
```

Take a look at your project folder. You can now see a **_dist_** folder. The files within have been concatenated and minified, ready to be sent off to a production server.

#### Step 10â€Š–â€ŠCleaning&nbsp;up

It’s not considered good practice to send off the **_tmp_** and **_dist_** folders to GitHub or whatever version control you may be using. You will need a way to delete them without much&nbsp;hassle.

```bash
npm install del --save-dev
```

Install the package above. This will make your life a lot easier. Require it at the top of **_gulpfile.js_** like&nbsp;so:

```javascript
var del = require('del');
```

And add this snippet of&nbsp;code:

```javascript
gulp.task('clean', function () {
  del([paths.tmp, paths.dist]);
});
```

Jump back to your command line and run gulp clean. Watch the magic. The **_tmp_** and **_dist_** folders have been&nbsp;deleted!

Another good practice would be to add the **_tmp_** and **_dist_** folders to your&nbsp; **_.gitignore_** , making sure you definitely never push them to your GitHub repository.

If you missed any of the steps above feel free to jump over to the GitHub [**repository**](https://github.com/adnanrahic/gulp-all-the-things) and catch your breath. The whole code base is over there, no need to&nbsp;worry.

You’ve faced the dark side and emerged a hero. Great job! This has been a _“throw you in the deep end of the pool”_ crash course on task automation. I’m confident to say you can swim if you’ve come this far. Don’t stop here though. There’s so much more to learn about Gulp, this was just the beginning. But, regardless of that, it’s more than enough for you to get started with building serious applications and start shipping code. The best way of learning something is through concrete examples. Hack away and ship as much code as possible.

_Hope you guys and girls had as much fun reading this article as I had writing it._

* * *


_This post was originally published on [medium.com](https://hackernoon.com/how-to-automate-all-the-things-with-gulp-b21a3fc96885)_