Unfreeze Your Brain

with Gulp and Slush

Why streams?

What is a task runner?

What is a scaffold?

Why Gulp?

Why Slush?


Whats a task runner?

Change the way you work

  • Concat, write, delete files
  • Backbone of a modern build system
  • File/code analysis
  • Preprocessors
  • Postprocessors

On in a word...



Much task.

Very Choice.

Why Gulp?

Whats so special?

(mostly) Objectively speaking

  • Steam Based
  • Sanitary Plugin Ecosystem
  • Power of Npm
  • Modular, sharp-tooled
  • Fast
  • Envy of your friends.

But also...

and in my opinion...



I know what some of you might be thinking...

Hey Wait!

We're a C# Shop!

..we have NUGET



and like. microsofty..stuff...

Its cool...

(Your home-slice Scott 'Rocket Punch', H, just chillin wearin' a gulp shirt.)

  • Gulp is fore everybody :)
  • Even in non js stacks, communities are requesting it!
  • Your frontend Coders will LOVE it
  • Y0u need client Devops
  • Its not 2006 anymore
  • But seriously: You really need those devops

So if you are in a c# environment.. 

(as many of you may be)

  1. TRX- Task Runner Explorer
  2. NPM/NBower Package Intellisense
  3. Optional Grunt Launcher

Trust your boy, Scott...Get the full scoop here:


Or you can do what the rest of us do...

npm install -g gulp


"We should have some ways of connecting programs like garden hose--screw in
another segment when it becomes necessary to massage data in
another way. This is the way of IO also."

Doug Mcllroy, 1964

  • IO is async
  • .pipe()
  • Streams are solid architectural foundation
    • (earlier days of unix)
  • pluggable, modular, simple


Read the FANTASTIC Manual



Substack wrote this, and its good read even out of the context of gulp, honestly.

npm install -g stream-handbook

Big Whoop.

What can I



More like



you do.


This is how you REALLY get it DONE

0. require gulp

1. require plugins

2. declare tasks (more on that later)

3. task order/separate from tasks (queue)

4. call tasks.

var gulp = require('gulp'),
    concat = require('gulp-concat'),
    minify = require('gulp-minify');

var scriptFiles = './src/**/*.js';

