Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Typescript

Create a gulpfile and Write gulp Tasks Using TypeScript

5.00/5 (1 vote)
21 Jan 2016Public Domain4 min read 12K  
Learn how to create gulp files in TypeScript and how to define gulp tasks in a class-based style

Introduction

Are you migrating code from JavaScript to typescript, or writing a new app using typescript, but don’t know how to write gulp tasks in typescript? Then this tip is for you.

There are some caveats in writing gulp tasks in typescript. First of all, when you run “gulp” in command line by default, it tries to work only with gulpfile.js file, and there is no support of gulpfile.ts or typescript at all. And how do we solve it? We need to compile our gulpfile.ts to the gulpfile.js using typescript compiler. That is a solution. But what if typescript compilation is a part of the gulp tasks process? This may be a problem, because you cannot run gulp tasks until you compile a typescript code, which can be compiled only after you run a gulp task. Recursion, hah? This tip answers how to handle this problem.

Also, since we are using typescript, we have a nice ability to use true OOP classes, encapsulation, inheritance and all other wonderful features. So, you may ask yourself how do I combine these awesome features when I write gulp tasks? How do I write my gulp tasks using classes? The answer is to use gulpclass package that allows you to write a beautiful class-based tasks without headache.

Before we start, you’ll need to install the required packages.

npm install typescript --save-dev
npm install gulpclass --save-dev

Next step is to create a typescript file where you’ll define gulp tasks. For example, let’s create a gulpclass.ts file.

Note that you can call it as you wish — for example you can call it gulpfile.ts, but in the case if you call it gulpfile.ts make sure that you are using outDir in typescript compiler options, because otherwise compiler will override gulpfile.js that you’ll need to create later.

In gulpclass.ts file, you need to create a class and put @Gulpclass decorator on it. Each method in class that you mark with @Task decorator will be a gulp task. For example, let's create a gulp class with one task that will clean everything inside of our “dist” directory. We are going to use npm’s del package, so you’ll need to install it:

npm install del --save-dev

Now let's put some code into gulpclass.ts file:

JavaScript
import {Gulpclass, Task} from "gulpclass/Decorators";

let gulp = require("gulp");
let del = require("del");

@Gulpclass()
export class Gulpfile {

    @Task()
    clean(cb: Function) {
        return del(["./dist/**"], cb);
    }
    
}

Right now, we created a gulp task named “clean” that will clean contents of the “dist” directory.

Next step is to create a gulpfile.js. Right, you still need this file because this is the only way gulp can understand that you have registered tasks. Remember that gulp itself is not working with typescript, it supports only JavaScript and gulp tasks written in JavaScript must be in gulpfile.js file.

But if gulp can only understand JavaScript, then how do we tell him about our tasks in gulpclass.ts? There is a trick. Just put this code into gulpfile.js:

JavaScript
eval(require("typescript").transpile(require("fs").readFileSync("./gulpclass.ts").toString()));

This trick does the following:

  • Reads the typescript code (containing gulp tasks) from typescript file
  • Tells typescript compiler to compile our typescript code read from the file
  • Typescript compiler returns us compiled JavaScript code in a string
  • We dynamically execute this compiled code in a current gulpfile.js file

And everything will work.

There are multiple ways in which you can make your typescript code work. This approach is useful because it allows you to run gulp tasks without pre-compiling typescript code. If you don’t understand the process — no worries, simply use this code in all your project’s gulpfile.js files.

Now you can simply run task:

gulp clean

Task will execute and clean “dist” directory contents. The name of the task is automatically read from the class’s method name.

If you want to specify a custom name, you can do it by specifying it in the first argument of the @Task decorator:

JavaScript
import {Gulpclass, Task} from "gulpclass/Decorators";

let gulp = require("gulp");
let del = require("del");

@Gulpclass()
export class Gulpfile {

    @Task("clean-dist")
    clean(cb: Function) {
        return del(["./dist/**"], cb);
    }

}

Now you can run task this way:

gulp clean-dist

Let's create more tasks and create a default task:

JavaScript
import {Gulpclass, Task} from "gulpclass/Decorators";

let gulp = require("gulp");
let del = require("del");

@Gulpclass()
export class Gulpfile {

    @Task("clean-dist")
    clean(cb: Function) {
        return del(["./dist/**"], cb);
    }
    @Task()
    copyScripts() {
        return gulp.src("./src/**/*.js")
            .pipe(gulp.dest("./dist/**/*.js"));
    }
    @Task()
    copyStyles() {
        return gulp.src("./src/**/*.css")
            .pipe(gulp.dest("./dist/**/*.css"));
    }
    @Task()
    default() {
        return ["copyScripts", "copyStyles"];
    }
}

Now 4 gulp tasks are available for you:

  • gulp?—?runs default task which copies scripts and styles in parallel
  • gulp clean-dist?—?cleans “dist” directory
  • gulp copyScripts?—?copies all scripts from “src” directory to “dist”
  • gulp copyStyles?—?copies all styles from “src” directory to “dist”

That's it. At this point, you should be available to use gulp as you usually do, but this time using Typescript instead of JavaScript.

Additionally, gulpclass provides you the ability to create tasks that can run in sequence. By default, when you are using gulp, it runs tasks in parallel, but sometimes when tasks depend on each other, you need to run tasks in sequence. To achieve this task, gulpclass is using run-sequence and encapsulates it in a simple decorator called @SequenceTask.

In our gulpclass.ts, we want to make first clean and only after clean is finished, we want to copy scripts and styles in parallel. Here is the updated code to achieve this:

JavaScript
import {Gulpclass, Task} from "gulpclass/Decorators";

let gulp = require("gulp");
let del = require("del");

@Gulpclass()
export class Gulpfile {

    @Task("clean-dist")
    clean(cb: Function) {
        return del(["./dist/**"], cb);
    }
    @Task()
    copyScripts() {
        return gulp.src("./src/**/*.js")
            .pipe(gulp.dest("./dist/**/*.js"));
    }
    @Task()
    copyStyles() {
        return gulp.src("./src/**/*.css")
            .pipe(gulp.dest("./dist/**/*.css"));
    }

   @SequenceTask()
   default() {
        return ["clean-dist", ["copyScripts", "copyStyles"]];
    }
}

Don’t hesitate to add github stars to gulpclass project and share with the community.

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication