We use gulp as my task runner. It automates much of the development process. It will watch for changes in the theme files and do the appropriate actions to them:
- If it’s a change in a javascript file, it will concatenate, minimize, and then deploy to the remote server.
- If it’s a change in a php file, it will deploy to the remote server.
- If it’s a change in any scss styles file, it will produce minimized .css files and deploy to the remote server.
- If it’s a new image, it will run the imagemin process on it to compress it.
General Setup
This project is on github and the readme.md file has the installation instructions.
The gulpfile is right outside of the theme folder so that all the development files stay out of the directory that will be distributed to the WordPress installation. Since the name of the theme folder will change with each project and we don’t want to have to go into the gulpfile.js and change all the paths with the new name, we can use the configuration info in the package.json file to extract out the theme name and use that as a variable. In all the gulp.src and gulp.dest statements we use this variable to set the path. For example:
In package.json
{
"name": "mytheme",
"templateName": "mytheme",
"version": "1.0.0",
"description": "wordpress genesis template",
......
And then in my gulpfile, we can easily read this in and set a variable to the ‘name’.
var pkg = require('./package.json');
var themeName = pkg.name;
Now in all the gulp tasks this variable defines the path
....
.pipe (gulp.dest(themeName + '/js/dist/'));
...
The data in the package.json
file can also be used to fill out the comment section WordPress uses to name the template and such. See the Styling section below for more details.
Typically, we either create a theme from scratch or we alter an existing theme. If we are altering say a child theme of Genesis produced by StudioPress, we would copy the theme directory to replace the mytheme
folder and change the name
in package.json to the theme’s folder name.
Styling tasks
Some theme’s contain multiple css files and it would be great to use postcss to autoprefix any of our changes. For any css file we want to change, we will want to copy that file and save it in the same location except with the .scss extension. Any changes added from now on, we will edit the .scss file. The gulp watch process will monitor any changes and copy it to the respective .css
file.
In style.css
we have in the comment section the theme name, version info, etc that gulp can also fill out for us automatically. Here’s what the comment section in the style.scss
should look like to take advantage of that:
/*!
Theme Name: <%= pkg.templateName %><% if(environment==='build'){print('build');} %>
Theme URI: http://jhtechservices.com
Description: <%= pkg.description %>
Author: <%= pkg.author %>
Author URI: http://jhtechservices.com
Version: <%= pkg.version %>
Tags:
Template: genesis
Template Version: 2.3.1
License: <%= pkg.license %>
*/
Combine gulp’s templating ability with the package.json
file we can make our styles gulp task fill in the info. We added the templateName
variable to the package.json file. See above package.json
You can easily add your own custom fields in this json file as well.
Also, notice the /*!
used on the top comment. This is to prevent the minifying process from deleting this comment in the .css
file.
Top of the theme’s style.scss file:
/*!
Theme Name: <%= pkg.templateName %><% if(environment==='build'){print('build');} %>
Theme URI: http://jhtechservices.com
Description: <%= pkg.description %>
Author: <%= pkg.author %>
Author URI: http://jhtechservices.com
Version: <%= pkg.version %>
Tags:
Template: genesis
Template Version: 2.2.0
License: <%= pkg.license %>
*/
Here is the gulpfile.js task we use for styles. Feel free to comment out the .pipe(cleanCSS())
line if you don’t want your css minified.
var gulp = require('gulp');
var postcss = require('gulp-postcss');
var sourcemaps = require('gulp-sourcemaps');
var cleanCss = require('gulp-clean-css');
gulp.task('styles', function() {
return gulp.src([ themeName + '/**/*.scss'])
.pipe(sourcemaps.init())
.pipe(template({pkg: pkg, environment: production}))
.pipe(postcss([require('precss'), require('postcss-calc')({warnWhenCannotResolve: true}), require('autoprefixer')({ browsers: ['last 2 versions'] })]))
.pipe(cleanCss())
.pipe(rename(function(path){
path.extname = '.css'
}))
.pipe(sourcemaps.write())
.pipe(gulp.dest( themeName ));
});
Overall, our gulp task runner will take our .scss
file and process any variables, autoprefix our rules if they are needed, and then minify the result into a respective .css
file.
Javascript
A theme can have multiple javascript scripts that need to be loaded. Sometimes it is nice to separate out the scripts in separate files for easier development and troubleshooting. The problem is then keeping track of of which scripts to enqueue and the more scripts to enqueue the more requests your site will have to make. We can have gulp concatenate all our scripts into one file for us.
In the top of gulpfile.js
there is a variable called jsScripts
that contains all the script names to be concatenated together. The order in the array is important only if any script depends on another script.
The variable jsConcatenated
contains the filename the concatenated and minified scripts will be stored in. This is the script name to enqueue in the functions.php.
Rsyncing changes
This is an awesome feature! We tend to develop on a staging server that is hosted for us. As we change files, gulp automatically sends those changed files to the development server. The hard part is setting up the keys/certificates. If you don’t, you will continually be prompted for a password. This site was very helpful for us.
Images
Using ImageMin we can automatically compress our images. We setup an images/src
folder outside of the theme folder. This is where we throw our images. Gulp is setup to monitor any new images in this folder and create a compressed version of the image in the images/dist
folder. From there, you can manually move the compressed image to your theme folder’s images folder or upload it to your WordPress Media Library, depending on how you are planning to use this image.