Having WordPress support the WinterCG project would not only improve the developer and end-user experience of WordPress, but help take the Internet to the next level. This is my thesis, which I would like to make a case for.

A (very) brief history of the web

I would like to start by talking about the web, in particular from the vantage point of the user. After all, as much as we builders like to think the web is for us, that’s only somewhat true. It’s really for everyone, and if everyone didn’t use it then the Internet simply would be another long forgotten system.

The first iteration of the Internet was created at the end of the 20th century. It was relatively simple. Most websites were purely presentational with little to no interactivity, aside from navigating the webpages. If you were astute, you might have a forum or something simple that allowed users to interact with one another by entering forms. JavaScript was quite young, and often times used for things like making text chase your mouse — useless, but fun and novel. By the end of the century, folks saw the potential and were delving into e-commerce, banking, and the like. Page refreshes were the norm and tolerated, and grabbing a coffee while a page loaded was habitual.

As we moved into the first decade of the 21st century (2000-2010), innovation surged as folks wondered how we could greatly improve the user experience of the web. AJAX became the norm, meaning the user could interact with the site and make changes without the page reloading. Design standards began to emerge as user expectations increased, people stopped reading and started scanning, and folks wanted websites to feel interactive. In short, JavaScript and CSS were having their glorious moment in the sun.

This trend really continued into the second decade (2010-2020). Frameworks like React, Vue, and Angular.js took the web by storm, flipping the premise of web applications on their head by suggesting that applications should be stateful and what rendered should be the result of the state. In short, what users interacted with in the browser should be powerful — not just a fancy widget, but a complete application like you used to think of as only possible with downloadable software. In fact, why not do less software and more web applications? The world applauded the possibilities, declared The Internet of Things, and slapped touch panels on refrigerators.

Now we begin to arrive at the present (2020-2024). We learned some interesting lessons along the way. First, making massive JS web applications had consequences — weak devices couldn’t run them, they tanked without fast connections, and required increasingly complex REST/GraphQL APIs (the latter really being born out of this pain point). Some folks even (re-)invented the JAMstack, which put rendering back on the server to overcome these issues. It was a pretty full swing.

Aiming for the best end-to-end UX

At the core of it all, we’ve kept striving to provide the best possible user experience. Everyone wants to go to a website that loads really fast (from the server) and is highly interactive. Ideally, this would mean the server understands what the user is intending to do and prepares the application for them.

This brought about an interesting realization. While the application “runs” in the browser, it begins on the server. After all, when you visit your bank’s site you don’t want to have to start from the beginning every time. The bank application should know who you are (not have to figure it out after the page loads), have your account information pulled up, know what features you’re most likely to use, and so forth. In other words, interactivity begins on the server and resumes in the browser.

Now, for the devs reading this, we think of “hydration”. This is the idea that you render the initial state of your application on the server, so when the browser picks it up it knows where to carry on from. But I like the Qwik concept of “resumability”, which takes this concept a step further and allows the application to get started immediately, without requiring a bunch of work.

In either case, the big idea here is that the best interactivity is a smooth hand-off between the server and browser, followed by subsequent exchange via API.

Interactivity and JavaScript

JavaScript is the interactive language of the browser. HTML has come a long way over the years, but you still quickly reach a point where JavaScript is necessary to make a true web application. Components became a huge piece of this success, wherein we could start to think of websites as modular pieces of work — a calendar, menu, form, etc. — that each contained isolated features that worked well together.

The pain point quickly comes when you build all of these components in (say) React, but your PHP backend has no concept of this. This means the server has no fundamental concept of what your components even are. Therefore, to prepare the interactivity on the server means building an entirely new system.

Enter WordPress

WordPress is a really good example of this tension. By 2018, WordPress was starting to feel rather dated. It was the largest CMS in the world, but out-of-the-box it provided precious little interactivity. It did almost nothing on the front-end for this, and the admin-side still predominantly required a refresh to perform most actions. Plugins and themes could go beyond this, but they were really on their own to make it happen.

Then, in December of 2018, WordPress 5.0 was released and introduced the Block Editor (or Gutenberg), a completely new way of creating content. It was pretty wild, and introduced the core concept of “blocks”. A block is a modular piece of content, like a paragraph, a bulleted list, a video, or a form. Instead of users writing a bunch of text and then using HTML or shortcodes to add more, they just added a block, and there was a block for everything.

The Block Editor was written in JavaScript and used React as the underlying framework. This was the largest piece of JavaScript ever added to WordPress and was a mighty undertaking by many talented developers, designers, and many others.

