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:
Validate your JavaScript using JSHint.
Concatenate your script into a single file.
Save the concatenated file as app.js.
Reload the web browser so you can see the changes.
Minify the javascript.
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:
vargulp=require('gulp'),
hint=require('gulp-jshint'),
concat=require('gulp-concat');
gulp.task('js',function(){
returngulp.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:
vargulp=require('gulp'),
jshint=require('gulp-jshint');
gulp.task('assets:js',function(){
returngulp.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
npminstallgulp-jshint
Now create a gulpfile containing something like the following:
vargulp=require('gulp'),
jshint=require('gulp-jshint');
gulp.task('js',function(){
returngulp.src('js/**/*.js')
.pipe(jshint())
.pipe(jshint.reporter('default'))
}
Now run gulp js to execute the task:
gulpjs
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.
vargulp=require('gulp'),
concat=require('gulp-concat'),
uglify=require('gulp-uglify');
gulp.task('js',function(){
returngulp.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.
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:
articlea{
color:red;
}
articlestrong{
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
Create a $header_colour variable. Use it to set the background-color of your header.
Create a $font_size variable (12px) and a $font_scale variable (1.5).
Set the font-size to be the $font_size variable.
Set the h2 font-size to be $font_size * $font_scale
Set the h1 font-size to be $font_size * $font_scale ** 2
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"
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.
npminstalljade
Here's a gulpfile:
vargulp=require('gulp');
varjade=require('gulp-jade');
vargutil=require('gulp-util');
varcomponents={
jade:'./jade/**/*.jade',
out:'./build'
}
gulp.task('jade',function(){
returngulp.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:
<ahref="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:
npminstalljade
Now we can compile our template. This gives us a template function:
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(){
returngulp.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.
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:
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.