authors are vetted experts in their fields and write on topics in which they have demonstrated experience. All of our content is peer reviewed and validated by Toptal experts in the same field.
Andrey Shalashov
Verified Expert in Engineering
12 Years of Experience

Andrey is a full-stack web developer and WordPress expert. Lately, his focus is on serverless computing and JAMstack.

Read More
Share

It’s no secret that the WordPress codebase is a mess. Personally, every time I go through it, all I want is to curl up and cry. On the other hand, WordPress is way ahead of its competition. An easy-to-use and powerful CMS is an enormous undertaking, and WordPress remains popular because it delivers this.

So why would we care about the quality of code in WordPress core? It works, right?

Yes, it works, and the 15-year-old codebase is unlikely to be completely refactored by its volunteer maintainers. Unfortunately, this means it also functions as an example of coding “the WordPress way,” excusing numerous developers for not following best practices and modern development techniques. So many WordPress plugins and themes have infamously bad code, and blindly following legacy practices only continues the trend.

But who cares about bad code that still does its job? Well, nothing is free, and someone pays for a badly done job. With the WordPress codebase itself, its maintainers pay with their time, thankfully. But with your own code, it’s your client who pays.

For any even moderately complex system, the cost of initial development is insignificant compared to the cost of maintaining it, and maintenance also means adding new functionality. Hiring a developer to fix poorly designed and implemented software is going to cost several times more than developing it properly from the start.

Cheap solutions are always the most expensive ones in the long run. Or they get abandoned after running out of budget. We actually save clients’ money when we follow proven software design principles and practices. These methods are not some hyped-up fad, nor change for change’s sake. The wisdom here is born from collective developer experience, and following it really does pay off.

Obviously, this doesn’t apply to truly simple tasks like adding a few lines of CSS or a couple of custom posts and rewrites. But slapping together a few plugins (or more commonly several dozens of plugins) or churning out a Visual Composer-powered site isn’t software engineering, anyway.

That’s not a bad thing, per se—the fact that some solutions are this simple is why WordPress is so popular. But in this series I’ll be talking about real WordPress development: writing significant PHP, HTML, CSS, and JavaScript code. I’ll start with the general workflow and then focus on WordPress front-end development in this article.

Modern WordPress Development Workflow

In general, quality code is:

  • Readable. It is easy to understand what code does and why.
  • Modular. Small blocks of code with a clear purpose are easy to understand, develop, and test.
  • Reusable. Re-using already developed modules for solving similar problems significantly speeds up development.
  • Maintainable. Modifying old functionality or introducing new features is easy.

The main results—lower cost of development and ownership—have many spinoff benefits that I won’t get into here.

Instead, I’ll focus on which development techniques and best practices can help you to produce quality code. Let’s start with version control.

Use Version Control

This means using Git. Sadly, “cowboy coding” on production over FTP is pretty much still a thing. Just recently I worked for a UK-based agency and they had files with names like these all over their codebase:

  • functions copy.php
  • functions copy 2.php
  • functions test.php
  • functions2.php
  • functions test2.php

The very first thing you should do when taking on a WordPress site is to put it under version control. Tanking Servers is a fun retrospective of WordPress development mistakes. It would have been very easy to amend those—and similar mishaps that have probably happened to everyone—using Git.

Made a mistake in your code and the whole site went down? git reset gets everything back the way it was. New version update broke everything? git reset works as a time machine. Some malicious code appeared from nowhere? git status shows any new files, deleted files, or changes to any tracked files. Then you just git checkout, restoring the originals.

Beware of Exposing the .git Folder

OK, it’s clearly important to use Git. But when you do, it’s just as important to avoid exposing your Git repository to being hacked. The problem comes when you have .git folders exposed and store your credentials in them.

A standard WordPress installation fully lives in a public web folder, and the .git folder is very likely to be there as well. Obviously, no login credentials should be stored in the Git repository, but it so happens that most repositories do contain some sensitive information that shouldn’t be leaked outside.

So public access to the .git folder should be blocked. If you are using Apache, adding the snippet below at the top of the .htaccess file will block access to the .git folder and to the log files as well. Log files often contain sensitive information, so it’s wise to make them unavailable as well. For different web server setups, please ask your DevOps expert for help.

RedirectMatch 404 /\.git
RedirectMatch 404 ^.*\.log

Use Separate Environments

Do not do development on live sites—this is a recipe for downtime and unhappy clients. OK, but how should you set it up?

