Gulp Wiki

This article is part of my personal wiki where I write personal notes while I am learning new technologies. You are welcome to use it for your own learning!

Gulp.js is a javascript task automation library that helps you automate your web development workflow such as minification, bundling, adding vendor prefixes, CSS preprocessor compilation, testing, etc and make you more productive and efficient.

How Does it Work?

Gulp works like a pipeline of tasks, it reads source code files as a stream, submits them to different tasks that can either be non-destructive processes (linting, etc) or transformations (minification, bundling, etc) and generates the output of these processes as new files wherever you want.

You define these tasks in the gulp configuration file, usually gulpfile.js and execute them using the gulp CLI (command-line-interface), f.i. gulp test.

Gulp’s API

Gulp provides a minimal API which consists on the following elements:

gulp.task lets you define arbitrary tasks for gulp to perform

gulp.src lets you define which files a task is going to convert in a stream and operate over

gulp.dest lets you define where the output files are going to be placed

gulp.watch lets you define files to watch so that when these task change we can execute arbitrary tasks of our choice

Gulp tasks

gulp.task lets you define arbitrary tasks for gulp to perform. It consist of:

a name for the task

dependencies that are executed in parallel before the task is executed

// install gulp and save it as a development dependency
PS> npm install gulp --save-dev
// this will generate a package.json with the installed dependencies
// dev dependencies are used only during development
// normal dependencies are used when the app is in production (they are
// libraries related to the running of the application itself
// like angular, knockout, express, etc)

The next step is to create a gulpfile.js file which will contain all of our gulp task configurations. For instance:

Adding Conditional Functions

You can also add the gulp-if package to handle flags to enable/disable certain subtasks within a given task. For instance, if we only want to show the files being processed when we use the verbose flag we can install the package via npm:

Improving the Handling of Many Gulp Plugins with the Gulp-Load-Plugins Plugin

As you can see in the previous tasks, as soon as your gulp tasks start getting more complitated the number of plugins that you need to import in your gulpfile.js increases. In order to improve the management of your gulp plugins you can use the gulp-load-plugins package to load them automatically and lazily:

By separating the configuration setting from the configuration of the tasks themselves, you could reuse all tasks from project to project and then just change the configuration.

Using Gulp to Compile CSS from LESS/SASS/Stylus

CSS preprocesors like LESS, SASS or Stylus provide awesome features and functionality on top of CSS such as variables, mixins, utility functions, etc. Gulp provides a great workflow to compile your LESS (and SASS, Stylus, etc) files into vanilla CSS via the gulp-less package.

Using Dependency Tasks to Delete Previously Generated Files

As you saw when we took a look at the gulp.task API method you can define tasks to be executed before a given task is run, these tasks are call dependency tasks. For instance, we can define a cleanup tasks that clean css files before re-generating them from LESS files:

var gulp =require('gulp')
config =require('./gulp.config')(),
$ =require('gulp-load-plugins')({lazy:true});// clean css before running less-to-css compilation
gulp.task('css',['clean-css'],function(){return gulp.src(config.lessFiles).pipe($.less()).pipe($.autoprefix()).pipe(gulp.dest(config.temp));});
gulp.task('clean-css',function(done){var files = config.temp +'**/*.css';del(files, done);// done callback is called when the files are deleted// and then the 'css' task is notified that the 'clean-css' task has been completed
});

Now whenever we run gulp css the task clean-css will be run automatically. (Note that you need to install the del npm package with npm install del --save-dev).

Using Gulp to Compile LESS files into CSS whenever a LESS file is Modified

We can use the gulp.watch API method that we saw previously to monitor LESS files for changes and trigger the CSS handling pipeline:

