Gutenberg is coming and if your WordPress plugin is using shortcodes, you might consider building Gutenberg blocks out of the shortcodes. In this tutorial, we will not learn about converting shortcodes into Gutenberg blocks. We will learn how we can integrate Gutenberg blocks into your existing plugins.
In this tutorial, I will assume that you don’t have Webpack configured in your plugin and that this will be the first configuration in your plugin.
If you already have Webpack configured for your plugin, you will have to edit it, but it should not be too complex.
For this tutorial, the configuration will mostly refer to the GiveWP configuration so you can see a live (production) example on how you can integrate the blocks in your plugins.
The Environment
Before you can build Gutenberg Blocks, you will need to set up the environment. If you think of using the modern JavaScript, your setup will need to compile React JSX and ESNext (ES6, ES7+).
I will focus on using Webpack here and if you’ve never used Webpack before, I have another article on Configuring Webpack in WordPress for the First Time.
If you don’t use NPM and packages in your plugin, then make sure that you have npm
available from your terminal (command prompt). If you don’t, you need to install Node.js.
Packages
We need to install npm
packages that will be used to compile our JavaScript and CSS and also optimize them. There are also other packages that are used for something else such as creating .pot
files and such.
Create a package.json
in the root folder of your plugin and add this:
If you already have a package.json
, take a look at the dependencies and add those that are missing. Place yourself in the root folder of your plugin using the terminal (command prompt) and run npm install
so that all dependencies are installed.
Babel Config
When Babel compiles our JavaScript, it will look for a Babel configuration and if it’s there, it will use the rules for the compilation that are defined there. Create a file .babelrc
and enter this:
We are defining that Babel when compiling React JSX, will use the Gutenberg Component wp.element.createElement
instead of the default React.createElement
. You are read more on editing Babel configuration here.
Git Ignore
If you’re using Git to version control your plugin, then you should ignore node_modules
because it will get really huge and you don’t need that since you can install the packages anywhere using package.json
.
Create a new file .gitignore
and add this:
Webpack Configuration
If you don’t have Webpack yet, create a file webpack.config.js
in the root folder of your plugin. If you understand Webpack, you can look at the whole configuration on gist.
Before going onwards, you should know that we’re using Webpack 3.12.0 and not the latest Webpack 4. Everything should be the same except the Extract Plugin. You can read the comment from my other article on configuring the Extract Plugin and Webpack CLI for 4.x.
Modules and Babel
Let’s now require the modules that we will use and create the constant config
that will hold some of compilation rules.
We are making Webpack know that jQuery
is globally available and it won’t be imported as a module. We are then creating a rule for .js
files, except those in node_modules
, to be compiled using Babel.
The plugins
section allows us to include various plugins that are going to get called when compiling all the files. First, we are deleting the dist
folder before comiling it again. We are extracting all the CSS to the css
folder and we are also calling the RTL plugin to create RTL CSS.
Let’s now add the rules to compile CSS/SASS and Images.
CSS and Images in Webpack
When a JS file is importing a .scss
, Webpack will load it using the provided rules and compile SASS to CSS. After it’s compiled, it will extract it to the css
folder. The images mentioned in our CSS will also be moved to the images
folder and optimized.
Input and Output Files
Webpack also requires entries and outputs. The entries are all the files that Webpack is compiling and such files will import other JS/CSS files.
In the first part, we are telling Webpack to look at the files located at assets/frontend
and assets/backend
. It is looking at both JS and SCSS. The keys backend
and frontend
will be used as the names for the compiled scripts and styles.
The output part is letting Webpack know where to put the compiled files. Here, all the files are going to be put inside assets/dist/js
. The Extract Plugin will then move the CSS files to assets/dist/css
.
The second part is related to Gutenberg. We will look at the load.js
inside blocks
folder to compile it and save it as assets/dist/gutenberg.js
. Also, there will be another file babel-polyfill.js
which you can enqueue before gutenberg.js
if you’re using ES6+ features that need polyfills.
Production
When using our plugin in production, we should have CSS and JS minified. We should also have our plugin localized so creating .pot
files is also a good thing.
That’s it. For now, this won’t work of course.
Folder Structure
For this Webpack configuration to work, we need to have a folder assets
with folders frontend
and backend
. The scripts and styles there will be then compiled into the folder /assets/dist
.
Also, create a folder blocks
in the root folder of your plugin and create a load.js
there. With that, you can now start writing Gutenberg blocks there.
Loading Gutenberg Blocks
We will also use a simple class to load our Gutenberg scripts. Let’s create a file blocks.php
inside of the folder blocks
and put this code:
If you include this file in your plugin, it will load the Gutenberg Blocks only if Gutenberg is installed and activated. You can also use this class to register new REST APIs that your blocks will use or anything else you need for your Gutenberg integration to work.
Conclusion
Integrating Gutenberg Blocks in existing WordPress plugins can be a complicated task, especially if you’ve never worked with Babel and compiling Modern JavaScript. I hope that with this tutorial, you’ll get an idea on how you can approach this and integrate your new Gutenberg Blocks in your plugin.
Have you already integrated Gutenberg in your Plugin? How was the process of it? Share with us in the comments below.
Become a Sponsor
Hi, Igor,
Thanks for the tutorial.
I’m trying to find a way to get BuddyPress to use Gutenberg as the editor for an XProfile textarea.
If I understand correctly, “class MyPlugin_Blocks” at the end of your tutorial has steps that are concerned with bringing Gutenberg into an existing plugin. Am I right that there is also code there intended to bring in new material (in the “register_blocks” function)? If I’m not bringing in new material, how would the “register_blocks” function look–am I misunderstanding this completely?
BuddyPress has a “bp.xprofile.loader.php” file in the bp-xprofile folder. My guess is that this loader is responsible for pulling in the code in the “classes” subfolder of the bp-xprofile folder, so I could add the code for “class MyPlugin_Blocks” to the “classes” subfolder, maybe with “class_bp_xprofile_gutenberg” as the file name.
I’m doing a lot of guessing, here. Looking at how BuddyPress modifies the URL string to display a user’s profile, and how Gutenberg modifies the URL string, I’m not sure I can use Gutenberg in BuddyPress as currently coded, but I thought I would seek your thoughts.
Thanks,
Mark Foote
Hi Mark, you would need to have Gutenberg plugin activated. This code in the tutorial is using the Gutenberg API and for now, it is used on a whole screen. I am afraid you won’t be able to use it just for one text field in BuddyPress.
It is not yet intended for that although in a near future it might have some functions that could do that since they do plan to replace the Customizer with Gutenberg in the long run.
Hi, Igor,
Thanks much for your prompt reply.
There is this code in “bp-xprofile/classes/class-bp-xprofile-field-type-textarea.php:
$editor_args = apply_filters( ‘bp_xprofile_field_type_textarea_editor_args’, array(
‘teeny’ => true,
‘media_buttons’ => false,
‘quicktags’ => true,
‘textarea_rows’ => 10,
), ‘edit’ );
Changing “teeny => true” to “teeny => false” allowed me to pick up TinyMCE Advanced as the editor in my xprofile textarea, when I enabled the TinyMCE Advanced plugin. My assumption was that the xprofile textarea would therefore pick up the default editor, but disabling TinyMCE advanced and enabling Gutenberg, I did not get Gutenberg as the editor.
Do you know, is there specific code in Gutenberg that limits its application in this regard? If I understand you correctly, you are saying there a check somewhere in the Gutenberg code as to whether a whole screen is involved; by any chance, can you point me to that code?
Thanks, Igor;
Mark
Hi Mark, Gutenberg is a complete application built on React. For now, it does not provide a small snippet just for a textarea such as wp_editor() does. It is used to replace the whole page/post screen not a small part. At least, not for now.
Gutenberg is loaded using React (JavaScript) inside the container:
.gutenberg__editor
You can check here: https://github.com/WordPress/gutenberg/blob/master/gutenberg.php#L26
Hi again, Igor,
Thanks for your explanation.
I get that Gutenberg was built with React (I’m more familiar with Angular), and I understand from your article here that developers are writing in Javascript and using various tools and libraries to translate that back into PHP. That’s amazing to me, having only experimented briefly with node.js.
I think the relevant line in that code you pointed me to is this, in the function “is_gutenberg_page()”:
if ( get_current_screen()->base !== ‘post’ ) {
return false;
}
I would guess that the routing mechanisms of Gutenberg and Buddypress aren’t going to play with each other nicely, so I’m giving it up.
Too bad Gutenberg (and Elementor) couldn’t be like the TinyMCE Advanced plugin, and appear anywhere an editor is being used.
Thanks again for your article and your replies, this is all pretty fascinating and new to me.
cheers,
Mark
I am trying to set default image in a image block. Could please help me how to get plugin_dir_url() in gutenberg block index.js
Hi Aryan, you could use the
wp_localize_script
to set a variable with that data and then use the variable in JavaScript. Check the codex on that: https://codex.wordpress.org/Function_Reference/wp_localize_scriptIs this still your preferred implementation of integrating a Gutenberg block in to an existing plugin or would you now prefer to use something like @wordpress/create-block
I have not played with new ways of integrating them. Will have to have a look and see what works better 🙂