Getting Started with Javascript Gulp Task RunnerJavascripts Gulp Task Runner helps you be productive by automating build tasks like SCSS, image processing and minificaion.
Gulp is a Javascript Task Runner which automates most, if not all, the tedious tasks web developers traditionally do. Gulp lets you automate tasks such as bundling and minifying libraries and stylesheets, Less/Sass to CSS compilation, compressing and optimising images, copying modified files to an output directory and it can even reload the browser window when files are changed.
The Gulp Task Runner Workflow
Gulp works using tasks. Each task takes in a set of files which are loaded into the Gulp stream to be processed. Each file is then processed and sent to the destination file. A simple input, process, output workflow.
Tasks can also be chained together so that a file can be processed, then another action can be performed before it is written to the output.
Installing Gulp Task Runner via NPM and Grunt
Grunt can easily be installed using the Node.js Package Manager. If you do not have it installed already, head over to the npm website where you can download and install it.
Gulp is installed globally, and also into your project. Global installation is only required once.
npm install gulp -g
Next, we need to change the directory to your project folder and install gulp on the project. This will install the modules and packages we will be using as well as create the default project settings.
If you are creating a new project you will first need to run the node init command to create files and folder structures.
cd webproject1
npm init
Then you can install gulp into the project.
npm install gulp --save-dev
Installing Gulp Task Runner Plugins
Next, we need to install a few plugins which we will be using in our tasks. Here I will just install some of the basic and most frequently used plugins. You can find a list of all the available plugins for Gulp here.
- Sass compile (gulp-ruby-sass)
- Autoprefixer (gulp-autoprefixer)
- Minify CSS (gulp-cssnano)
- JSHint (gulp-jshint)
- Concatenation (gulp-concat)
- Uglify (gulp-uglify)
- Compress images (gulp-imagemin)
- LiveReload (gulp-livereload)
- Caching of images so only changed images are compressed (gulp-cache)
- Notify of changes (gulp-notify)
- Minify HTML (gulp-htmlmin)
- Clean files for a clean build (del)
These can all be installed on the command line using npm
.
npm install gulp-ruby-sass gulp-autoprefixer gulp-cssnano jshint gulp-jshint gulp-concat gulp-uglify gulp-imagemin gulp-notify gulp-rename gulp-livereload gulp-cache gulp-htmlmin del --save-dev
Creating a gulpfile to Manage Tasks
Next, we need to create a gulpfile.js
and load in the plugins. The gulpfile is a plain javascript file.
var gulp = require('gulp'),
sass = require('gulp-ruby-sass'),
autoprefixer = require('gulp-autoprefixer'),
cssnano = require('gulp-cssnano'),
jshint = require('gulp-jshint'),
uglify = require('gulp-uglify'),
imagemin = require('gulp-imagemin'),
rename = require('gulp-rename'),
concat = require('gulp-concat'),
notify = require('gulp-notify'),
cache = require('gulp-cache'),
livereload = require('gulp-livereload'),
htmlmin = require('gulp-htmlmin'),
del = require('del');
This is a pretty standard header for the file, as you can see it simply loads in the plugin files. Feel free to change this accordingly. If you don't intend on using a plugin you can comment it out or delete the line.
Windows users will also need to install Ruby as well as the sass gem.
Creating Tasks in Gulp Task Runner
Next, we need to create a few tasks, since that is the whole point of the exercise. A Task takes in a source file, runs an action on the contents of the file then outputs the result, either to another plugin or to a file.
We must first create a default task in which gulp runs automatically. This task will launch all the other tasks we define.
In this example, we will transform a source SCSS stylesheet into a CSS file for distribution.
This code goes into the gulpfile.js
after the plugins.
gulp.task('default', function() {
gulp.start('styles');
});
I'm going to create a very basic SCSS file in src/styles/main.scss
with the following contents.
$font-stack: Helvetica, sans-serif;
$primary-color: #333;
body {
font: 100% $font-stack;
color: $primary-color;
}
Next, I'm going to create the task to transform this into CSS so we can upload it to our web server.
This goes in after the default task.
gulp.task('styles', function() {
return sass('src/styles/main.scss', { style: 'expanded' })
.pipe(gulp.dest('dist/assets/css'));
});
All this is going to do is transform the SCSS into CSS.
We can run gulp by simply running the command gulp
in the command line in the project folder.
Once it has been completed, the folder dist/assets/css
should contain a file called main.css. This will have pure CSS.
body {
font: 100% Helvetica, sans-serif;
color: #333;
}
Now we will leverage some of the power of gulp and chain some plugins together to further transform this file. We will automatically add vendor prefixes to CSS properties, minify the output, rename the output file and show a message in the console when the command is complete. This is useful when lots of tasks are to be run so you know what is being run.
We can modify our styles task to include the following:
gulp.task('styles', function() {
return sass('src/styles/main.scss', { style: 'expanded' })
.pipe(autoprefixer('last 2 version'))
.pipe(gulp.dest('dist/assets/css'))
.pipe(rename({suffix: '.min'}))
.pipe(cssnano())
.pipe(gulp.dest('dist/assets/css'))
.pipe(notify({ message: 'Styles task complete' }));
});
Now when we run gulp, we will see a main.min.css has been generated, with the minified CSS contents.
body{font:100% Helvetica,sans-serif;color:#333}
Now you may have noticed that we have a main.css and a main.min.css in the dist folder. It would be great if we could clear out old files each time gulp is run, so let's create a task for that.
gulp.task('clean', function() {
return del(['dist/assets/css', 'dist/assets/js', 'dist/assets/img']);
});
Next, we need to modify the default task to include a clean task. We will add clean as a dependency since we want it to always run before anything else. This is done by adding an array as the second argument.
gulp.task('default', ['clean'], function() {
gulp.start('styles');
});
Now we can add a task to do the same thing for some Javascript. This will take all the javascript files in all subfolders, combine them into one file, minify, run jshint
to validate the javascript code and finally write out main.js (unminifed) and main.min.js (minified) to the dest folder.
gulp.task('scripts', function() {
return gulp.src('src/scripts/**/*.js')
.pipe(jshint('.jshintrc'))
.pipe(jshint.reporter('default'))
.pipe(concat('main.js'))
.pipe(gulp.dest('dist/assets/js'))
.pipe(rename({suffix: '.min'}))
.pipe(uglify())
.pipe(gulp.dest('dist/assets/js'))
.pipe(notify({ message: 'Scripts task complete' }));
});
Again this task is added to the default task runner.
gulp.task('default', ['clean'], function() {
gulp.start('styles', 'scripts');
});
The next task to add will be to optimise and copy images from our source folder to the assets folder.
gulp.task('images', function() {
return gulp.src('src/images/**/*')
.pipe(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true }))
.pipe(gulp.dest('dist/assets/img'))
.pipe(notify({ message: 'Images task complete' }));
});
This is OK if there are only a small number of images, but if your site has many images it is better to cache the results so that only modified images get reprocessed. This saves a lot of time during the build process. Again this task will take all images in all subfolders and output them to the dist/assets/img
folder.
gulp.task('images', function() {
return gulp.src('src/images/**/*')
.pipe(cache(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true })))
.pipe(gulp.dest('dist/assets/img'))
.pipe(notify({ message: 'Images task complete' }));
});
Finally, no website would be complete without HTML, so we're going to take our HTML pages, minify them and copy them to the dist folder.
gulp.task('minify', function() {
return gulp.src('src/*.html')
.pipe(htmlmin({collapseWhitespace: true}))
.pipe(gulp.dest('dist'));
});
Gulp Task Runner and Live Reload Plugin
One of the most powerful features of Gulp Task Runner is the ability to add file watchers. These will trigger when files are changed and automatically rebuild the output files and also refresh the browser window, meaning you change the code, save the file and automatically the browser refreshes with the new code.
To configure this we need to add a new task for a watch and install the browser plugin from LiveReload .
Download for Firefox Download for Chrome
gulp.task('watch', function() {
gulp.watch('src/styles/**/*.scss', ['styles']);
gulp.watch('src/scripts/**/*.js', ['scripts']);
gulp.watch('src/images/**/*', ['images']);
gulp.watch('src/*.html', ['minify']);
livereload.listen();
gulp.watch(['dist/**']).on('change', livereload.changed);
});
This will watch for any changes to styles, scripts, images and HTML and fire off the relevant task. If a file changes in the dist folder then it will fire off the browser reload.
To run the gulp watcher, just enter this command in the project folder.
gulp watch
Full Practical Example of Gulp Javascript Task Runner
Below is the full gulpfile.js
which I use for most of my web templates. It should be more than enough to get you started.
var gulp = require('gulp'),
sass = require('gulp-ruby-sass'),
autoprefixer = require('gulp-autoprefixer'),
cssnano = require('gulp-cssnano'),
jshint = require('gulp-jshint'),
uglify = require('gulp-uglify'),
imagemin = require('gulp-imagemin'),
rename = require('gulp-rename'),
concat = require('gulp-concat'),
notify = require('gulp-notify'),
cache = require('gulp-cache'),
htmlmin = require('gulp-htmlmin'),
livereload = require('gulp-livereload'),
del = require('del');
gulp.task('default', ['clean'], function() {
gulp.start('styles', 'scripts', 'images', 'minify');
});
gulp.task('watch', function() {
gulp.watch('src/styles/**/*.scss', ['styles']);
gulp.watch('src/scripts/**/*.js', ['scripts']);
gulp.watch('src/images/**/*', ['images']);
gulp.watch('src/*.html', ['minify']);
livereload.listen();
gulp.watch(['dist/**']).on('change', livereload.changed);
});
gulp.task('clean', function() {
return del(['dist/assets/css', 'dist/assets/js', 'dist/assets/img']);
});
gulp.task('styles', function() {
return sass('src/styles/main.scss', { style: 'expanded' })
.pipe(autoprefixer('last 2 version'))
.pipe(gulp.dest('dist/assets/css'))
.pipe(rename({suffix: '.min'}))
.pipe(cssnano())
.pipe(gulp.dest('dist/assets/css'))
.pipe(notify({ message: 'Styles task complete' }));
});
gulp.task('scripts', function() {
return gulp.src('src/scripts/**/*.js')
.pipe(jshint('.jshintrc'))
.pipe(jshint.reporter('default'))
.pipe(concat('main.js'))
.pipe(gulp.dest('dist/assets/js'))
.pipe(rename({suffix: '.min'}))
.pipe(uglify())
.pipe(gulp.dest('dist/assets/js'))
.pipe(notify({ message: 'Scripts task complete' }));
});
gulp.task('images', function() {
return gulp.src('src/images/**/*')
.pipe(cache(imagemin({ optimizationLevel: 5, progressive: true, interlaced: true })))
.pipe(gulp.dest('dist/assets/img'))
.pipe(notify({ message: 'Images task complete' }));
});
gulp.task('minify', function() {
return gulp.src('src/*.html')
.pipe(htmlmin({collapseWhitespace: true}))
.pipe(gulp.dest('dist'))
.pipe(notify({ message: 'Minify task complete' }));
});
Do you use Gulp? Have you any helpful tasks we can add to the collection? Do you use another task runner? Let us know in the comments below!