Theme development is possible with just a text editor and graphics package, but modern toolsets can revolutionize your workflow. In this tutorial, we’ll use Gulp for our WordPress development to run tasks including:

  • copying newer PHP theme files
  • optimizing images
  • compiling Sass SCSS files into a single, minified CSS file
  • merging ordered JavaScript files, remove debugging statements and minifying
  • automatically refreshing the browser when files are updated.

What is Gulp?

As they say:

gulp is a toolkit for automating painful or time-consuming tasks in your development workflow, so you can stop messing around and build something.

This perfectly describes what the Gulp really is. Install it in a few easy steps:

  1. Install Node.js.
  2. Install Gulp globally: npm install gulp-cli -g
  3. Make a theme folder with: mkdir themeName and enter the folder withcd themeName.
  4. Initialize your project with npm: npm init

#1 Setup Dependencies

You will need a fresh WordPress instalation for your local development.

Navigate to the theme folder (~/themename/), run the following npm a command to install Gulp and all plug-ins as development dependencies:

npm install --save-dev autoprefixer browser-sync css-mqpacker cssnano gulp gulp-concat gulp-deporder gulp-imagemin gulp-newer gulp-postcss gulp-sass gulp-strip-debug gulp-uglify gulp-util postcss-assets

This will create node_modules folder which contains the module code with dependencies. For Git users, add node_modules to your .gitignore file.

#2 Gulp Configuration File

Create a new gulpfile.js configuration file in your theme folder. This code should get you started:

// Gulp.js configuration 'use strict'; const // source and build folders dir = { src : 'src/', build : '/var/www/wp-content/themes/themename/' }, // Gulp and plugins gulp = require('gulp'), gutil = require('gulp-util'), newer = require('gulp-newer'), imagemin = require('gulp-imagemin'), sass = require('gulp-sass'), postcss = require('gulp-postcss'), deporder = require('gulp-deporder'), concat = require('gulp-concat'), stripdebug = require('gulp-strip-debug'), uglify = require('gulp-uglify') ; // Browser-sync var browsersync = false; // PHP settings const php = { src : dir.src + 'template/**/*.php', build : dir.build }; // copy PHP files gulp.task('php', () => { return gulp.src(php.src) .pipe(newer(php.build)) .pipe(gulp.dest(php.build)); });

We’re defining our folder location, loading modules, then creating a php task to copy new and updated files to the theme folder. The task has been kept intentionally simple to copy the PHP source files as-is. Later you can add more gulp plugins like php lint.

Save gulpfile.js and create a few .php files in the source template folder. Then enter the following command:

gulp php

All the files will be copied to the theme folder (/var/www/wp-content/themes/themeName/).

#3 Image Processing

Image files can often be compressed further using tools such as imagemin. Add the following code to gulpfile.js:

// image settings const images = { src : dir.src + 'images/**/*', build : dir.build + 'images/' }; // image processing gulp.task('images', () => { return gulp.src(images.src) .pipe(newer(images.build)) .pipe(imagemin()) .pipe(gulp.dest(images.build)); });

Save then run gulp images. Compressed versions of any new or updated images in the source images folder are copied to /var/www/wp-content/themes/themeName/images/.

#4 Sass Compilation

CSS on its own can be fun, but stylesheets are getting larger, more complex, and harder to maintain. This is where a preprocessor can help. Sass lets you use features that don’t exist in CSS yet like variables, nesting, mixins, inheritance and other nifty goodies that make writing CSS fun again.

WordPress cannot use Sass files directly; you must compile to a single style.css file. Add the following code to gulpfile.js:

// CSS settings var css = { src : dir.src + 'scss/style.scss', watch : dir.src + 'scss/**/*', build : dir.build, sassOpts: { outputStyle : 'nested', imagePath : images.build, precision : 3, errLogToConsole : true }, processors: [ require('postcss-assets')({ loadPaths: ['images/'], basePath: dir.build, baseUrl: '/wp-content/themes/wptheme/' }), require('autoprefixer')({ browsers: ['last 2 versions', '> 2%'] }), require('css-mqpacker'), require('cssnano') ] }; // CSS processing gulp.task('css', ['images'], () => { return gulp.src(css.src) .pipe(sass(css.sassOpts)) .pipe(postcss(css.processors)) .pipe(gulp.dest(css.build)) .pipe(browsersync ? browsersync.reload({ stream: true }) : gutil.noop()); });