gulp.task('watch-less',function(){// when less files change run the css pipelinereturn gulp.watch(config.lessFiles,['css']);});

Now you can start the watch-less task to monitor changes in less files and generate css:

PS> gulp watch-less

You can also include these gulp-watch calls inside other tasks and ensure that additional tasks are executed on file changes.

Using Gulp To Automatically Inject References to Js and CSS into Your HTML files

A front-end devops pipeline installs and generates javascript and css files. We can use gulp to automatically inject references to both the javascript third party libraries, javascript and css from our application into our HTML files. The wiredep library (to wire dependencies) and gulp-inject plugin are particularly good in performing this task.

PS> npm install wiredep gulp-inject --save-dev

In order to tell the plugin where files should be placed we used html comments like <!-- bower:js --> for instance. In a real world app we would use something like this:

Configuring Bower to Wire Dependencies After Installing New Libraries

Using Gulp to Create a Server to Run Your Dev Build

You can create a gulp task that makes use of the nodemon npm package to restart a node server when you make changes on the source code of your web application. There is a gulp-nodemon plugin that lets you run tasks when events are fired.

PS> npm install gulp-nodemon --save-dev

gulp.task('serve',[/* build all front-end files and wire dependencies */'inject'],function(){var nodeOptions ={
script: config.nodeServer,
delayTime:1,
env:{'PORT': process.env.PORT|| config.defaultPort,'NODE_ENV':'dev'},
watch:[config.server]// when any of the server files change the server will restart};return $.nodemon(nodeOptions).on('restart',['lint'],function(){})// restart after files in the server have changed (lint task is only executed on restart!).on('start',function(){})// start.on('crash',function(){})// crash.on('exit',function(){});// clean exit});

Using Gulp to Auto-magically Update Your Browser When You Change Files

You can use gulp and BrowserSync to keep not one but multiple browsers synched when you update your files (and even when you perform actions in each given browser like clicking, scrolling or filling a form). You can add BrowserSync to your project like any npm package:

Now you can run gulp serve and browser sync will be automatically activated. From the on it will monitor any changes in your front-end files and reload the page as needed. If you don’t want to run browser sync when serving your application you can use the --nosync switch.

Managing an Ever-increasing Number of Gulp Tasks With the Gulp-Task-Listing Plugin

You can use the gulp-task-listing plugin to create lists to easily visualize your existing gulp tasks.

Using Gulp to Complete the Build Pipeline and Serve a Production Version of Your App

So far we’ve been working with the development version of our application. When we want to take our app into production we want to minimize the number of assets that we are going to distribute over the wire to minimize the number of HTTP calls and bandwidth consumed. In order to do that we need to gather all our assets and submit them to bundling and minification processes. Gulp can helps us achieve that by combining all previous tasks with the gulp-useref plugin.

The gulp-useref plugin gathers annotated sections of html in comments and turns them into a single file. We can combine the previously used sections for wiredep and gulp-inject with an additional filename for gulp-useref to use:

gulp.task('build',['inject'],// inject wires all dependencies via wiredep (js,css), injects our app's js/css and also prepares the templateCachefunction(){var assets = $.useref.assets({searchPath:'./'});// gather all assets between comments and find them starting in the rootreturn gulp
.src(config.index)// grab the config.index file.pipe($.plumber())// error handler.pipe($.inject(
gulp.src(templaceCache,{read:false}),{
starttag:'<!-- inject:templates:js --> '// => inject inside this comment element})).pipe(assets)// grab all assets and bundle them into single js/css files (everything between build comment tags inside a single file).pipe(assets.restore())// restore to get index.html back.pipe($.useref())// update index.html with tags (link for css, script for js) pointing to bundled files.pipe(gulp.dest(config.build));// write everything to the build folder})// in summary// useref.assets() gathers all assets from the HTML comments// useref.assets.restore() restores the files to the stream (index.html for instance) and concatenate all assets within single files// useref() update files (index.html for instance) with links to the concatenated/bundled files

Using Gulp to Minify Your Front-End Assets

The gulp-csso plugin (CSS optimizer) let’s you optimize your CSS files (minification, mangling and other optimizations). The gulp-uglify plugin let’s you perform optimizations in your JS files (minification and mangling). And you can use the gulp-filter plugin to filter files, perform specific transformations on them and then continue handling all files within the build pipeline.

Using Gulp to Manage Assets Revisions (And Avoid Caching When New Versions of a Web App Are Released)

You can use the gulp-rev plugin to handle revisions of the files in your build pipeline. It will rename your files with revision hashes. And the gulp-rev-replace plugin to update your application references to point to the versioned assets (and not to the files with the original names).

You’ll need to configure your karma.conf.js properly to point to the code to be tested and the test specs themselves. After that you can run gulp test to initiate karma and run your unit tests. You can also use the node-notifier npm package to show you a toast when the process of running tests is complete.

You can also run your tests continuously by making use the startTest function above with options.singleRun = false:

Using Gulp with Other Client-Side Frameworks

Using Gulp and Angular to Cache Angular HTML Templates in the $templateCache

By default, angular will make an HTTP request to get any HTML template referenced by a directive or a route. The Angular $templateCache service allows us to define key value pairs of urls matching to templates and thus provide a cache and avoid the necessity of doing unnecessary HTTP requests.

You can use the gulp-angular-templatecache plugin to get all your Angular HTML templates and put them inside the $templateCache, and the gulp-minify-html plugin to minify them:

You can find more information about the gulp-angular-templatecache plugin on GitHub.

Beware of Mangling With Angular

Whenever you optimize your javascript code with mangling, the Angular DI infrastructure can be affected. Because mangling will try to use single letters as names for arguments, angular won’t be able to use convention over configuration to find your services, etc by name. In those ocassions you’ll get cryptic warnings in the browser. A way to get better DI information is to decorate your ng-app element with ng-strict-di. This will warn you whenever any angular component lacks the necessary annotations (see $inject property annotation).

Gulp 4

Run tasks in a explicit serial order: gulp.task('styles', gulp.series('clean-styles', styles))

Run tasks in parallel as before: gulp.task('assets', gulp.parallel('fonts', 'images', 'styles'))

Mix tasks in series and parallel: gulp.task('build', gulp.series(gulp.parallel(...), gulp.parallel(...)))

Built-in listing of tasks with: gulp --tasks or gulp --tasks-simple

Migrate From Gulp 3 to Gulp 4

Just substitute the task signatures from gulp.task(name[,dep],fn1) to gulp.task(name,fn2) where fn2 are sets of tasks that can run either in parallel or in serial form (either task names or functions). You’ll also need to notify serial tasks when they are done (by calling done()).

You can install the pre release version of gulp by running: npm install --save-dev git://github.com/gulpjs/gulp.git#4.0 and npm install -g git://github.com/gulpjs/gulp-cli.git#4.0.

Would you like to receive more articles like this one on programming, web development, JavaScript, Angular, developer productivity, tools, UX and even exclusive content like free versions of my books in your mailbox? Then sign up to my super duper awesome inner circle.

Did Ya Know I've Written Some Books?

I have! The JavaScript-mancy series is the lovechild of three of my passions: JavaScript, writing and Fantasy. In the pages of each one of the books of the series you’ll find a breadth of JavaScript knowledge, delivered with a humorous and casual style of writing and sprinkled with Fantasy at every turn.

They are the weirdest and quirkiest JavaScript books you'll ever find. There's nothing out there quite like it.