A modern front-end workflow for Wordpress

Wordpress development can feel a bit like working in the past, but it doesn't have to be that way. In this post I take a fresh look at the starter theme that brings with it a modern development workflow.

For all intents and purposes, this is a first look at the Wordpress starter theme Sage. I think I did, a long time ago, try an earlier incarnation of this theme, when it was called Roots, but I can't remember much about it (I must be going back the best part of a decade here). Roots is now a suit of Wordpress development tools, one of which being the starter theme, now known as Sage. Shortly after trying the original Roots, I for whatever reason switched to Underscores, which I continued to use as a starter theme for many years. Underscores has served me well, and I've not really had any major gripes with it; but when something recently drew my attention to Sage it made me (re)consider what I / Underscores was potentially missing. In short the missing pieces are a bunch of developer experience stuff, that we've become used to, especially working with other stacks. Specifically that means a templating engine, and a configured build script with concatenation, minification and live reloading. If these are things you tend to add to your Wordpress workflow, or like me, you'd quite like to have but not sure it's worth the setup time, then read on.

With my interest piqued I needed something Wordpressy to build. I decided to make a little shop; then set about designing a couple of pages, to give myself something to work towards.

Web page showing mug for sale. It is branded Hate Capitalism

If you want to skip to the end result, it can be found at hatecapitalism.com.

Setting up your project is pretty straight forward. Recently I've been using Local by Flywheel as my local Wordpress environment, and I continued to do so here. New Sage projects are created with Composer (which I ran outside of Local).

# wp-content/themes/
$ composer create-project roots/sage my-theme-name

During the setup you can choose to include one of a selection of CSS frameworks, but I opted for a blank slate. In your new project you run yarn to install dependancies, then when you've got got things configured yarn start to run the development server. When running the dev server, you'll want to switch the to the BrowserSync address (localhost:3000 by default), not only because this is where the live reloading happens, but once run, your updated assets do not exist in their build location. To build your assets, so they are available at my-new-site.local you need to run yarn build. When you're ready to go live yarn build:production. I suggest reading the docs before getting started. I found them to be pretty good, if maybe a little thin, given how much there is to cover. The forum does a good job of bolstering the docs, should you be left wanting.

Once up and running I had a couple of little niggles with dependancies being out of date. I quickly found that I couldn't disable the Webpack specific Browsersync (in browser) notifications. There wasn't much recourse for this as the plugin being used is no longer maintained. If this is the only problem that this plugin causes, then it's not too big of a deal (I can hide the notifications with CSS, I guess), but a bit of a concern. Less of a concern was Stylelint flagging stuff that it shouldn't be, like the system-ui font-family keyword. Updating Stylelint resolved that problem.

On to the good stuff - as I thought would be the case, having a templating language in place was nice. I've never used a templating language in Wordpress before, frankly because I've never really felt the need enough to warrant looking into it. Sage uses Laravel's Blade templates out of the box, so you get templating for free. The main benefit of using a templating language, such as Blade, is the ability to define, inherit and extend layouts. Many of us are used to working in this way, via various templating languages, in other environments, whether that be Liquid templates in Jekyll or Jinja templates in a Python project. A secondary advantage is less opening and closing of PHP tags in your templates, specifically when echoing variables:

<h1>Hello <?php echo $name; ?>.</h1>

becomes

<h1>Hello {{ $name }}.</h1>

Blade also gives you "shortcuts" for common PHP control structures; for example you can put if statements and loops right in your templates.

@if($products)
<ul>
@foreach($products as $i=>$product)
<li>{{ $product->name }}</li>
@endforeach
</ul>
@endif

When you need to, breaking into regular PHP is easy; you just wrap it like so:

@php
//php here
@endphp

I found myself doing this out of habit - I wrote a little switch statement (to handle the words that come before the price on the home page) before realising that Blade has its own syntax for this. If you're going to put such things in your templates though, I don't think using one syntax over the other will make a huge difference to the cleanliness of those templates.

@php
switch ($i) {
case 1:
First case...
break;
case 2:
Second case...
break;
default:
Default case...
break;
}
@endphp
@switch($i)
@case(1)
First case...
@break
@case(2)
Second case...
@break
@default
Default case...
@endswitch

When it came to writing styles I felt at home working with CSS in Sage. First of all, this is probably the point when you appreciate that Sage has BrowserSync ready to go, out of the box. In addition to that, Sass and PostCSS are wired up in a Webpack configuration. If I were constructing this build process from scratch I would probably forgo Sass in favour of PostCSS plugins, and opt for something less gnarly than Webpack, but I think the choices here are reasonable, and given that they are configured for us, I'm perfectly happy to use them.

The Sage build process really started to shine when it came to adding Javascript. Sage provides DOM-based routing, giving you an easy way to specify which scripts run on what pages. For example, if I wanted the Javascript for the slider on my homepage to only run the homepage, that can be achieved pretty much just by putting it in a file named home.js (the is based on body classes, of which home is one). Global Javascript, such as the slide-out navigation for example, lives in common.js. From a developer experience point of view, I found this to be a really nice answer to the question of what to do with page specific Javascript. From a user experience point of view, the appropriateness of this technique will vary with each project. You will need to consider whether putting all the Javascript in a single file the best approach.

Ironically, given that this was an exercise in exploring a Wordpress starter theme, I felt like I didn't spend much time engaging with Wordpress while working on this little project. That is perhaps the biggest compliment I could give Sage, it puts a layer of modern tooling between you and Wordpress. I still had the odd Wordpress moment, like writing a PHP function in order to change the contents of the title tag, but for the most part I felt free to focus on the sort of front-end stuff that I wanted to be focusing on. That was a breath of fresh air.