Jake McMurchie saxophonist and Wordpress developer

Jake McMurchie

Development workflow with gulp

I’ve been using Coda for website development for many years. It has many advantages – good code editing, snippets, FTP and publishing – one being its tight integration with Codekit. However, I’ve worked on a couple of projects in the past couple of years for which I’ve had to use different build/deployment systems so I thought it might be about time to try something new. So, after a bit of reading, I looked at gulp.

I already have node.js and npm installed so I was able to dive straight into gulp installation. I was updating an existing WordPress project (myproject) with a new theme (mytheme) with the following structure:

/acf-json/
/assets/
-css/
-images/
-js/
/includes/
/src/
-images/
-js/
-scss/
/templates
functions.php
gulpfile.js
index.php
style.css

Notice gulpfile.js. I’ll return to it.

Next I opened a terminal window in my theme folder and initiated the project with NPM:

npm init

Now I start to think about how I will automate the tasks using gulp and the processes I want gulp to handle for me:

And when I’m developing:

So I ran the following commands:

npm install gulp
npm install gulp-cli
npm install gulp-sass
npm install autoprefixer
npm install gulp-clean-css
npm install gulp-postcss
npm install webpack-stream
npm install gulp-minify
npm install gulp-imagemin
npm install del
npm install yargs
npm install gulp-if

npm install --save-dev gulp-sourcemaps
npm install --save-dev browser-sync gulp

If you’re using git you’ll definitely want to add the following to .gitignore:

# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip

# Logs and databases #
######################
*.log
*.sql

# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

# npm generated files #
#######################
node_modules
build
npm-debug.log
.env

Then I opened gulpfile.js in a code editor:

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

// Local URL for your site
var localproxy = 'http://mysite.test';

// scss
const gulpif = require( 'gulp-if' );
const sass = require( 'gulp-sass' );
const cleanCss = require( 'gulp-clean-css' );
const postcss = require( 'gulp-postcss' );
const sourcemaps = require( 'gulp-sourcemaps' );
const autoprefixer = require( 'autoprefixer' );

// image optimisation
const imagemin = require( 'gulp-imagemin' );

// javascript
const webpack = require( 'webpack-stream' );
const minify = require( 'gulp-minify' );
 
// clean up script so production is fresh
const del = require( 'del' );

// browser-sync server
const server = require( 'browser-sync' ).create();

// dev/production
const yargs = require( 'yargs' );
const PRODUCTION = yargs.argv.production;

function styles( done ) {
    src( ['src/scss/style.scss', 'src/scss/editor-style.scss'] )
    .pipe( gulpif( ! PRODUCTION, sourcemaps.init() ))
    .pipe( gulpif( ! PRODUCTION, sass().on( 'error', sass.logError )))
    .pipe( gulpif( ! PRODUCTION, sourcemaps.write() ))
    //.pipe(gulpif( PRODUCTION, postcss( [ autoprefixer ] ))) // autoprefixer tells me I need gulp-postcss but it's installed! Probably a bug...
    .pipe( gulpif( PRODUCTION, cleanCss( { compatibility:'ie8' } ))) // if I only want to minimise for production, otherwise...
    //.pipe( cleanCss( { compatibility:'ie8' } ))
    .pipe( dest( 'assets/css'));
    //.pipe(server.stream());
    
    done();
}

function images() {
    return src( 'src/images/**/*.{jpg,jpeg,png,svg,gif}' )
    .pipe( imagemin() )
    .pipe( dest( 'assets/images' ));
}

function scripts() {
    return src( 'src/js/scripts.js' )
    .pipe( webpack( {
        mode: PRODUCTION ? 'production' : 'development',
        devtool: PRODUCTION ? false : 'source-map',
        output: {
            filename: 'scripts.js'
        },
    }))
    .pipe( minify( {
        ext: {
            min: '.min.js'
        }
    }))
    .pipe( dest( 'assets/js' ));
}

function clean() {
    return del( ['assets'] );
}



// run our server, watch for changes, and reload if they occur
function serve( done ) {
    server.init({
        proxy: localproxy,
        //files: [
        //    './**/*.php'
        //]
    });
    done();
}
function reload( done ) {
    server.reload();
    done();
}
function watchForChanges() {
    watch('src/scss/**/*.scss', series( styles, reload ));
    watch('src/images/**/*.{jpg,jpeg,png,svg,gif}', series( images, reload ));
    watch('src/js/**/*.js', series( scripts, reload ));
    watch("**/*.php", reload);
}



exports.styles = styles;
exports.images = images;
exports.scripts = scripts;
exports.clean = clean;
exports.serve = serve;
exports.reload = reload;
exports.watchForChanges = watchForChanges;

exports.dev = series( parallel( styles, images, scripts ), serve, watchForChanges );
exports.build = series( clean, parallel( styles, images, scripts ) );
exports.default = exports.dev;

Now I add some run scripts to package.json

  "scripts": {
    "start": "gulp",
    "build": "gulp build --production"
  },

Now I can just return to terminal and type

npm start

… to begin development, and when I’m ready to build I just type…

npm build

… which runs the gulp file with the environment flag set to production