Gulp

Gulp is a development automation tool. It allows us to pipe files through a succession of pipline stages. Each stage can transform the files in the pipe.

For example, we might a pipeline to:

  1. Validate your JavaScript using JSHint.
  2. Concatenate your script into a single file.
  3. Save the concatenated file as app.js.
  4. Reload the web browser so you can see the changes.
  5. Minify the javascript.
  6. Save the minified code again as app.min.js.

Gulp streams

Gulp has a concept of streams. A stream is a set of files that can be transformed.

We create a stream using gulp.src, then pipe it through different functions which can transform the stream in a variety of ways. We can optionally pipe our stream back out onto the filesystem at any point using gulp.dest.

We use gulp for:

  • Validation
  • Compilation
  • Concatenation
  • Reformatting
  • Renaming
  • Wrapping content
  • Anything else we can think of…

The Gulpfile

We configure gulp using a file called gulpfile.js. By convention, this lives in our project root. Our gulpfile contains a set of tasks that we would like to automate.

Our gulpfile might be tiny, it might only run jsLint on save, or it might be huge, rebuilding our entire project including HTML, JavaScript, CSS and images.

A simple gulpfile to lint concatenate and save all the JavaScript in a project might look like this:

var gulp = require('gulp'),
hint = require('gulp-jshint'),
concat = require('gulp-concat');
gulp.task('js', function () {
return gulp.src('**/*.js')
.pipe(hint())
.on('error', gutil.log)
.pipe(concat('app.js'))
.pipe(gulp.dest('build'));
});

Gulp modules

We extend the capabilities of Gulp using modules, which are installed using npm. Here are some useful ones:

  • jshint - JavaScript validation
  • sass - CSS precompilation
  • Uglify - JavaScript minification
  • Concat - Script concatenation
  • Autoprefixer - Automatically add vendor prefixes to CSS
  • Header - Adds a header to the file
  • Size - Outputs the size of a minified file

Validating code

A common requirement is to validate our JavaScript. We can do this with a simple Gulp task:

