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 <tomaz@zaman.io>",
"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 );
this.emit('end');
}
// 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() {
livereload.listen();
// don't listen to whole js folder, it'll create an infinite loop
gulp.watch( [ './js/**/*.js', '!./js/dist/*.js' ], [ 'scripts' ] )
gulp.watch( './scss/**/*.scss', ['scss'] );
gulp.watch( './**/*.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'
} );
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://' + (location.host || '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.
You'll need to following file strucutre (an example), but it's not mandatory, change the gulpfile.js if your paths differ
/js/src/navigation.js
/js/manifest.js
/scss/style.scss
/js/src/src folder and, if you use Bower, from the bower_components directorystyle.scss loads all the other stylesheets inOnce 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.js
/js/dist/scripts.min.js # Uglified, production ready
/style.css
/style.min.css # Minified, production ready
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.