I recently spent four months developing Gutenberg blocks for the Boldermail email builder. Prior to this, I only had used JavaScript with the jQuery library to add cool dynamic effects to my websites. At first, I felt frustration over the large amount of new language standards and frameworks I had to learn. I had to read about ReactJS, babel, webpack, ESLint, ES5 vs ESNext, among other things. Even my preferred code editor, Eclipse, didn’t support ReactJS natively, and required additional configuration! This experience motivated me to start this series of articles, which I’m calling “ReactJS and Gutenberg for the WordPress PHP + jQuery Developer”. My goal is to share what I have learned, and to provide an introduction to ReactJS and Gutenberg. In this article, I will show you how to get ready to code a block for Gutenberg. Let’s begin!
What to Expect From This ReactJS and Gutenberg Tutorial
At the end of this tutorial, you should have the following foundation:
- Understand basic concepts from ReactJS, Gutenberg, NPM, ES5 vs. ESNext, JSX, babel, webpack, and create-guten-block.
- Have a development-ready environment installed on your machine to write and compile your ReactJS code. (Yes — coding for Gutenberg the way I do it in this tutorial requires compilation!)
- Be ready to add your own block to the Gutenberg editor.
Do I Need This Tutorial?
No, you don’t actually, but…
You don’t need to learn ReactJS nor modern JavaScript (ESNext) to create your own blocks. You can use regular ES5 JavaScript (more on ES5 vs ESNext in a minute). There are also plenty of frameworks that make the job easier for you. See, for example, the Advanced Custom Fields plugin. However, think of learning ReactJS as coding your own meta boxes rather than using a plugin like CMB2; or coding your own custom post types with register_post_type
rather than using Pods. These tools make your life easier by shielding you from some low-level coding, but in my humble opinion, it’s always best to know how things work under the hood. Also, if your block setup is complex, the tools mentioned above may not work for you.
So, even though you don’t need this tutorial, I would highly recommend that you follow it and learn from it. Doing so will come in handy!
Prerequisites for learning about ReactJS and Gutenberg
As I write this tutorial, I’ll expect you to know or have done the following things*:
- Have experience developing in WordPress. Whether it’s a plugin or a theme, I am going to assume you are familiar with PHP, HTML, CSS, and jQuery.
- Have a working WordPress development/testing installation.
- Know basic object oriented programming, or at least be familiar with arrays.
*I’m programming from a Macbook Pro, so my configuration will be done from a macOS perspective.
Basic Concepts
It was difficult for me to jump right into coding a block for Gutenberg without understanding a few basic ideas first. For the first half of this article, I’ll provide you with 7 basic concepts you need to know to get started coding with ReactJS and Gutenberg. In this section, I will repeatedly oversimplify things in order to make them easier to digest. However, don’t fret! As we progress in this series of articles, I will progressively add complexity to these concepts. We are just starting with simplified explanations to wrap our heads around these new terms. I will also provide you with the closest equivalent to these concepts in WordPress and/or PHP. It’ll be easier for you if you learn these new concepts in terms of things you already know!
ReactJS
ReactJS (also known as React) is an open-source JavaScript library for building user interfaces. Facebook and a community of individual developers and companies maintain it. As a WordPress developer, think of React as a JavaScript version of shortcodes. In React, you have these functions and components that will render HTML in the frontend. Let’s consider the following HTML + React code:
<html>
<head>
<body>
<div id="myReactApp"></div>
<script type="text/babel">
function Greeter(props) {
return <h1>{props.greeting}</h1>
}
var App = <Greeter greeting="Hello World!" />;
ReactDOM.render(App, document.getElementById('myReactApp'));
</script>
</body>
</head>
</html>
In familiar WordPress terms, think of the function Greeter
in the script as a shortcode, and the parameter props
as shortcode attributes. The variable App = <Greeter greeting="Hello World!" />
works similar to creating a PHP string with a shortcode in it (think $app = '[greeter greeting="Hello World!"]'
. Then, ReactDOM (a ReactJS function) works as do_shortcode
and renders the shortcode inside the <div id="ReactApp"></div>
element. The code, once displayed on the frontend, looks like:
<html>
...
<div id="myReactApp">
<h1>Hello World!</h1>
</div>
...
</html>
This is an oversimplification, but thinking of ReactJS as a fancy way of doing shortcodes will make it easier for you to learn it. And really, understanding this concept is enough for you to start coding with ReactJS and Gutenberg!
ReactJS and Gutenberg
How does ReactJS play into the new Gutenberg block editor? Well, the Gutenberg editor is built using the ReactJS framework. The WordPress and Automattic teams have been using ReactJS for a while, so it’s not surprising they decided to also use it for the editor. You can read more about the development team’s decision to use ReactJS versus other JavaScript frameworks (Vue, Angular) here.
ReactNative
This is another term that you may see being thrown around. ReactNative is the mobile version of ReactJS, and it is used to build mobile application for Android and iOS. Gutenberg uses ReactNative code in its source code to support the block editor in the WordPress app.
JSX
JSX is a syntax extension to JavaScript. It is part of the ReactJS framework. It basically allows you to write quasi-HTML in JavaScript. For example, I had to use a table
element in my React component for my Boldermail blocks. So instead of writing HTML like this:
<table align="left" border="0" cell-padding="0" cell-spacing="0" style="max-width: 100%; min-width: 100%;" width="100%" class="bmContentContainer">...</table>
I wrote the following in JavaScript in my block:
var table = <table align="left" border="0" cellPadding="0" cellSpacing="0" style={ { maxWidth: '100%', minWidth: '100%' } } width="100%" className="bmContentContainer">...</table>
Note how all of the HTML attributes and CSS properties (cell-padding
, cell-spacing
, max-width
, min-width
) were converted to camelCase (cellPadding
, cellSpacing
, maxWidth
, minWidth
). The word class
is a reserved keyword in ReactJS, so we use className
instead. When the code gets displayed in the frontend, className
gets converted to class
. Also instead of passing the CSS properties inside a string to the style
attribute, now they are passed inside a double set of curly brackets ({{}}
). Furthermore, a variable can store the whole thing to use it later!
The double set of curly brackets confused me at first, so I want to talk more about them. JavaScript uses one set of curly brackets to denote an object. And JSX uses one set of curly brackets to denote that a JavaScript notation is about to be used. So, again, coming from WordPress, think of style={ { maxWidth: '100%', minWidth: '100%' } }
as being somewhat equivalent to:
$style = array( 'max-width' => '100%', 'min-width' => '100%' );
...
<table ... <?php echo $style ?> ... </table>
where the outermost set of curly brackets behaves similar to <?php ?>
. Basically, you are telling JSX that you are about to use regular JavaScript notation inside the brackets. The inner set of brackets represents an object, similar to a PHP array.
ES5 vs ESNext
You will see these two terms show up a lot in the Gutenberg developer documentation. They refer to standards of the ECMAScript scripting language. JavaScript is an implementation of ECMAScript. Basically, think of ES5 as being PHP 5.4 and ESNext as being PHP 7.x. Similar to how some web hosting providers do not support PHP 7.x yet, not all web browsers support ESNext. You can write your blocks in old ES5 syntax, or you can write your code in ESNext syntax. If you choose ESNext, you will then need to use a translator to convert your code to the ES5 standard. Coming from WordPress, you can also think of this process as converting SCSS code to CSS using a compiler.
The advantage of using ESNext is that you can use JSX syntax, which will make your code easier to implement. For example, the following code in ES5:
function() {
return wp.element.createElement(
'div', // tag type
{
className: "myClass",
}, // attributes
'Your block.' // content
);
}
can be written in ESNext syntax (using JSX) as:
() => {
return <div className="myClass">Your block.</div>;
}
So how do we translate ES5 to ESNext? We use …
Babel and Webpack
These are another two terms you will see around a lot on Gutenberg tutorials. Babel is a translator that converts fancy ESNext syntax to the ES5 syntax that web browsers understand.
If Babel is a translator for JavaScript, you can think of Webpack as the Google Translate of programming languages. That is, Webpack works with multiple languages and assets. It also uses Babel under the hood to compile JavaScript code. Webpack will translate the JS code and other assets (like SCSS files) into a few small bundle files. Then, you will enqueue these assets into the block editor using wp_enqueue_script
.
ESLint
A linter is a static code analysis tool for identifying problematic patterns (i.e. code smells). ESLint is a linter for the JavaScript language. WordPress offers a series of coding patterns in the @wordpress/eslint-plugin package available in NPM (more on NPM in a bit). The tool we’ll be using later, create-guten-block already comes with ESLint configured (via the .eslintrc
file). If you code editor supports linting, you won’t have to configure anything to see the analysis!
Tools
Now that you understand basic concepts from ReactJS and Gutenberg, let’s discuss the tools or apps you need. By the time you finish this section you should be ready to start coding your block!
Homebrew
Homebrew is a package manager for macOS. It’s equivalent to using apt
in Ubuntu, or pip
in Python. If you have never used a package manager, think of it as being a WordPress plugin directory for your computer. We will use Homebrew to install a package manager for JavaScript, npm
.
To install Homebrew, you will need the Terminal. Open Finder on your Mac machine, navigate to Applications >> Utilities, and then double-click Terminal. Copy and paste the following code on the terminal using ⌘+C and ⌘+V on your keyboard:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
Enter your administrator password for your computer if prompted. The installation will then start.
NPM
Let’s now install the NPM package manager. NPM is a package manager for the JavaScript programming language. Gutenberg uses NPM to set and install its dependencies in your project directory. Think of Composer if you are used to coding in PHP. To install NPM, open your terminal again, and install NPM using Homebrew:
brew install node
Run npm --version
in your terminal to check that it installed correctly.
$ npm --version
6.13.4
Your Preferred Code Editor
Not all editors offer native support for ReactJS, so it’s important to choose an editor wisely. I have tested vim, Sublime Text 3, Atom, Eclipse, and IntelliJ. I’ll discuss these editors in a different article; for now I’ll say that I had the smoothest experience with IntelliJ. Unlike the other editors mentioned here, IntelliJ is not free. However, it does has a free license for students and teachers. If you can’t get your hands on an IntelliJ license, I would go with Atom or Eclipse (in that order). For both of these options, you will need to install additional plugins to make the editors work with React.
I like IntelliJ because it includes things like PHP_CodeSniffer and ESLint right off the bat. Both of these tools analyze your code as you write it. The analysis informs you if your code is formatted properly according to the WordPress Coding Standards. Atom, Eclipse, and Sublime Text offer support for these tools via plugins.
create-guten-block
Now we will use create-guten-block to set up the environment where we will code our block. create-guten-block is a developer toolkit that uses NPM to install all of the dependencies required to create blocks for Gutenberg. You can compare create-guten-block to the WordPress Plugin Boilerplate or the Underscores theme — it’s a tool get you started coding your project! I have tried other alternatives, like using Zac Gordon’s Gutenberg Course or WordPress’ Gutenberg Examples as starting points, but I found Ahmad Awais’s create-guten-block to be the best choice because it comes already configured with ESLint and is super easy to update if needed!
To install create-guten-block, navigate to any directory, and run:
npx create-guten-block gutenberg
where gutenberg
can be whatever you want to call your development directory. At this point, the NPM package manager is eXecuting some scripts via npx
, and installing all of the Gutenberg project dependencies inside your directory. Once the installation is successful, you should see the following screen:
The default directory structure of create-guten-block looks as:
gutenberg
├── .editorconfig
├── .eslintignore
├── .eslintrc.json
├── .gitignore
├── dist
├── node_modules
├── package-lock.json
├── package.json
├── plugin.php
├── readme.md
└── src
where dist
is the location of the translated files in ES5 syntax, node_modules
are the NPM dependencies, package-lock.json
and package.json
keep track of which dependencies are installed in node_modules
, plugin.php
is a fully functional plugin file (meaning you could drop this directory into the wp-content/plugins
directory and activate it), and src
contains the source code of your block(s).
For now, simply move the gutenberg
directory to wp-content/plugins
and activate the plugin. Unless you change the plugin name in plugin.php
, it will be listed as “gutenberg — CGB Gutenberg Block Plugin”. Now, if you go to the block editor, you should be able to add and see the default block there.
Integrate create-guten-block Into Your Project
The directory create-guten-block creates is fully customizable. Since all of the dependencies are inside the gutenberg
directory you created above (inside node_modules
), you can move the directory to wherever you want, and everything will still work as intended. For example, for Boldermail, I put this directory inside boldermail/trunk/includes
. I removed the Plugin Name and Plugin URI comments from plugin.php
, and renamed the file to class-boldermail-gutenberg.php
(this file then gets included through my plugin). I also got rid of .gitignore
, and readme.md
, and moved .editorconfig
to the root directory of my plugin. Here is what the blocks directory looks like inside Boldermail:
boldermail
├── assets
├── ...
└── trunk
├── ...
├── .editorconfig
├── includes
│ ├── gutenberg
│ │ ├── .eslintignore
│ │ ├── .eslintrc.json
│ │ ├── class-boldermail-gutenberg.php
│ │ ├── dist
│ │ ├── node_modules
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ └── src
│ └── ...
└── ...
To compile any changes I make to my block(s), I open my terminal, navigate to boldermail/trunk/includes/gutenberg
, and then run:
npm run build
Conclusion
That’s it! That’s all you need to know and have installed to get started coding for ReactJS and Gutenberg. I hope this article saves you about 2-3 weeks of research, and that you can use it as a starting point. You should now be ready to start designing and coding your own blocks. In my next article, I’ll explain how I built a button block for the Boldermail email builder using create-guten-block. I’ll also show you how to enqueue the compiled script into your WordPress website. Thanks for reading!
Srikanth Meenakshi says
Very nicely done, thanks! The parallels with WP development makes it easier to relate to and understand. Appreciate the write-up…
Hernán Villanueva says
Thank you for reading, and for your feedback!
AJ Clarke says
Literally the best guide and explanation out there, really helpful to have the comparisons to wrap my head around things. Like how you compared React to Shortcodes. I know I’m late to the game, but can’t wait to start building blocks 😉