Launch this new task with gulp css to:

  • run the Gulp images task first because images may be required in your CSS
  • compile the Sass code in the source scss/style.scss file using the fast LibSass compiler
  • use PostCSS to automatically add asset references, apply vendor prefixes, pack media queries together, and minify the resulting CSS code
  • output the stylesheet to /var/www/wp-content/themes/themeName/style.css.
  • force a Browsersync CSS to reload (more about that later).

The source scss/style.scss file must include the WordPress theme metadata at the top, e.g.

/*! Theme Name: My Theme Theme URI: http://www.sitepoint.com/ Description: Demonstration theme Version: 1.0.0 Author: Craig Buckler (@craigbuckler) Author URI: http://www.sitepoint.com/ Tags: Gulp License: MIT License URI: http://opensource.org/licenses/mit-license.php */ @import '_base'; @import '_forms'; @import '_tables'; @import 'components/_widget1'; // etc...

It is important to use /*! as the first line. This ensures the cssnano minifier does not remove the comment and render your theme unusable.

The postcss-assets plugin allows you to refer to image assets using code such as:

.widget1 { width: width('myimage.jpg'); height: height('myimage.jpg'); background-image: resolve('myimage.jpg'); }

You can also inline images with automatic Base64 encoding:

.widget2 { background-image: inline('myimage.jpg'); }

#5 JavaScript Processing

Add the following code to gulpfile.js:

// JavaScript settings const js = { src : dir.src + 'js/**/*', build : dir.build + 'js/', filename : 'scripts.js' }; // JavaScript processing gulp.task('js', () => { return gulp.src(js.src) .pipe(deporder()) .pipe(concat(js.filename)) .pipe(stripdebug()) .pipe(uglify()) .pipe(gulp.dest(js.build)) .pipe(browsersync ? browsersync.reload({ stream: true }) : gutil.noop()); });

Run this new task with gulp js to:

  • process all JavaScript files in the source js folder
  • order the files appropriately. Add comments at the top of your JavaScript files to declare dependencies, e.g. // requires: lib1.js or // requires: config.js lib1.js.
  • concatenate into a single file
  • strip all debugging and console logging statements
  • minify the code
  • output the resulting code to /var/www/wp-content/themes/themeName/js/scripts.js.
  • force a Browsersync CSS to reload (more about that later).

#6 Run Everything

Rather than calling each task separately, we can add the following code to gulpfile.js:

// run all tasks gulp.task('build', ['php', 'css', 'js']);

You can now use gulp build to run the phpjscss and images tasks in parallel. (Note images is a dependency of the css task, as we set it up early so we need not call it directly.)

#7 Enable File Watching and Browsersync

Your workflow can be radically improved by:

  1. Letting Gulp watch for file changes before launching the appropriate task.
  2. Automatically reloading CSS and JavaScript files when they change (without a page refresh).
  3. Automatically refreshing the page when a template file changes.

First, we need to define a browsersync task in gulpfile.js. This will create a proxy server to your web server running WordPress on localhost (change this domain or use an IP address as necessary):

// Browsersync options const syncOpts = { proxy : 'localhost', files : dir.build + '**/*', open : false, notify : false, ghostMode : false, ui: { port: 8001 } }; // browser-sync gulp.task('browsersync', () => { if (browsersync === false) { browsersync = require('browser-sync').create(); browsersync.init(syncOpts); } });

Now add a watch task to run Browsersync, watch for file changes and run the appropriate task:

// watch for file changes gulp.task('watch', ['browsersync'], () => { // page changes gulp.watch(php.src, ['php'], browsersync ? browsersync.reload : {}); // image changes gulp.watch(images.src, ['images']); // CSS changes gulp.watch(css.watch, ['css']); // JavaScript main changes gulp.watch(js.src, ['js']); });

Finally, add a default Gulp task which runs an initial build and starts the watch task:

// default task gulp.task('default', ['build', 'watch']);

Now run gulp from the command line. The console will display output which includes lines similar to:

[BS] Proxying: http://localhost [BS] Access URLs: ------------------------------------- Local: http://localhost:3000 External: http://192.168.1.99:3000 ------------------------------------- UI: http://localhost:8001 UI External: http://192.168.1.99:8001 ------------------------------------- [BS] Watching files... 

Rather than loading your development site from http://localhost/, enter the address http://localhost:3000/ or the External URL if you are viewing from another device. Your WordPress site will load as before but Gulp will watch for changes and apply the updates immediately. You’ll need never switch to your browser and click refresh again!

Hit Ctrl/Cmd + C when you want to stop Gulp processing.

 

 



Author

Ivan Jurković

Front-end web developer at Kontra and a car enthusiast.