What is WordPress?
In short, WordPress is what you want it to be. While it began as an open source blogging platform, over the years it has grown to become many other things such as CMS, an eCommerce platform, and more.
It has its limitations, but in general is a well-known tool that a lot of non-technical content managers already know how to use. It’s a good choice for any small- to medium-sized project, but requires a close evaluation if you’re dealing with any dynamic content and a lot of traffic.
Quick note: The content of this article is not very complex, but it is assumed that the reader has a certain level of understanding of WordPress as a platform working in OSX/Linux console. Familiarity with some tools mentioned below will save on side reading as well.
Problems can be subjective, and we have our own particular list of issues with this platform.
The first and possibly biggest is speed, specifically page load times. Even on a relatively small page, loaded with only a few plugins and running on a fair server, you can see a server response time of about 700-900ms without any form of full page cache. For us that’s way too long to return a simple content page, especially if you add loading additional assets on top of that. There are ways to avoid that, but at extra effort, planning and (unfortunately) quite often, additional hosting costs.
Next is our favorite, version control of a WordPress project. There are so many approaches to the problem and we struggle to find a one that we’d go about like “yup, that’s how you should be doing it”. Why? Because there is a pretty common thought that you should only version control the theme files. On one hand that makes sense, but then, it’s important to keep the tested WordPress version and exact versions of the plugins the site was tested with as well. Also, given how much configuration is stored in the database, you should also version control the DB and uploaded assets.
Having thought about the version control, add the WordPress and plugins updates to your to-do list. There are multiple tools created to manage multiple WordPress websites in terms of updates workflow, but so far we have failed to find one that operates on the Git-controlled project repo. Usually, these just assume that the plugins and WordPress core are a playground to be changed as the updates come out.
Finally, something that is not essential, but can cost a lot of time is that WordPress is terrible when it comes to moving data between environments. Imagine that you have production site running on example.com domain. You have quite a lot of URLs in the DB, plus DB-stored configs, using this one. A usual way of working on a site is to get the PROD database dump and use it in DEV with WP_HOME and WP_SITEURL variables. While that will work, if, for some specific but valid reasons, you need to push the changes done in DEV to PROD, you’ll end up with two domains in the content. One can get the DB dump processed and all URLs and server folders updated, but it takes time and is error-prone.
How Nopio works with WordPress
Working with projects, we came up with our own set-up that combines various approaches but solves the most painful issues. Here’s how we handle almost every project built using WordPress.
Our standard is to have the development environment hosted on a remote server, edit files on local machine, and use something like SFTP plugin for SublimeText to upload a file after every save. It’s up to a developer when all version control operations are performed – personally we do most of it on the local copy.
Alternatively, as with the demo project set-up to illustrate our boilerplate set-up, we use Docker to streamline a quick development set-up. In our case it works well for changes that we don’t want to demo to the client; you just run the whole stack on local machine with a single command.
Required external tools
Without listing things like Git or SublimeText, we will focus on less obvious tools that are needed for our workflow:
- WP CLI – In most cases, we use this to update a WordPress version, which saves quite some time. It’s also capable of setting up new sites and updating plugin versions, although we choose another tool for that.
- Composer – We use Composer to manage plugin dependencies for the site. Thanks to this, we don’t need to keep plugins in the repository.
- NodeJS – A dependency to handle WordPress theme JS/CSS compilation process.
- Grunt – We have specially crafted Gruntfile.js to handle building SASS files, running JSHint, and combining themes JS and CSS files into a single one.
- SASS – All our CSS is created using this language. It’s just great 🙂
- RVM – Our SASS build process uses Composer and we like to keep our dev environments tidy so we keep the rvm gemset per project and auto configure it with rvm dotfiles.
Of course, an exact list of plugins depends on the project specification, but here are a few that we favor at Nopio:
- WP Migrate DB Pro and its addons (Media Files and CLI). If you have had enough of moving data and media files between project environments, this is the tool you should check out. It’s not free, but it’s soooo worth it – we spend about $150 a year on it (Dev licence for 100 domains) and never look back. You can also use the free version but it won’t handle the media files for you.
- Advanced Custom Fields Pro. Another paid plugin that has a free variant available, it allows us to create nice interface to edit content of posts, pages, and categories etc. If you need to have custom fields created that are easy to use, opt for this one. It also has some clever add-ons like global options screen.
- Kraken Image Optimizer. This is something that ensures that all images uploaded to the Media Library are optimized as much as possible – including the files generated by WordPress (sizes). This plugin uses an online service which is not free (with a free limited usage option), but optimized images are a must to have a well optimized site.
- Contact Form 7. WordPress doesn’t have a good way of creating any types of forms. This plugin solves this annoying issue for you – and does it in style.
- Comet Cache Pro. A paid replacement for W3 Total Cache plugin, it has proven itself to be completely worth the price. Both these plugins enable quite a lot of additional performance optimizing (caching) options, but Comet is nicer to work with.
- OPCache. WordPress is quite slow by itself so Comet + OPCache is our go-to duo. OPCache adds a dashboard for PHP opcache and integrates with Comet Cache plugin so all caches are cleared on content updates.
WordPress boilerplate set-up
We created a Github repository that you can clone to see our set-up in action. This is a simplified version of what we use, but has all important bits and pieces included. Also, the master theme that we created is nothing more than TwentySixteen theme with all CSS/JS removed and replaced with foundation of our development workflow.
Check out the example here:
.gitignore file. If you’re familiar with Git, this one should be obvious (if you’re not familiar, you should start on it ASAP). We use it to exclude all files that are dynamically built with Grunt tasks as well as installed dependencies like node modules and sass cache folders. You’ll also notice this:
Basically, we ignore all plugins except for comet-cache-pro, if it’s there. This is due to the fact that Comet does not offer a composer package repo that we can use to pull the plugin with composer.
composer.json & composer-paid.json files. These sit in the top folder of the project. Composer itself uses only one of these (composer.json), but we include the -paid suffixed example to illustrate how we’re handling installing paid plugins that are not available from wpackagist-plugin repository.
.ruby-version & .ruby-gemset files in the nopio_master theme folder. These are local config files for RVM. If you cd to a folder that contains them, RVM automatically switches to given Ruby version and Gemset. It’s cool, as you don’t want to install gems for all projects into your system ruby, and we personally would never remember to switch gemset manually when entering given project.
package.json in the nopio_master theme folder. It’s by npm to automatically install Grunt and its modules.
Gruntfile.js in the nopio_master theme folder. It’s used by Grunt and we created it in order to automate the build process of our JS and SCSS files. This file needs to be updated if you add more JS files to the project. If you want a new file to go through automation, you need to add it to the jshint.all array.
Nopio WordPress Workflow
So, once you have the boilerplate app, how do you use it to optimize the development process? Here are the steps that we usually take while working on the WordPress site:
- Enter the project folder and pull up the newest changes from git
- Run a composer install to local plugins with any changes from the repository.
- Go to the theme folder and run ‘grunt’ (assuming that you have already performed the set-up described in the README file of the example repository) to build JS and CSS files.
- [optional] Login into the admin section and check for outdated plugins. If there are any require updates:
a. Edit versions in composer.json file
b. Run ‘composer update’ in the root folder of the project
c. Check if the versions have been updated in the admin
d. Check the site for possible issues
e. Commit composer.json and composer.lock files.
- [optional] Check if WordPress itself is up to date. If not:
a. Run ‘wp core update’ in the root folder of the project
b. Refresh admin area page to trigger DB update
c. Regress test the site to ensure nothing has broken with the update
d. Commit WordPress update
- If development DB is outdated, use WP Migrate DB Pro plugin to pull content and media files from the production environment (or other that is up to date). It takes a minute or two to have the site fully updated.
- Work on the changes you need to add. The project will automatically rebuild CSS and JS if it detects changes to any source files.
a. You can find SASS files in the theme folder under sources/css path
b. You can find JS files in the theme folder under sources/js path
- When done, we commit the sources. There is no need to add result files to the repository.
NOTE: These steps assume that we’re working on a local machine, without the need of uploading files to the remote server.
Deploying to target environment
Our set-up requires us to run
‘composer install’ and
‘grunt build’ after deployment to target environment. Although you can do it manually, it’s a bit of a pain. If you need to do something more than once it’s a good idea to look into automating this task.
For most our projects, we use DeployHQ service to run automated deployment scripts, but you can use almost anything that allows for running commands on remote servers. Some other choices are:
- Jenkins + Fabric
- Gitlab Pipelines
And that just about covers how we do it! Feel free to let us know if we can improve it somehow 🙂