Headstones mark the path

Interlude: Gutenberg Moves Fast

I’m taking a pause on my plugin posts to talk about Gutenberg.

I really love Gutenberg. I’m not kidding! I find it far more enjoyable to write (stories) in plain apps (I used Apple Pages because it syncs between laptop and iPad, yes, I am often using my iPad to write my novel, yes, I will let the world know when it’s done). But when I write for the web, it’s a more visual medium, and Gutenberg is fantastic to represent what I’m writing as it will be properly seen by all!


Gutenberg moves fast. Hella fast. So fast it can leave you in the dust, and it has a critical flaw that I feel has been stifling it’s growth and usage among developers.

JS isn’t your Momma’s PHP

This is obvious. Javascript ain’t PHP. PHP is a simple language that can be coerced into doing complex things if you understand basic algebra. Surprise! Everyone who considers themselves good at PHP? You’ve mastered the concepts of algebra! Alegrba is one of the easier ‘complex’ mathematic concepts to wrap your head areoud. You get “if a + b = c and a = 10 and c = 11 then b = 1” and you win!

Javascript though, it’s a little more like calculus and trig, in that you have to understand the formulas a little deeper, and they have that thing where not just numbers and letters appear, but weird symbols.

[nb: Like all analogies, this falls apart at scale, don’t read too much into it.]

For the thousands of developers who whet their teeth on PHP, jumping into JS feels like you’re a first-year high schooler in senior maths! It’s scary, it’s complicated, and worst of all … it isn’t actually documented at the micro level, because it’s generally compiled.

Micro vs Macro / Interpreted vs Compiled

The macro scale is, more or less, the big picture of what your code is supposed to do. Micro would be each individual element. For PHP, you can clearly identify both the macro (the overall function) and the micro (each teeny process in that function). This is less so for JS because the languages are different.

There are two primary types of code languages. PHP is what we call an interpreted language, because while the PHP binary is a compiled app, what you write is interpreted by the compiler. Basic JS (like jQuery) is also an interpreted language!

Compiled languages need a “build” step – they need to be manually compiled first. And if that suddenly made you think “Wait, Gutenberg is JS but I have to build it!” then you have spotted the quirk! The JS we use in Gutenberg is actually JSX!

JSX was designed for React (which is what we use to build in Gutenberg) and while it may contain some plain Javascript, it’s impossible to use the code without React. That’s why we have the build process, it takes the JSX, compiles it into JS, and saves it to a file.

The Compilation Downfall

This is where it gets messy … messier.

When there’s an error in PHP, we get the error message either on the page or in our logs, depending on how we set up our environment. I personally pipe things to debug.log and just keep that file up as I bash on things. Those errors tend to be incredibly helpful!

$mastodon not defined on /path/to/file.php:123

In that example, I know “Ooops, I’m calling the variable $mastodon on line 123 of file.php and forgot to declare it!” Either I need an isset() check or (in this case) I brain farted and copied a line but forgot to rename the variable so I was setting $tumblr twice. Mea culpa, pop in, edit, save, done.

On the other hand, I was testing out some blocks and modernizing them a little when suddenly … the block didn’t load. I got the WP notice of the block had an error. You’ve probably seen this if you’re a dev:

Example of an error which says "This block has encountered an error and cannot be previewed"

or this:

An error: This block contains unexpected or invalid content.

And if you’re like me, you used foul language and wondered ‘well… now what.’

Enter the Console

Unlike PHP, the errors don’t go to a nice debug.log file, it goes to your in-browser console. This is because, again, PHP is being directly interpreted on the server, and the server happily converts the PHP to HTML and Bob’s your uncle.

JS (and JSX in this case) aren’t processed by the server. They’re processed on the fly in the browser. If you’ve ever wondered why too much JS, or bad JS, cause your browser to hang, that’s why. We moved the processing from the server (PHP) to the browser. On top of that, it’s also why JS content isn’t really cachable by traditional methods! But that’s another story.

