How we made a php production team adopt Gutenberg

A migration path from defiance to adoption
Posted in Gutenberg, the 03/11/2020.

Reaching the limit of wysiwyg

I’ve started working with WordPress in 2009, and it followed me quite closely throughout the last 11 years. During the first 8 or 9 of them, be it me, my colleagues, or most of the community working with this CMS, we did so in PHP. Altogether, we were part of this huge ecosystem made of WordPress profesionnals that built themes and plugins for it, and mostly all of that written in PHP.

Then Gutenberg came along, and for the right reasons in my opinion. The old editor had reached its limits. As an agency building premium websites for our customers, we felt limited by it, and so were our clients. It had reached a point where they couldn’t get high quality layouts without writing HTML themselves or composing with uncomfortable trickery. Well, it had made its time and it was time for a change. And ho boy what a change it was about to be.

First Gutenberg encounter

I remember the excitement I felt when I saw the first Gutenberg demo. It was even mounted on a front office environment, which let us think we might be able to offer live content editing on a page too in the future. Sadly that was just for the demo, Gutenberg is still only a back office editor for now.

Then came the Gutenberg plugin that let us work with it even though it was not part of the WordPress core yet. It was time for a first encounter, and honestly I was shocked. I was shocked because I wasn’t ready, I was shocked because I was surprised, I was shocked because it felt so different, I was shocked because it was hard. I was close to call it a treason. Why ? Because I felt a rupture with why I think WordPress is awesome.

WordPress is in my opinion a very open platform, partly thanks to its hooks and template hierarchy mechanism. Thanks to those two things, you can expand the CMS or rewrite parts of it in really great extends. For example you can use many different rendering methods in the front end, be it the loop by default, or MVC with frameworks, or twig / timber rendering if you want. It’s so open and so many people have produced resources to work with it that you can choose an approach that truly fits the way you’d like to work with it.

At first, I felt we’d lost that with the introduction of Gutenberg. Suddenly I felt I didn’t have the choice anymore, that someone told me and the rest of us : “Learn JavaScript deeply because that’s what the cool kids do now, and we want to be cool again”.

I did think at first that it was a hype driven development and elitist move forcing the use of React upon a php based community. A move that would exclude so many people from the game when WordPress usually tries to get the most on board. I saw a risky and unstable move embracing a technology evolving a high speed, with the frequent introduction of major or breaking changes in its core API, which contrasts with the huge retro compatibility efforts on the PHP core for example.

Unsurprisingly I wasn’t alone feeling this. Many of the WordPress pros I know where shook by this new way of approaching our work.

But don’t get me wrong, I’m not here to bash on Gutenberg. Those last lines summarize a first impression, a first negative impression that needed more time and understanding of the product to mature, that’s why I didn’t share it that much at the time.

Embracing change

Despite my first skepticism regarding the development experience, Gutenberg was going to stay, and was going to be a center piece of the platform I was working the most with, so I had two options : jumping on the train, or stay grumpy on the side.

Furthermore the development experience was not the only thing to take into consideration : what about the webmaster experience? What about the writer experience?

I’ve tried both and I had to admit Gutenberg was a huge improvement compared to what the situation was before it. Writing was smoother, and also quicker. Same for when I put the webmaster hat on : I was able to quickly mount pages, sometimes with complex layouts. The presentation was clear, it distinguished content from the structure, I could rapidly see how the page was mounted, find the area I would want to edit. It felt cleaner with no more HTML visible on the page, just blocks. We awaited an editing improvement and that was clearly the case, it’s a great tool to create content and lay it out, and those are two very good reasons to make a development effort to offer our customers the best editing experience we could.

How can we close such a gap

Let’s summarize the situation we’re in. On one side we’ve got a php production team, with php processes, php plugins, php components accumulated over the years, and on the other hand we’ve got a brand new editor, full of possibilities, promising to break the edition barrier, but requires you to code and even render in react. That made the team defiant.

That’s quite a gap, but the questions are : are those two worlds really incompatible? Do we have to throw away our capitalized efforts in favor of a shiny new tool? Is there a pragmatic migration path ?

First point : server side opening

Remember when I wrote that Gutenberg was removing the luxury of the choice from developers earlier on? It turns out I was wrong (on many parts but let’s focus on this one for now). First choice you have : you can choose to prefer a server side rendering in place of the the react rendering when you register a block on the php side with the register_block_type function. Here’s a more complete example available as a gist.

This opens up a new world of possibilities because in a sever side render callback, you have access to two crucial parameters : the attributes administered on your block, and the administered block content. You can see those two parameters documented on the WP_Block_Type::render method documentation. And honestly with those two parameters you have more than anything you need to render your blocks with a php callback, and more precisely in our case, existing php components like the ones we used to administer via shortcodes for example.

To sum up, with a server side render callback, you can improve the admin experience by coding a react block for the back office, and potentially map the edited attributes and content to an existing php component on the front office, which smoothens the migration path.

Second point : Migrating away from ShortCodes

ShortCodes have been around for so long. They’ve been utterly useful to ease the administration of content inside the wysiwyg editor. They allowed us to separate the content from the HTML structure for example.

But they have limits too, especially when trying to deal with medias for example or complexe structures (even with imbricated shortcodes).

