Researching Headless WordPress:
The head stays on…for now.

Posted December 23, 2017 in Thoughts, WordPress


I’ll be working on a new project over the next few months: a pro-bono website for a fantastic non-profit called “Cool Cars For Kids” (current site built with Wix) that connects classic car enthusiasts with families of children with birth defects through an annual car show to raise funds for research.

I’d like to use this project as a guinea pig in figuring out a new process for building WordPress websites, and I plan to write about it as I explore. My current process, the ACF and Timber way, seems antiquated. I want to write more JavaScript, not only because it’s where the web is going, but that’s where WordPress is going, too. There are some really cool JavaScript capabilities within the Customizer and the Gutenberg Blocks API, and I think this project will be a great use case for them.

When I first started researching the tech options for this project, I was all gung-ho about the headless CMS approach. In a sentence, a “headless” CMS, a.k.a. “decoupled” CMS, is where your CMS handles data only, and front-end display happens completely separately. The worst part about working with WordPress is probably dealing with it as you develop the front end, so isn’t this the dream? I can hit the WordPress API to grab whatever data I need and build the front end completely PHP-free (which is what Timber allowed me to do!) and, finally, have a project where I can really use React worry-free.

Not so fast. Here’s a tweet of mine that sums up my hestitations:

Brainless instead of Headless

I set out to do further research on how exactly people are building headless WordPress websites powered by the WordPress REST API and frameworks, and the ensuing pitfalls. In Ben Moore’s talk, Headless and Brainless WordPress, he brought up an interesting idea, the “Brainless” approach.

Rather than completely severing the connection between front end and back end, your front-end code still lives within WordPress, and WordPress acts as a wrapper so, in theory, you could still use things like previewing posts, URL routing, the Customizer, and plugin functionality. In page.php, for instance, you’d have something like this:

<?php get_header(); ?>

<div id="app">
    <!-- Nothing here until JavaScript puts it there -->
</div>

<?php get_footer(); ?>

Awesome! Now I can do all my single page app loveliness and still take advantage of what WordPress gives me out of the box.

Once again…not so fast. I foresee a few major headaches here, first of all: lack of server-side rendering.

From my understanding, server-side rendering needs to happen in a node environment and is not terrible to set up, if you are using a framework like React or Vue. It’s probably possible to figure some way to do all that within WordPress with some custom node work and weird code injection, but I am not up to that task…at all.

Of course, this touches on the age old debate of progressive enhancement. In 2017, isn’t it okay that a website doesn’t work without JavaScript? My gut – and by “gut” I mean the web design people I follow – tells me no, it’s not okay. It doesn’t have to be the same experience without JavaScript, but it has to be something.

Server-side rendering allows search engine bots to crawl rendered pages, and improves perceived page load times. More on that here.

Brainless example: Foxhound

I did some digging into Foxhound, a React-based WordPress theme on the repository built by Kelly Dwan. There’s a nice CSS-Tricks article about it, too. Overall, it’s a zippy and a well-designed experience, and how I wish I was able to write code like Kelly’s…getting there!

However, I have some concerns regarding performance. When auditing Foxhound on a local install with Chrome DevTools, on a “Fast 3G” connection the main page/post content – i.e. what is requested from the API and rendered with React – does not appear until about 8s, which is about 5s after the server-rendered content appears. That’s way too slow.

Image of screen captures during loading show that content does not appear until 8s.
The “brain” of the page, or the main post content requested via JavaScript, does not load until 8s on a Fast 3G connection in this “brainless” example.

Besides server-side rendering, I believe the solution for this would be caching the large, and essential, app.js file for offline use with a service worker, or splitting up that file and loading scripts by prioritization. Unfortunately, at the time of this blog post service workers are not yet supported in iOS Safari, Edge or IE11, so that’s not an option quite yet.

Regarding the code splitting, I’m not sure how helpful that would be given how large React itself is, and it would be quite challenging to implement that type of loading in a fashion inline with WordPress standards.

So, I think I’ve ruled out the “brainless” approach, but if service workers were better supported I would definitely do some more digging.

Shoutout to Gatsby.js

Before I wrap this up, I want to give a shoutout to the up and coming Gatsby.js, a relatively new kid on a block. It’s a “bring your own data” approach to a static site generator. It’s server-side React and includes code splitting and service workers and other stuff, so that’s a solved problem. It uses GraphQL to query API requests, and from what I know of GraphQL after a recent meetup here in LA, is that it is really, really awesome and exciting and is the future.

What’s more, Gatsby.js has a ready-made source package for hooking up to the WordPress REST API. Plug and play! The WordPress portion could be hosted on an inexpensive shared server (or even WordPress.com), and the front end for free on Netlify.

If this was my personal site, I’d do it because I don’t care much about previewing posts and smart URL routes. But this is not my personal site, and I have too much to do to be wrangling with the task of building my own smart routing solution when WordPress already has one ready to go.

In Conclusion

It comes down to this: I want to use WordPress because I think it is the right content management solution for this project and client. After I build the site, I want them to manage it on their own and I don’t want to be putting out fires or dealing with multiple server setup. It’s too many moving parts. Plus, as a developer, I ultimately care more about gaining experience developing with Gutenberg blocks and the Customizer than I do about learning React – I can do that on another project.

So, the head stays on!

Resources

Comments

What do you think? Do you have any questions, thoughts, or related links to share? Did I make a mistake in my post?

  • I hear you. I built a cool headless theme with angular a year ago. It was fun, but I had to recreate all the things like permalinks and pagination that a WordPress themer takes for granted. I say, if you want a blog, stick with php.
    Since then I've used the API numerous times in applications. But not for blogs..

    Compose a Reply

  • I agree with you completely, I think for headless I'd ditch WordPress entirely for something purpose configured like Contentful and deploy it on something static like Netlify, but you lose a lot of functionality without heavy coding (like user registration, membership sales).

    For now, heavier projects = WordPress with the head on and ACF for depth.

    Compose a Reply

Submit a Comment