Develop your own WordPress block - Part 1: Getting started with programming with Gutenberg
In this series of articles, I'll show you how you can develop your own WordPress block from scratch. The first part is about the structure and architecture of a Gutenberg Block Plugin and the presentation of all tools required for development in modern JavaScript.
Image card block
The aim of the entire series is to develop an image card block for the new WordPress Gutenberg editor. It should be possible to determine the image, title and text and to adjust the layout, the colors and the design of the block with some options.
To get started, let's first define some theoretical basics:
- What is a block plugin made of?
- What is React and JSX?
- Why do I need tools?
- What is Webpack, Babel and Sass for?
Building a Gutenberg block
First, I would like to take a look at the architecture of a Gutenberg block.
Basically, only one JavaScript file is integrated into the editor for a WordPress block. The block JS is integrated as usual in WordPress with wp_enqueue_script()
and should be done in a WordPress plugin (not theme).
A very simple WordPress block plugin could consist of just four files:
Block JavaScript - block.js
Here the block is created and programmed with the
registerBlockType()
function. From the block interface in the editor, HTML markup in the front end to the block options, everything takes place here in JavaScript and React. In the rest of the tutorials in this series of articles, we will focus on this part of the block development in detail.Block stylesheet - block.css
The styling of the block is integrated with its own CSS file both in the editor and in the frontend (theme).
Editor stylesheet - block-editor.css
In contrast to the block.css , this stylesheet is only loaded in the editor. It includes extra styling for block options and the block interface, which is not needed in the front end.
Plugin File - plugin.php
The main plugin file with the normal WordPress plugin header . Here our block JavaScript and block stylesheets are integrated
enqueue_block_editor_assets
the theme and editor with the new action hooksenqueue_block_assets
andenqueue_block_editor_assets
.
This basic block architecture also works for the currently very popular block collections. Instead of one block, several blocks are simply registered in the JavaScript file.
React and JSX
When you hear Gutenberg, you inevitably think of React as a developer.
React is a JavaScript library from Facebook for creating user interfaces. The Gutenberg Editor is completely written in React, as are all core blocks. Theoretically, you can also create your own blocks without React, but as of today almost everyone uses the framework.
React relies on components that are nested within one another. A component is a function or class that returns and renders a React element.
class Welcome extends React.Component { render() { return <h1>Hello, {this.props.name}</h1>; } }
The return value of the render function looks strange at first and is neither a string nor HTML, but JSX. It is the preferred form of creating a React Element.
JSX is a syntax extension for JavaScript and recommended for development with React. It brings JavaScript and HTML together and in principle allows us to mix HTML tags, JavaScript code and React components, similar to a template language.
Modern JavaScript tooling
The development of WordPress themes and plugins involves few hurdles and is very easy, because nothing more than a text editor and a local development environment is required. Even WordPress beginners can adapt the code relatively easily.
In theory, WordPress blocks don't need more than that either. The Gutenberg Handbook shows code examples in ES5 that can do without any tooling. In my opinion, the development for Gutenberg only makes sense in ESNext and with JSX, which requires a number of tools:
Webpack
It would be very tedious to create an entire block or even several blocks in a JavaScript file. Webpack is a so-called bundler and is used to merge several JS files back into one file. We can use it to split our JavaScript code into any number of files and import and export them as modules.
Babel
Modern JavaScript usually means the use of the latest ES6 features . ES6 is the latest standard for JavaScript and has lots of great features, but it won't work in older browsers. This is where Babel comes in. The tool compiles your modern ES6 and JSX code and turns it into compatible JavaScript for all browsers.
Sass
Sass is super-powered CSS and makes it easy for you to write style sheets with useful features like variables, nesting and mixins.
Webpack is the core of the build process, ie in addition to bundling files, the code is transformed with so-called Webpack loaders - for Babel and Sass, among others. You can think of it as a funnel. At the top you pour in a lot of source files and code (ES6, JSX, SCSS), at the bottom our block.js and block.css come out.
Developing a WordPress Block: Outlook on Part 2
Phew, I hope the multitude of terms and buzzwords didn't put you off immediately.
In the next tutorial we leave theory behind and create our own block plugin. The structure of the plugin and the functionality of the tooling should become a little more understandable and clearer as soon as we start with the practical part. React and JSX are not rocket science either, as we will see with the first code examples.
Thanks Brian for the explanations - really very helpful!
In particular, all of these JavaScript-related tools have so far only been Bohemian villages for me. Now I've finally understood what these things do and what they can be used for. To be honest, it wasn't even clear to me that you can build a Gutenberg block without the tools - very good to know!
I am really surprised that nobody has explained this * like that * before, and then some wonder why many of the PHP plugin developers fall by the wayside?!?
Thanks again, sometimes it is the supposedly "small" things that are important 😉
Hi David,
Thank you for your feedback. I'm glad it was understandable. It is often very difficult for me to assess whether everything is described clearly enough. As a theme developer, the whole tooling was initially off-putting for me, but now I can handle it well 🙂
All in all, we just need more documentation, tutorials, blog posts and code snippets for Gutenberg. The PHP ecosystem for WordPress has grown over the years and you can find answers to every imaginable topic, at Gutenberg there is currently a lot of trying out and studying code because there are still few sources.
I haven't published anything technical about Gutenberg for a long time, because the API has been constantly changing. Only now after the release does such a long series of articles really make sense.
Many Greetings,
Brian
Thank you Brian!
I can only say that your explanations help me a lot in understanding the relationships.
lG
wolfgang
Hello Wolfgang,
Thank you very much for your comment and the great feedback!
LG,
Brian
Moin Brian, I wanted to build my own blocks with Gutenberg for the next project, so your explanation is exactly right for me 🙂 One question: When will part 2 of the tutorial appear?
Hello Patrick,
I hope next week. I'm on a WordCamp for the weekend, so little time to write 😉
LG,
Brian
Hello Brian,
thanks for the series - everything really well explained. I am currently working intensively on the topic in order to create my own custom blocks collection in a plugin, which will then serve as the basis for all pages to be developed in the future. I use the @ wordpress / scripts ( https://www.npmjs.com/package/@wordpress/scripts ) for bundling, it works similarly to CGB but currently unfortunately without SASS or PostCSS. But now I have a problem with the registration of the blocks: Each block code is in its own src-JS and is then bundled into a build-JS. How can I summarize everything in the PHP plugins in such a way that all blocks are registered within a function and all dependencies are set? Have you done that before? I already asked the question at SO, but no one answers 🙁
Hope it's ok to ask this in the comments ...
Thanks for your help and greetings, Tim
Hello Tim,
It should be enough to define the build JS with
wp_register_script()
and all dependencies and then to register each block withregister_block_type()
:function plugin_slug_register_blocks() {
// register build.js
wp_register_script (
'plugin-slug-blocks',
plugins_url ('build.js', __FILE__),
array ('wp-blocks', 'wp-element', 'wp-data')
);
// Register block 1
register_block_type ('plugin-slug / block-name-1', array (
'editor_script' => 'plugin-slug-blocks',
));
// Register block 2
register_block_type ('plugin-slug / block-name-2', array (
'editor_script' => 'plugin-slug-blocks',
));
}
add_action ('init', 'plugin_slug_register_blocks');
In addition to editor_script ,
register_block_type()
also accepts style and editor_style as arguments for the CSS files. If it is a dynamic block, a render function can also be passed with render_callback .Hope that helps you 🙂
LG,
Brian
Hello Brian,
thanks for your quick answer with code example. I'll test that right away. I now had a separate wp_register_script function for each block, which refers to the one built-js. Then, of course, an attempt is made every time to re-register all blocks. Which works, but only with corresponding errors in the console ...
I haven't looked at dynamic blocks yet, then comes next ...
Helped me a lot! Thanks again and greetings,
Tim
Hello Brian,
So that works wonderfully, less code - no errors. Thanks again!
If you want to answer my question on SO, here is the link:
https://stackoverflow.com/questions/56045886/registering-multiple-custom-gutenberg-blocks-in-a-plugin-with-webpack-build
Many Greetings,
Tim
Ah, glad it worked. I also posted the answer on Stack Overflow 🙂