They were quick to create though (thus cheap in cost), and efficient in their task, and most importantly for our subject, they were mastered by everyone, whereas suddenly, we need to produce react blocks, which at the moment of writing eliminates some of our developers from the process, and it’s becoming longer for the others (thus more expansive).

That’s why we’ve decided to invest on a solution that would equilibrate the balance : a php annotation based block abstraction mechanism. I’ll write a dedicated article on this technique soon because it’s a bit long to explain it in detail, but here’s a summary in short : placing php annotations on a php component class (such as ones we use to render content historically), as well as on its attributes, would automatically make this php based component available as a Gutenberg block in the editor, under the form of an admin form, with one field per attribute. Then the render would be delegated back to this component, with all the values for each field passed.

Bascially it allows you to turn the following

/**
 * @Block(title="Chiffre clé")
 *
 */
class ChiffreCleComponent extends AbstractComponent
{
    /**
     * @var string
     * @BlockAttributes(component="PlainText",type="string",componentAttributes={"placeholder":"Titre"})
     */
    protected $title;

    /**
     * @var string
     * @BlockAttributes(component="PlainText",type="string",componentAttributes={"placeholder":"Texte"})
     */
    protected $text;

    /**
     * @var string
     * @BlockAttributes(component="MediaUpload",type="string",componentAttributes={"size":"medium"})
     */
    protected $image;

[...]

Into this :

TL;DR : that worked super well for low level administration needs.

Third point : Becoming comfortable with react Gutenberg blocks in the back office

Indeed that’s the all point of having this new editor : being able to create new blocks for it.

I did a bit of react in the past : a side project to understand the framework, how it worked, and what coding with it felt like. But it was a long time ago and not really in depth, so I had to train again: train on react, train on Gutenberg. I read a lot of tutorials, plenty of documentation, then decided to take on a small challenge : creating a section block (the equivalent of the <section> html tag), and a container block, (which is basically a wrapper div.)

I’ve always found it interesting to try to build something, even small, when learning a new skill : it allows you to learn by doing, and search online for ways to tackle a difficulty you encounter. In this case : focusing on those two blocks helped me to understand how a block should be registered, structured, how changes should be persisted, how the render mechanism works and so on. It was full of discovery and knowledge, and that surely helped me a lot to tackle the abstract block challenge which was a lot more technical.

For those two blocks I opted for a react render, not a server one, it was more appropriate in this case, and it made me discover how you can render inner blocks within a block.

It was not easy at first to build those blocks. Since then, I became more at ease with the process, and the React syntax, even though it moves quickly. But it’s still a lengthier process for us than coding in PHP, so when facing a new block opportunity, we’ve decided to question what the best way of dealing with it would be at the given time instead of having a fixed thinking. Let’s see how in the next chapter.

Conclusion : we have an even greater choice now

To summarize how my thoughts evolved : I was at first afraid that Gutenberg would force us into a closed path, furthermore one that was disconnected from our php reality. After investigation, it turns out it gave us an even wider set of tools to address the needs of our clients by adding new ways to work, and by not necessarily eliminating the existing ones.

Now when we have to develop an administration brick for our clients our webmasters, we ask ourselves the following questions :

  • Is the editing feature we’re looking at complex? (For example a slider, an accordion, a set of rich panels…). And therefore does it deserve the best Gutenberg experience we can offer ?
    • If yes, we should take advantage of the editor’s possibilities, and we should code a native Gutenberg block (in react).
    • We still have the choice to render in PHP or React based on the desired output. Some of our components are even rendered in Twig.
    • It’s more difficult for us to code, but we’re improving block after block. We even abstracted some of the mechanism already to shorten the process of creating of blocks. Our tooling is in place too.
    • For the webmaster : it adds a lot of value to his experience.
    • For now, we rely on more senior profiles to produce those blocks. Those profile took the right training and are now able to create production ready Gutenberg blocks.
  • Is the editing feature we’re looking at basic? Or a shortcode improvement ?
    • If yes, a form to fill should be sufficient in the admin, therefore we’ll provide a php component, made available as a form to fill in Gutenberg thanks to annotations.
    • Thanks to the fact that the process is well documented, these blocks are very quick for the team to code and to make available in Gutenberg.
    • It’s not the full editor experience but it’s still very comfortable for a webmaster, and it’s cheap to produce.
    • Any member of the team knows how to produce such blocks and is able to do so.
  • Do we really need to code a block for this feature? Maybe a set of default Gutenberg blocks could do the trick? Or maybe a pattern ?
    • It’s worth knowing all the default blocks, what you can do with them, and what you can’t. For example, I frequently use the paragraph, columns, gallery, and media ones.

To sump up, in front of a new block opportunity, we try to take the best decision as where to invest time and effort on blocks that are worth it, versus blocks that are not because they are more basic.

Even though adopting Gutenberg was a bit daunting during our first encounter, the time and efforts we put on the tool analysis and the adoption path was clearly worth it. Our webmaster loves it, so do our clients. The team is onboarded, everyone understands the added value and is technically able to contribute at different scale.

Finally, we haven’t lost our historical ecosystem, quite the contrary it’s now enhanced by a much better editing experience. Everyone wins.