The new editor significantly raised the bar of required competency to extend WordPress. Matt Mullenweg, in anticipation of this, gave his famous “Learn JavaScript deeply” directive to the masses. This remains a struggle to this day within the WordPress community, as many folks feel left behind.

There was a fundamental issue though at the heart of it all: Blocks were written in JavaScript, while the rest of WP was largely PHP.

The complexity of blocks

Blocks have both an admin-side and front-end context. In the admin-side Block Editor the block renders for the admin to view and provides its own settings. On the front-end, it’s rendered based on the settings for the end-user.

Let’s break this down:

  • An interactive component is presented to the admin
  • The component has state, stored as the block settings
  • The component may have further state, if it’s complex (e.g. a calendar block)
  • The component is beautifully interactive within the editor

At this point one may think, “Great! The component is defined and can be used again for the front-end!” And this is where things get complicated.

WordPress stores the block in the post_content in a serialized format. You can choose to “save” the content when the block is rendered, but now your block is no longer dynamic. Or you can make it dynamic, but “dynamic” here means rendered in PHP, which can’t use the perfectly good React component you just made. If you want to use your React component, you have to load your script again on the front-end and render it on page load — which means you can’t hydrate it (start the interactivity on the server). You can use server-side rendering in blocks, but this means you end up losing your fluidity in the Block Editor as it re-renders the whole thing every time any setting changes.

This not only means more redundant code, but increases the mental load of even understanding how blocks work. Blocks are complicated, weaving back and forth between JS and PHP, which many people struggle to keep up with.

Interactivity API

In WordPress 6.5 the Interactivity API was introduced. The idea behind this API is to provide a way of introducing easy, front-end interactivity with blocks. It’s a really noble idea, which I agree with the need for. Unfortunately, I think the direction is problematic.

The Interactivity API introduces an entirely new way of creating interactive components. It doesn’t use React as bundled with core, but Preact, and an entirely new set of directives. This means one more thing the already overwhelmed WP community gets to learn, and is something that only works with WordPress.

I don’t mean to knock what was, no doubt, a huge amount of work. And given the limitations, it’s probably about the best that could be done. Still, it now means an interactive block is:

  • The React block used in the Block Editor
  • PHP for dynamically rendering the block
  • A new set of directives to use in HTML
  • A separate JS file that provides the store which defines the interactivity

A simpler-ish alternative

What if there was a simpler way to do this? What if the whole thing were possible with nothing but JS?

  • A component that defined the settings in the Block Editor
  • A component that renders the block

That’s it. That’s the whole thing.

The Block Editor block would simply reference the render block to render it in the admin screen, and then the same component would be used when rendering the post_content to send to the front-end.

Want further interactivity? That’s fine! The component will render on the server and then hydrate in the browser to resume the interactivity. No need for another API, you’ve already got React which happens to be very good at this sort of thing! (To be fair, this isn’t necessarily mutually exclusive with the Interactivity API, but in my opinion it’s far less necessary.)

So why simpler-ish?

Here’s the rub. The Block Editor is as complex as it is in dealing with all the back and forth of rendering into HTML, parsing for PHP, and rendering again because WP simply can’t assume that a JS runtime is available on the server. It can only assume PHP and a MySQL database. That’s it.

Kind of makes this whole post sound moot?

Conclusion: Possibilities

There’s a real tension in innovation. Sometimes you need to stay within the walls possibility and simply do the best you can with what you have.

And, sometimes, it’s time to knock a wall down.

Especially when you have a massive wrecking ball with WP stamped on it.

As we ponder the evolution of the Internet, I think we’re quickly arriving to the fact that interactivity is critical to the future of the web, and interactivity needs to start on the server. This is why frameworks like Qwik, NextJS, Remix, and more all the time continue to exist and grow. Many products and services get to enjoy this reality right now, and make incredible experiences, because they simply call themselves a JS runtime framework. But I think it’s short-sighted to simply say, “Good for them.”

I wish WordPress would use its weight and influence to not just make itself better, but the whole Internet. Extending the JS spec to the server means we can begin the best user journey from the server and resume it in the browser. This would simplify blocks, open up doors for web components, and more. I believe it’s possible to make a backwards-compatible approach that introduces new benefits to hosts that include the JS runtime, while not breaking it for those that don’t, incentivizing more to follow.

To be clear, I’m not suggesting that WP should become a JS runtime framework. I’m saying it’s time we stopped thinking in this way entirely and accepted JS as a full stack part of the web, working alongside PHP and other languages, so PHP could assume JS is right there to work with as well.


P.S.

There’s actually an interesting PHP extension called v8js by phpv8 that already aims to bring the JS runtime to PHP. Worth checking out!

Similar Posts