Ideally, there should be three development environments, with code always going in one direction: local → staging → production. This is a proven method for avoiding collisions. All core, plugin, and theme updates are first done locally, then tested on staging, and finally deployed to production.

For example, the server-specific configuration could be stored in a separate file. You can create a wp-config-local.php for each local and staging environment. (Don’t forget to add it to your .gitignore file!) Then add the following snippet to wp-config.php:

if (file_exists(dirname(__FILE__) . '/wp-config-local.php')) :
  // use local settings
  require_once(dirname(__FILE__) . '/wp-config-local.php');
else :
  // production settings
endif;

Often the best way of setting up different environments is using environment variables. If you’re not familiar with this concept, I would advise using a complete modern solution like Roots.

Use WP-CLI

The WordPress command-line interface (WP-CLI) is an extremely useful tool for administering WordPress installations. Having access to WP-CLI means having the ability to run virtually any WordPress API function. For example, you can add, remove, and edit users and their passwords with WP-CLI. Useful if you’ve just inherited a site and the owner has locked themselves out.

Another example is that initial deployment is a breeze with WP-CLI. These can be accomplished with few commands:

  • Downloading core, themes, and plugins
  • Searching and replacing in the database
  • Adding an admin user

Moreover, these actions can be scripted and automated.

Use Advanced Deployment Options

Speaking of automation, it’s worth learning some deployment technologies and processes like:

Granted, going from not using version control to dealing with Docker is a huge leap to make and will likely be overwhelming for a typical one-person WordPress project. Some options may not even be possible depending on your hosting provider. But advanced deployment is a must-have for teams and for larger projects.

Use Linting

For projects of any size, though, linting is a boon to most developers. Linting means automatically checking your code for errors. A fully-featured IDE such as PHPStorm already does that out of the box; however, simpler editors such as VSCode or Sublime Text need a dedicated program called a linter. One way of setting this up is configuring your editor to run a linter whenever you save a file.

PHP_CodeSniffer is the de-facto linter for PHP. In addition to checking for syntax errors, it can also check if your code follows style guidelines such as PSR-2. This greatly simplifies following coding standards.

For JavaScript, ESLint is a popular linter. It has an extensive ruleset and supports custom configs for all flavors and frameworks of JavaScript out there.

A powerful use case here is incorporating linting into a CI/CD build pipeline so all code is automatically validated before being deployed.

Modern WordPress Front-end Development Techniques

With a proper workflow now set up for your overall WordPress project, let’s dive into best practices for the front end.

Use Modern Tooling: Sass and ES6+

The front-end development world is ever-changing and always in motion. Once we thought that Sass was the best tool for writing CSS—and for pre-Gutenberg WordPress development, it still is—but then everyone began talking about CSS-in-JS and styled components.

Even WordPress couldn’t resist and picked up a few of those new technologies. Gutenberg, the new block editor, is built on React and a REST API.

You should definitely get up to speed with these core front-end technologies:

ES6 and Sass are modern-day JavaScript and CSS, respectively, and Webpack is a tool that allows using all these modern features without worrying about backward compatibility. Webpack can be called a front-end app compiler that generates files for usage in a browser.

Transition from jQuery to Vue.js or React

The WordPress core and almost all WordPress plugins depend on jQuery, so you can’t just stop using it. Actually, it doesn’t make sense to stop using it for simple tasks such as hiding a couple of

s or doing a one-time AJAX request when you are used to doing it that way. jQuery is going to be loaded anyway, and it’s simple and easy to use.

Complex apps are where jQuery struggles: Hard-to-follow logic, callback hell, global variables, and no HTML templating. This clearly calls for a different way of organizing the front-end app.

Modern front-end libraries such as React use object-oriented programming (OOP) principles and organize front-end app architecture into modular, reusable components. A component contains all the code, markup, and “component state” (variables) for a particular element. An element could be almost anything: A button, input field, user form, or a widget that displays recent posts from the WordPress REST API back end. Components can contain other components, forming a hierarchical relationship.

With the complexity of web pages nowadays, organizing an app into components is a proven way of building maintainable, fast web apps of any complexity. Components are highly reusable, isolated, and thus easily testable “bricks,” so it really pays to learn this concept.

There are two component-based libraries that are trending at the moment: Vue.js and React. React would be an obvious choice because it’s already used by Gutenberg. However, for someone new to modern JavaScript, Vue.js could be better to start with.

React throws you into the deep end by using ES6 features, classes, proprietary JSX syntax, and Webpack build pipeline straight away. The learning curve is quite steep.

Vue.js, on the other hand, is much more beginner-friendly, and can be used by just dropping in a