function build(){
    .pipe(concat({fileName: "funky-town.js"})

gulp.task('build', build);

A simple, yet comon scenario.


gulp build
gulp.task('build', build);

If this is your JS file:

This is what you type on the command line:

And then?...

A simple, yet comon scenario.


var gulp = require('gulp'),
    concat = require('gulp-concat'),
    minify = require('gulp-minify');

var scriptFiles = './src/**/*.js';

function build(){
    .pipe(concat({fileName: "funky-town.js"})

gulp.task('build', build);

1. Glob goes in

2. pipepipe,pipe,

3. ...files go out.

"you can't explain that"

This is only the surface.

  • Automated Tests
  • File Watchers
  • Complexity Analysis (Come see my talk tomorrow)
  • Common JS Build (browserify webpack)
  • Interact with git
  • Integrate with your browser or OS (gulp-app)


Gulp is simple.

Just remember:

"I got 5 on it"

The 5

Noble Tasks

.task('name', taskFn)


.watch(glob, taskFn)



Flow Control

How To

How To


3 ways to handle a task

  • Return nothing, like firing an event
  • Return the stream
  • Return a callback

Returning nothing is probably not what you want, because you might introduce

Race Conditions


Return a stream

Return a callback

var gulp = require('gulp');
var coveralls = require('gulp-coveralls');

function lcov() {
  return gulp

gulp.task('coveralls', lcov)
var gulp = require('gulp');
var istanbul = require('gulp-istanbul');
var mocha = require('gulp-mocha');
var gutil = require('gulp-util');

function test(cb) {
  function runner() {
    return gulp
      .on('end', cb);

    .on('finish', runner)
    .on('error', gutil.log);

gulp.task('test', test);
  • gulp-only stuff
  • simple: just return the task
  • the main "currency" of gulp
  • going outside gulp
  • async stuff
  • freedom

And then?

You can sequence these larger gestures into task chains!


They naturally run async, but you can use plugins to handle things further.

  • Vanilla parallel task chains
  • Sequences chains with run-sequence
  • merging streams!

Basic Gulp task chain :


gulp.task('lots-of-stuff', ['task-1', 'task-2', 'task-3']);


  var gulp = require('gulp'),
      runSequence = require('run-sequence');

  function runAllTasks(cb) {
    runSequence('pretasks', 'posttask', cb);
  gulp.task('pretasks', ['clean']);
  gulp.task('posttask', ['build', 'lint', 'test']);
  gulp.task('default', runAllTasks);
// npm install --save-dev gulp merge-stream

var gulp = require('gulp');
var merge = require('merge-stream');

gulp.task('test', function() {
  var bootstrap = gulp.src('bootstrap/js/*.js')

  var jquery = gulp.src('jquery.cookie/jquery.cookie.js')

  return merge(bootstrap, jquery);

Combining Streams

gulp merge-stream


Scaffolding made simple.



Ask questions

Do stuff

And that's Slush.

Scaffolding Rocks

  • Kickstart new project
  • Standardize practices
  • Increase productivity
  • and of course...


Did I mention?

Hey, hold up!

What about that other scaffolding system?

I used that a few times and my scaffolding needs already taken care of


why do I even need this???

Why you might choose slush

  • More separate concerns
  • Plugin ecosystem
  • Generators/subgenerators = TASKS
  • Simpler system
  • No need to introduce additional
npm install -g slush
npm install -g gulp
npm install -g slush-generator
slush generator

Easy to use

Easy to make

1. think of questions

2. make a slushfile

3. call your generator

A basic slush task

// your callback

function callback(answers){
      .src(__dirname + '/templates/**')
      .on('end', function () {
//every inquirer statement is made like this.
inquirer.prompt( questions, callback )

Ask questions

Do stuff

What do questions look like?

var prompts = [{
  name: 'appName',
  message: 'What is the name of your project?',
  default: defaults.appName
  }, {
  name: 'appDescription',
  message: 'What is the description?'
  }, {
  name: 'appVersion',
  message: 'What is the version of your project?',
  default: '0.1.0'
  }, {
  name: 'authorName',
  message: 'What is the author name?',
  default: defaults.authorName
  }, {
  name: 'authorEmail',
  message: 'What is the author email?',
  default: defaults.authorEmail
  }, {
  name: 'userName',
  message: 'What is the github username?',
  default: defaults.userName
  }, {
  type: 'confirm',
  name: 'moveon',
  message: 'Continue?'
? What is the name of your project? ballz
? What is the description? Some description
? What is the version of your project? 6.6.6
? What is the author name? Jesse Harlin
? What is the author email? harlinjesse@gmail.com
? What is the github username? Jesse_Harlin
? Continue? Yes
  appName: 'ballz',
  appDescription: 'Some description',
  appVersion: '6.6.6',
  authorName: 'Jesse Harlin',
  authorEmail: 'harlinjesse@gmail.com',
  userName: 'Jesse_Harlin',
  moveon: true



You're darn tootin it will!

  • Mock responses from inquirer with fixture
  • Mock file writing with mock-gulp-dest
  • Mock environmental things with rewire

Test every little bit.

'use strict';
var inquirer = require('inquirer');

function mockPrompt(answers) {
  function assignAnswer(prompt) {
    if (!(prompt.name in answers)) {
      answers[prompt.name] = prompt.default;
  function inquirerPrompt(prompts, done) {
  inquirer.prompt = inquirerPrompt;

module.exports = mockPrompt;

Inquirer Fixture

var mockPrompt = require('./inquirer-prompt-fixture');
var chai = require('chai'), //chai for assertion
  gulp = require('gulp'), 
  mockGulpDest = require('mock-gulp-dest')(gulp), //here is our dest stub
  expect = chai.expect; //I use expect, but I dont expect(you).to.also()

var mockPrompt = require('./inquirer-prompt-fixture'); //this is to mock inquirer

require('../slushfile'); //and the thing we are testing

describe('your awesome module!!!', function () {
  describe('taskname', function () {
    beforeEach(function () { 
        appName: 'test-app',
        userName: 'the-simian',
        authorName: 'Fancypants Harlin',
        authorEmail: 'derp@derp.derp',
        appDescription: 'some description',
        moveon: true
    it('should make a readme', function (done) {
      function assertDirectories() {
        .once('task_stop', assertDirectories); //here's the tricky part....




Unfreeze Your Brain

By Jesse Harlin

Unfreeze Your Brain

  • 3,323