In this case, I got the first error (cannot be previewed) and being somewhat savvy with the world of Gutes, I popped open the console and saw this gem:

wp.blockEditor.RichText value prop as children type is deprecated

The rest of the message was warning me that the thingy would be removed in WP 6.3, and it had a link to ‘help’ resolve it. Spoilers? It didn’t. But take a deep breath. Let’s debug.

Debugging Gutenberg

The first issue was that the error came on a page with multiple blocks. I happened to be using a custom plugin I wrote that contains about 6 blocks, you see, so I opened a new page on localhost and added each block, one at a time, until I determined the issue was my incredibly simple spoiler block.

How simple is this block? It’s basically a custom formatted paragraph, so everyone could use the same design without having to remember the exact colours. I could have made it a ‘reusable block’ on the site but, at the time, I wanted the practice.

Next I went to that link, which was for “Introducing Attributes and Editable Fields“. I admit, I was a little confused, since I was already using attributes and editable fields! But I did the logical thing and searched that page for the word ‘children.’ My thought process was that if something was being deprecated, it would have a warning right?

Gif from Blazing Saddles, where Dom DeLuise is a director and walks up to an actor who made a mistake. He uses his bullhorn to scream WRONG! at the man, and bops him in the head with the bullhorn.

Okay, maybe I was looking in the wrong place. This error is specific to RichText so I clicked on the link to read the RichText Reference and again, looked for “children.” Nothing. Zip. Nada. I followed the link for the more in-depth details on GitHub and still nothing.

At this point, I ranted on Mastodon because I was chapped off. I also popped open the Gutenberg Deprecations page, and looked for “children” but all I could find was a message to use children!

RichText explicit element format removed. Please use the compatible children format instead.

Logically there should be a note that “children is deprecated, please use…” but there is not.

Now, here is where I accidentally stumbled on a fix, but after I made my fix is when I found the Github issue about this!

If you are still using “children” or “node” sources in the block attribute definition, like so:

content: {
 	type: 'array',
 	source: 'children',
 	selector: 'p',

Then change it to use the “html” source instead to get rid of the deprecation warning:

content: {
 	type: 'string',
 	source: 'html',
 	selector: 'p',

And in fact, that was the correct fix.

Here’s the Flaw

None of that was properly documented.

The link to ‘help’ fix the error didn’t mention the specific error, it talked about attributes at the MACRO level. I was (obviously) already using attributes, else I wouldn’t have had that error at all.

There is no proper documentation that could help someone fix the issue on their own UNLESS they happened to be trawling through all the issues on GitHub.

As I put it to my buddy, the reasons developers are salty about Gutenberg are:

  1. It changes pretty much every release
  2. There’s no real way to tell people if it impacts you so you have to check every release and read the console logs, which is not what devs are used to
  3. The JS console won’t tell you (I don’t know if it can) what file caused the warning, so finding it is a crap shoot
  4. The documentation is high level, which is not helpful when you get micro level errors

Okay, can we fix it?

At this point, if you’ve made a WordPress Block for Gutenberg, make sure you test every single release with the JS console open. If you don’t do this, you will have a rude awakening until things are made a little better.

How can things be made better? It will have to begin with a culture shift. Traditionally WordPress has used a “release and iterate” model. With Gutenberg, we’ve become “move fast and break things,” but that is only sustainable if everything broken can be documented for a fix.

That means I see only one way to correct this, and it’s to slow down Gutenberg enough that deprecations AND THEIR CORRECTIONS are properly documented, and the error messages link to a page about deprecations.

We need to not link to the general “here’s how attributes work” page, but instead to a specific page that lists those deprecations along side the WordPress versions impacted.

Another matter is we should be posting in the Field Guide about these things. Currently the 6.3 field guide links to all the various pages where you can find information, but that means you have to click and open each one and hopefully find your exact usage. In my case, those links to the ten Gutenberg versions being ported to core never mention the issue I had.

If we don’t start slowing down and paving the road for developers, we will begin haemorrhaging the very people who make WordPress a success.