2/20/2015 - 12:10 AM

Gulp workflow for WordPress theme development

Gulp workflow for WordPress theme development

  "name": "Kickstart",
  "version": "1.0.0",
  "description": "Gulp packages for WP theme development",
  "main": "gulpfile.js",
  "author": "Tomaz Zaman <>",
  "devDependencies": {
    "gulp": "~3.8.11",
    "gulp-plumber": "~0.6.6",
    "gulp-watch": "~4.1.1",
    "gulp-livereload": "~3.7.0",
    "gulp-minify-css": "~0.4.6",
    "gulp-jshint": "~1.9.2",
    "jshint-stylish": "~1.0.0",
    "gulp-uglify": "~1.1.0",
    "gulp-rename": "~1.2.0",
    "gulp-notify": "~2.2.0",
    "gulp-include": "~1.1.1",
    "gulp-sass": "~1.3.3"
// Example if you have bower package scripts
//= include ../bower_components/magnific-popup/dist/jquery.magnific-popup.js

// Your scripts inside js/src directory
//= include ./src/customizer.js
//= include ./src/skip-link-focus-fix.js
// Load all the modules from package.json
var gulp = require( 'gulp' ),
  plumber = require( 'gulp-plumber' ),
  watch = require( 'gulp-watch' ),
  livereload = require( 'gulp-livereload' ),
  minifycss = require( 'gulp-minify-css' ),
  jshint = require( 'gulp-jshint' ),
  stylish = require( 'jshint-stylish' ),
  uglify = require( 'gulp-uglify' ),
  rename = require( 'gulp-rename' ),
  notify = require( 'gulp-notify' ),
  include = require( 'gulp-include' ),
  sass = require( 'gulp-sass' );

// Default error handler
var onError = function( err ) {
  console.log( 'An error occured:', err.message );

// Jshint outputs any kind of javascript problems you might have
// Only checks javascript files inside /src directory
gulp.task( 'jshint', function() {
  return gulp.src( './js/src/*.js' )
    .pipe( jshint( '.jshintrc' ) )
    .pipe( jshint.reporter( stylish ) )
    .pipe( jshint.reporter( 'fail' ) );

// Concatenates all files that it finds in the manifest
// and creates two versions: normal and minified.
// It's dependent on the jshint task to succeed.
gulp.task( 'scripts', ['jshint'], function() {
  return gulp.src( './js/manifest.js' )
    .pipe( include() )
    .pipe( rename( { basename: 'scripts' } ) )
    .pipe( gulp.dest( './js/dist' ) )
    // Normal done, time to create the minified javascript (scripts.min.js)
    // remove the following 3 lines if you don't want it
    .pipe( uglify() )
    .pipe( rename( { suffix: '.min' } ) )
    .pipe( gulp.dest( './js/dist' ) )
    .pipe( livereload() );
} );

// As with javascripts this task creates two files, the regular and
// the minified one. It automatically reloads browser as well.
gulp.task('scss', function() {
  return gulp.src('./scss/style.scss')
    .pipe( plumber( { errorHandler: onError } ) )
    .pipe( sass() )
    .pipe( gulp.dest( '.' ) )
    // Normal done, time to do minified (style.min.css)
    // remove the following 3 lines if you don't want it
    .pipe( minifycss() )
    .pipe( rename( { suffix: '.min' } ) )
    .pipe( gulp.dest( '.' ) )
    .pipe( livereload() );

// Start the livereload server and watch files for change
gulp.task( 'watch', function() {

  // don't listen to whole js folder, it'll create an infinite loop [ './js/**/*.js', '!./js/dist/*.js' ], [ 'scripts' ] ) './scss/**/*.scss', ['scss'] ); './**/*.php' ).on( 'change', function( file ) {
    // reload browser whenever any PHP file changes
    livereload.changed( file );
  } );
} );

gulp.task( 'default', ['watch'], function() {
 // Does nothing in this task, just triggers the dependent 'watch'
} );

Gulp workflow for WordPress theme development


In order for Livereload to work, you need a Firefox or Chrome extension as Gulp doesn't inset it automatically. Alternatively, you can also manually put the livereload script in footer.php, just make sure to insert it only on development environment:

<script>document.write('<script src="http://' + ( || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1"></' + 'script>')</script>

There's more documentation on Livereload here.

You also need node.js installed (it comes with npm, which is it's package manager). If you want to install frontend packages via Bower, install that too, but it's not a requirement.

This workflow is built for MacOS, but should work in any operating system where you can get node.js to run.


There are 4 main tasks defined in this workflow, watch, jshint, scripts and scss and they all run depending on which file you change. If jshint fails for some reason then scripts is not being run (because it would produce poor javascript).

In every case both scripts and scss produce two versions of final files, a normal, concatenated one and a minified/uglified one.

File structure

You'll need to following file strucutre (an example), but it's not mandatory, change the gulpfile.js if your paths differ

  • The first file is an example of where all your javascript source files should be, in /js/src/
  • The manifest file just loads all those files from the src folder and, if you use Bower, from the bower_components directory
  • style.scss loads all the other stylesheets in

Once you start developing (and Gulp does it's job), you'll end up with the following files you can enqueue in your functions.php:

/js/dist/scripts.min.js # Uglified, production ready
/style.min.css # Minified, production ready

Running Gulp

Once you install this workflow, just run $ gulp inside your theme folder and it'll automatically start to listen to any changes inside the folder and reload the browser automatically.