Gulp Workflow for WordPress Plugins

In my last post, I shared my boilerplate plugin and shell script for automatically scaffolding new WordPress plugins. Among the components of my boilerplate plugin is a Gulp workflow for things like compiling Sass, concatenating and minifying Javascript, compressing images, etc. In this post, I’ll share all the details about what this file does, and how it benefits my plugin development workflow.

First, I can’t thank Ahmad Awais enough for his WPGulp project. My Gulp file is based heavily on WPGulp, but with some tweaks.

Project Variables

In my plugin boilerplate gupfile.js file, the first 1/3 of the code is setting up project variables, and loading Node modules. These are grouped by function: styles, images, Javascript, and translation. They mainly include source paths (development files), and output paths (production files). Also included are paths to watch – Gulp will watch the Sass partials, and custom and vendor scripts, and will run the associated tasks when those files are changed.

Also in this section is the loading of Node modules, such as Gulp itself, and the Gulp plugins that do the heavy lifting. There’s also a constant for defining which browser versions to support in the Gulp Autoprefixing plugin for adding proper vendor prefixes.

Gulp Tasks

Each Gulp task handles its specific role, and output a push notification to let me know that it finished.

Styles Task

The styles task compiles the project’s Sass into CSS, adds vendor prefixes, minifies the results, and sends it off to a .min.css file in the assets/css directory.

Note that each top-level file in the assets/css/sass directory (.scss files not in the partials folder) will be compiled into its own, separate .css file. For example, if I have assets/css/sass/main.scss and assets/css/sass/other.scss, then the styles task will generate two CSS files: assets/css/main.css and assets/css/other.css. This is helpful for when I want to enqueue page-specific styles.

Images Task

The images task is pretty simple: grabs each image in the assets/images/raw directory, compresses them, and sends the compressed images to assets/images, which is the source from which I pull the images in the plugin’s code.

Vendors JS Task

The vendorsJS task concatenates (joins) all the Javascript files in assets/js/vendors into one file, renames this file to vendors.min.js, minifies the code, and sends the output to assets/js. I keep the vendor scripts in a separate file from my custom scripts because the custom scripts will depend on the vendor scripts, so the vendor scripts will need to be loaded first.

Custom JS Task

This operates in the exact same way as the vendorsJS task, except it concatenates the files from assets/js/custom, and sends them to assets/js/custom.min.js.

POT Task

The pot task is what generates the .pot file for the plugin. This file is important for internationalization of your plugins, because they’re used by translators to create translation files. It looks through all of the plugin’s PHP files, and generates a .pot file based on your usage of WordPress i18n functions, such as __(), _e(), etc.

A convenient feature I added to the pot task is the search-and-replace for the text domain placeholder. The best practice for creating translatable strings is to use a text domain that matches the name of the plugin directory. If my plugin’s directory name is my-plugin, then the text domain should be my-plugin. This means that the text domain is different for each plugin I develop. Unfortunately, I can’t use a constant for the text domain, because the pot task won’t properly recognize the strings unless the second parameter of the WP i18n function is literally the text domain value. Meaning, this won’t work…

__( 'My translatable string', MY_PLUGIN_TEXT_DOMAIN );

Instead, the pot task requires this…

__( 'My translatable string', 'my-plugin' );

Since some of the plugins I have can have lengthy text domains, I don’t want to type this out every time I add a translatable string, and locating-copying-pasting the text domain each time is not cool. To get around this, I’ve added a custom snippet to my code editor to output a placeholder text domain when I use the i18n functions.

__( 'My translatable string', 'tdomain' );

Now, when I run the pot task, Gulp searches the PHP files for tdomain, and replaces it with the value of text_domain, a variable defined in the Gulp file. No longer do I have to repeatedly type out a plugin’s text domain, or screw around with copying and pasting it.

Default Task

Last is the default task. This task is what runs when you run gulp from within the project. It automatically runs the styles, images, customJS, and vendorsJS tasks. Then, it begins watching the Sass partials, and individual Javascript files, running the tasks associated with each when the files change.

This Gulp workflow works really well for me in my custom plugin development. I consider it a work-in-progress, and will be making adjustments in the future, but feel free to copy it and make it work for your needs. Again, huge thanks to Ahmad for all his hard work!

Leave a Reply

Your email address will not be published. Required fields are marked *