Gulp setup for WordPress Theme Development

As a follow up to my previous post where I show you a Gulp setup for static sites development, today, I want to share a Gulp setup for working with WordPress. The goal is to integrate Gulp into your existing WordPress development environment and take advantage of all the file processing goodness Gulp has to offer.

This file was heavily inspired by Morten Rand-Hendriksen’s setup from one of his courses on You can check out his website at to learn more about Monten.

I am assuming you have downloaded and ran Gulp locally on your machine. But if not, please check out Gulps ‘Quick Start’ page to get it installed and ready to go.

Also, please make sure to copy the package.json file from this repo and download the dependencies by running npm install

This Gulp file will be just like the file I shared on my last post with just a few adjustments. So if you  are new to Gulp I recommend you check out that post as I provide a bit more detail on each task which may be useful for the new Gulp user. On this post I will be using the same file and just point out the adjustments made for WordPress and why it changed for this setup.

Ok, so lets start.

The Directory Structure

This Gulp file should live inside a directory with a name of your choosing, mine is named gulp-dev, and this directory should be placed in your WordPress themes directory along with your main theme, which in my case it is called hsnyc.

- themes
-- gulp-dev
---  gulpfile.js
---  package.json
-- hsnyc
--- scss
--- js
--- images
---- RAW
--- languages
--- ...
- plugins

The Imports

At the top of the file we will get the necessary functions from Gulp.

const { src, dest, watch, series, parallel } = require('gulp');

Then, we will import the following modules.

const sourcemaps = require('gulp-sourcemaps');
const sass = require('gulp-sass');
const postcss = require('gulp-postcss');
const autoprefixer = require('autoprefixer');
const image = require('gulp-image');
const jshint = require('gulp-jshint');
const stylish = require('jshint-stylish');
const browserSync = require('browser-sync').create();
var replace = require('gulp-replace');

The Variables

Next, I will be setting up some variables that we will need in the construction of each task.

Theme variable

We will use this variable to store our theme name. Make sure you assign it the name of the theme you will be working on.

//your theme name
var themename = 'hsnyc';

File paths variables

These variables will hold the path to the files inside your theme’s directory.

var root = '../' + themename + '/',
    scss = root + 'sass/',
    js = root + 'js/',
    img = root + 'images/',
    languages = root + 'languages/';

The Tasks

Please note that these can be named any way you like. We will have one less task compared to the static sites files. We will not be using the cache bust so there will be 4 tasks instead of 5: scssTask, jsTask, imgTask, and the watchTask.

The SASS Task

The main thing I am accomplishing here is to compile the style.scss file found in the theme’s scss directory to a style.css file that will be placed in the theme directory.

function scssTask(){   
 return src(scss + 'style.scss')
     .pipe(sourcemaps.init()) // initialize sourcemaps first
       outputStyle: 'expanded',
       indentType: 'tab',
       indentWidth: '1'
     }).on('error', sass.logError)) // compile SCSS to CSS
     .pipe(sourcemaps.write(scss + 'maps'))

The notable difference from my static sites Gulp file is that I am not checking an env variable to see if on production or development. That was done so postcss can auto prefix and minify the css files if in production. In this task, I will just leave it as is. I am also passing in some options for sass (outputStyle, indentType, indentWidth) but those are optional and you can just leave them out if you choose.

The Js Task

In the Js task I am only running jshint on any javascript files I write which I place in the js directory. I place any third party libraries in a ‘lib’ or ‘vendor’ directory under the js directory and I do not lint those.

function jsTask(){
 return src([js + '*.js'])
 .pipe(jshint()) //to ignore some files or directories, create a .jshintignore file and add the files/dirs you want to ignore -

I am using the stylish jshint reporter, by Sindre Sorhus, to make the output look nicer.

The Image Task

In this task I am optimizing images I place in a directory named RAW, which is inside the images directory, and outputting the optimized images outside of RAW.

function imgTask(){
 return src(img + 'RAW/**/*.{jpg,JPG,png}')

In this file I am using gulp-image instead of gulp-imagemin. There is no right or wrong, it’s just a matter of preference. gulp-image is a bit more simple in my opinion. One thing I didn’t add to my static file is gulp-newer which will only grab the source files that are newer than the destination files.

The Watch Task

The watch task will, you guessed it, watch the files for any changes and if any changes are made, it will execute a task.

function watchTask(){
 //start BrowserSync server
 watch(scss + '*.scss', scssTask);
 watch(js + '**/*.js', jsTask);
 watch(img + 'RAW/**/*.{jpg,JPG,png}', imgTask);
 watch(root + '**/*').on('change', browserSync.reload);

The first thing is to start the BrowserSync server using server() (see server function next) Then, using Gulp watch, we will monitor our html, scss, js, and image files and if any changes occur we run the corresponding task. One difference here is that I am using one watch function to reload instead of reloading on each task, like I do on my static Gulp file. I will consolidate the differences in these files at some point, but for now you can do it either way. I am sure there is performance gain by doing it one way over the other.. But it’s just too negligible to worry about, especially on a local setup.

And that was the final task on the file.

The following is the BrowserSync built-in server configurations

function server() {
   proxy: 'hsnycwp.local', //alias
   port: 8080, //<-- changed default port (default:3000). Make sure to use proxy url + port for reload to work i.e http://hsnycwp.local:8080
   open: false //<-- set false to prevent opening browser

Here are the options we specify:

  • proxy : If you have a setup that uses a local domain alias this is where you would specify it. This is the alias I am using with Docker.
  • port : Is the port number I want to use. The default is 3000 if it’s not specified.
  • open : Allows you to choose if the browser should open automatically when the server starts. I want to open it manually so I have set it to false

Default Task

And finally, we will export our default task which will be the watchTask. This task will start the monitoring of the files. 

exports.default = watchTask;

And that’s all there is to it. With this file you will be able to add a Gulp workflow, within your WordPress dev setup, that allows you to compile sass files, lint Js files, compress and optimize images, and refresh the browser upon any edits. Also, remember to copy the package.json file if you decide to start with this Gulp file.

I hope this post helps you make your WordPress theme development easier by automating some of the most repetitive dev tasks. 

If you have any feedback, suggestions, or questions please do leave them on the comment section below. I do read and try to respond to every comment. 

Thanks for reading!

Please Post Your Comments & Reviews

Your email address will not be published. Required fields are marked *


This site uses Akismet to reduce spam. Learn how your comment data is processed.