var gulp = require('gulp'),
jshint = require('gulp-jshint');
gulp.task('assets:js', function () {
return gulp.src(components.js)
.pipe(jshint())
.pipe(jshint.reporter('default'))
}

We execute this task with:

gulp assets:js

Automatic execution

We can tell gulp to watch our filesystem for changes, and execute a task whenever a file is modified.

gulp.task('watch', function() {
gulp.watch(components.js, ['assets:js']);

Now we might create a default gulp task:

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

We can now set our gulp task running simply by typing gulp at a command line.

gulp

Exercise - JSHint

Install Gulp and the gulp-cli using npm. Note that currently gulp has to be installed locally in your project, so we omit the -g flag.

npm install gulp
npm install gulp-cli -g

Test your installation:

gulp --version

Now we're going to set up gulp to validate our javascript.

first install the gulp-jshint dependency

npm install gulp-jshint

Now create a gulpfile containing something like the following:

var gulp = require('gulp'),
jshint = require('gulp-jshint');
gulp.task('js', function () {
return gulp.src('js/**/*.js')
.pipe(jshint())
.pipe(jshint.reporter('default'))
}

Now run gulp js to execute the task:

gulp js

Any errors? You may need to introduce an error to see the effect.

Set up Gulp to automatically validate the code in your node server. When you save the file, it should give you an error if you have made a mistake.

Piping out a stream

We can make transformations to our code right in the stream, and then at any point, pipe it out into a file. We might pipe it out more than once if we want to.

var gulp = require('gulp'),
concat = require('gulp-concat'),
uglify = require('gulp-uglify');
gulp.task('js', function () {
return gulp.src('./js/**/*.js')
.pipe(concat('app.js'))
.pipe(gulp.dest('./build/js'))
.pipe(rename('app.min.js'))
.pipe(uglify())
.pipe(gulp.dest('./build/js'))
});

Exercise - Pipe out

Try to get the above running. Make a gulp task that will concatenate and minify your JavaScript.

Remember you will need to npm install gulp-concat and gulp-uglify.

Now integrate this with the lint exercise above. Make a task that will first lint your code, then concat and minify.

Angular Exercise - ngAnnotate

ngAnnotate is a project that will convert Angular round brace injectors into minification safe square brace injectors.

Here's the gulp task: https://www.npmjs.com/package/gulp-ng-annotate

Try to integrate ngAnnotate into your js build process.

Exercise - Header

You might wish to mark your generated files as such so that future coders don't try to edit them directly. We can use gulp-header for this.

https://www.npmjs.com/package/gulp-header

Use gulp-header to add a header to your concatenated js file, something like this:

"Generated by `gulp js`
// Do not modify
"

Exercise - Validate your gulpfile

Slightly meta this one. Use the gulp-jsonlint package to automatically validate your gulpfile.

Watch & Reload

We can use gulp to watch a set of files and automatically run a task when any of them change.

For example we might watch our js directory and run the js task.

gulp.task('watch', function() {
gulp.watch('./js/**/*.js', ['js']);
});

We can then start our watchers using gulp watch.

Combination tasks

We can make a task depend on other tasks. This can help us split our tasks up into smaller pieces, like so:

gulp.task('build', [
'js',
'sass',
'lib',
]);

Now we run:

gulp build

and this will run all the tasks.

Default task

We can set a default task that will be run when we call gulp:

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

Now we only need to run:

gulp

to build and turn on the watchers.

Livereload

Live reload will automatically reload your web page when a task completes. It comes in two parts:

  • The gulp-livereload plugin that manages the livereload server
  • A Chrome plugin that listens for a reload

If you install both of these you can chain live-reload into your tasks and have gulp reload your browser automatically on file change.

This works extremely well when multi-screening.

gulp.task('assets:js', function () {
return gulp.src('./js/**/*.js')
.pipe(concat('app.js'))
.pipe(gulp.dest('./build'))
.pipe(livereload());
});

Exercise - Livereload

  • Create a gulp watch task which watches your js.
  • Create a default task so you can just call gulp to start watching.
  • integrate live-reload

SASS

SASS is Syntactically Awesome StyleSheets. It's similar to LESS, and most of what we learn here will also apply to LESS.

Refer to the documentation here: http://sass-lang.com/documentation/file.SASS_REFERENCE.html

CSS is valid SASS

One of the great things about SASS is that any CSS file is also valid SASS, so you can start using it right away.

a {
color:#f00;
}

Variables

We can define variables in sass, like so:

$red: #f00;
a {
color:$red;
}

Functions

SASS comes with a set of built in functions that we can use to transform variables, like so:

$red: #f00;
a {
color:darken($red, 30%);
}
a:hover {
color:lighten($red, 30%);
}

Maths

We can perform maths functions in our SASS to generate sizes. Here is a simple 2 column layout with a gutter.

$desktop: 1000px;
$gutter: 20px;
body {
width: $desktop;
}
article {
width: $desktop / 3 * 2 - $gutter;
float:left;
}
aside {
width: $desktop / 3 - $gutter;
float:right;
}

Nesting

We can nest our sass like so:

article {
a {
color: red;
}
strong {
font-weight: normal;
}
}

This will generate something like the following:

article a {
color: red;
}
article strong {
font-weight: normal;
}

Exercise - Gulp-sass

Use gulp-sass to compile sass. Have a look at the gulp-sass project and try to create a sass task to compile your sass. You may wish to concat it first.

Exercise - Nested Sass

Write nested queries to style the header with a horizontal nav bar, nicely positioned h1, and pretty background colour.

Exercise - Variables

  1. Create a $header_colour variable. Use it to set the background-color of your header.
  2. Create a $font_size variable (12px) and a $font_scale variable (1.5).
  3. Set the font-size to be the $font_size variable.
  4. Set the h2 font-size to be $font_size * $font_scale
  5. Set the h1 font-size to be $font_size * $font_scale ** 2
  6. Adjust the $font_size. See how everything updates. Woot!

Further Exercise - Mixins

Create a button mixin which sets a width, a height, a background-color, a padding and display:inline-block. Apply it to input type="submit", button, and a class="button"

Downloads

Example - Dropbox

Jade

Jade is an HTML templating language that's extremely popular in Node circles. You make fewer keystrokes to get the same result, which makes you a more productive coder. This is very Node.

First Install with NPM

To use Jade you must install the package. Do this with NPM.

npm install jade

Here's a gulpfile:

var gulp = require('gulp');
var jade = require('gulp-jade');
var gutil = require('gulp-util');
var components = {
jade: './jade/**/*.jade',
out: './build'
}
gulp.task('jade', function() {
return gulp.src(components.jade)
.pipe(jade({pretty:true}))
.on('error', gutil.log)
.pipe(gulp.dest(components.out));
})
gulp.task('watch', function() {
gulp.watch(components.jade, ['jade']);
});

Elements

The first word on any line is the html element:

h1 Hello there

Compiles to:

<h1>Hello there</h1>

Nesting elements

We can nest elements inside each other using indentation:

article
h1 Hello
p Hey!

Compiles to:

<article>
<h1>Hello</h1>
<p>Hey!</h1>
</article>

Attributes

We can create attributes:

a(href='http://www.lolcats.com/') LOL cats

Compiles to:

<a href="http://www.lolcats.com/">Lol cats</a>

Variables

We can include variables in our template using an equals sign like this if we just have one value:

article
h1= titleContent

or using curly brace interpolation like this if we want to embed content into text:

html
head
title myWebsite.com - #{titleContent}

Compiling Jade

We con compile Jade manually using the jade package. First we install it with npm:

npm install jade

Now we can compile our template. This gives us a template function:

var jade = require('jade');
var template = jade.compile('h1 hello #{name}');

Or from a file:

var template = jade.compileFile('./path/to/template.jade');

Finally we can compile our template into HTML, passing it an object full of include variables, like so:

template({name: "Davie Skitch Mulldoon"});

Jade with Gulp

We can use gulp to automatically compile jade into static html templates.

We use the gulp-jade package

gulp.task('assets:templateCache', function () {
return gulp.src('../jade/**/*.jade')
.pipe(jade({basedir: __dirname}))
.on('error', gutil.log)
.pipe(gulp.dest('../build/templates'));
});

Angular Exercise

Create a gulp task to automatically compile a folder full of jade into a folder full of html.

Extension

Try to integrate gulp-template-cache to generate an angular template module from a folder full of jade.

Yo Yeoman

Yeoman is a code generator. You can use it to bootstrap an entire project, or you can use subgenerators to make individual units of code, perhaps a single controller, JavaScript file or view.

You can read more about Yeoman here: http://yeoman.io/

In this section we're going to use the Yeoman Express generator to build an Express project.

Installing Yo

First install Yeoman. As you would expect, we install it with npm. We're going to use the -g global flag because we want to call yeoman from outside of a project.

npm install -g yo

Installing a generator

Next we'll need a generator. You can find a list of them here: yeoman.io/generators/. Yeoman generators all start with the word generator, for example express-generator or angular-generator.

Create a project directory to hold your code. Now install the express generator. We'll make this local to our project in case we need a sub-generator again later:

mkdir myproject
cd myproject
npm install generator-express

Build your Express application

Create an app using the express generator. At a command line type:

yo

Choose the Express generator. Accept the defaults. Choose Jade for templates. As a build tool, choose gulp (or grunt if you prefer an old friend). For CSS choose SASS. Optionally choose MVC.

Using SASS

If you choose SASS you'll probably need the compass Ruby gem. Install Ruby if you don't already have it. For Windows this is a double click install:

http://rubyinstaller.org/downloads/

test if from a terminal using:

ruby -v

Now install the gem. From a terminal:

gem install compass

Starting the server

We start the server using gulp:

gulp

View in the browser

We can now visit http://localhost:3000 to view our app in all it's glory.

Exercise - Create an Express scaffold with Yeoman

Use yo to generate a simple express site. Fire it up with by running Gulp.

  • Try to add another route

Exercise - Gulp

Gulp is watching your project. Every time you change a view file, your browser will refresh.

Make a change to the SASS file and watch the browser reload automatically. This is a massive productivity gain, especially with multiple screens.

You ay need to install the livereload Chrome plugin.

Exercise - Modify a view

Look in your views folder. You'll find a file called layout.jade. Jade is an html preprocessor with semantic indentation. You don't need to use angled braces or close your tags, it handles that for you.

Read more on Jade here: http://jade-lang.com/

  1. Try to create a header and footer in your layout.jade file that will appear on every page.
  2. Create an about us page url with content.