Visit project on GitHub

Overview

Brief introduction into plugin's internals


Gutenberg codebase

Gutenberg is a Javacsript browser app internally based on React framework (wrapped through the @wordpress/element package). It also uses its own state management module which is inspired by Redux called @wordpress/data. Gutenberg also provides some other generic packages under the @wordpress scope, which are handy for writting other Javacsript code for Wordpress, like @wordpress/api-fetch for using the WP REST API, or @wordpress/scripts tool to easily scafold your app quickly.

Check out the project's Github page for more information.

How does Gutenberg store its content?

Get familiar with blocks core concepts from the official handbook.

In a nutshell, block is some kind of unit for defining structured content. Every block has unique namespaced name and has to be registered in the block registry upon gutenberg bootstrap. Each block also contains attributes or configuration setting, which acts as a further metadata storage.

The gutenberg editor than uses raw post html content to serialize/parse block information which is stored in html comments.

Here is the example of serialized blocks in raw html post content,

<!-- wp:columns {"columns":3} -->
<div class="wp-block-columns has-3-columns">
	<!-- wp:column -->
	<div class="wp-block-column">
		<!-- wp:paragraph -->
		<p>Left</p>
		<!-- /wp:paragraph -->
	</div>
	<!-- /wp:column -->

	<!-- wp:column -->
	<div class="wp-block-column">
		<!-- wp:paragraph -->
		<p><strong>Middle</strong></p>
		<!-- /wp:paragraph -->
	</div>
	<!-- /wp:column -->

	<!-- wp:column -->
	<div class="wp-block-column"></div>
	<!-- /wp:column -->
</div>
<!-- /wp:columns -->

and here the parsed counterpart:

const blocks = [
	{
		blockName: "core/columns",
		attrs: {
			columns: 3,
		},
		innerBlocks: [
			{
				blockName: "core/column",
				attrs: null,
				innerBlocks: [
					{
						blockName: "core/paragraph",
						attrs: null,
						innerBlocks: [],
						innerHTML: "\n<p>Left</p>\n",
					},
				],
				innerHTML: '\n<div class="wp-block-column"></div>\n',
			},
			{
				blockName: "core/column",
				attrs: null,
				innerBlocks: [
					{
						blockName: "core/paragraph",
						attrs: null,
						innerBlocks: [],
						innerHTML: "\n<p><strong>Middle</strong></p>\n",
					},
				],
				innerHTML: '\n<div class="wp-block-column"></div>\n',
			},
			{
				blockName: "core/column",
				attrs: null,
				innerBlocks: [],
				innerHTML: '\n<div class="wp-block-column"></div>\n',
			},
		],
		innerHTML: '\n<div class="wp-block-columns has-3-columns">\n\n\n\n</div>\n',
	},
]

Issues with Gutenberg

Gutenberg's main issue lies within its client-side only architecture for registering/validating blocks. This way the block registry and block definitions are only available in the editor itself but not available from the PHP side of WordPress. This exposes many challenges on how to actually expose this information outside of WordPress.

How can the block registry be used from server?

The plugin is able to serialize the block registry inside gutenberg and save it with the help of REST API to the database. To load the registry, one can:

  • just open any post any gutenberg and the registry is updated behind the scenes
  • use the plugin's admin settings page which has the ability to open gutenberg inside hidden iframe and use it to fetch and update the registry
  • use the optional javascript server app, which opens up gutenberg with the help of headless browser and returns the data seamlessly as if they were stored inside database

Checkout out the server section if you are intersted in how the server app works and how to use it.