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:
- install gulp
- allow npm to control gulp using the gulp-cli
- compile my SCSS into CSS (using gulp-sass)
- add vendor prefixes to my CSS if they’re required (using autoprefixer)
- minify my CSS (using gulp-clean-css)
- process my CSS just once so I need a way to “pipe” it (using gulp-postcss)
- concatenate and compile javascript (using webpack, for which we need the gulp module webpack-stream))
- minify javascript (using gulp-minify)
- minify any images in my theme (using gulp-imagemin)
- clean up any unnecessary files when I build for production (using del)
- define different types of processes (e.g., for development and production, using yargs)
- have different processes depending on whether this is development or the production build (using gulp-if)
And when I’m developing:
- create sourcemaps for my CSS (using gulp-courcemaps)
- automatically display any changes I make in my browser of choice (using browser-sync)
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