How to Build Gutenberg Blocks Using JSX

One of the biggest roadblocks for WordPress developers looking to build custom blocks for Gutenberg is the strange syntax and compilation requirements of React/JSX. This tutorial will cover the steps required to build a custom block using JSX. This tutorial is specific to Gutenberg and is not meant to explain how to use all of React. Follow along to build your first Gutenberg block with JSX.

(If you just want to build blocks without NPM, JSX, Babel, Webpack, etc. please see the How to Build Custom Gutenberg Blocks: a Beginner’s Guide post.)


JSX and ES6 go beyond what modern browsers support, so we’ll need to compile our code before running it in the browser. However, we don’t need to worry about manually compiling our code because there are tools that automate this process for us. We will be using npm to install these tools. If you haven’t worked with npm before, please see the How to Install npm documentation.

Installing Tools

All the tools we need to install, along with their versions, are defined in the package.json file which is placed in the root directory of our plugin:

  "name": "gutenberg-block-static-jsx-example",
  "version": "1.0.0",
  "license": "GPL-2.0-or-later",
  "main": "block.js",
  "devDependencies": {
    "babel-core": "^6.25.0",
    "babel-loader": "^7.1.1",
    "babel-plugin-transform-react-jsx": "^6.24.1",
    "babel-preset-env": "^1.6.0",
    "cross-env": "^5.0.1",
    "webpack": "^3.1.0"
  "scripts": {
    "build": "cross-env BABEL_ENV=default NODE_ENV=production webpack",
    "dev": "cross-env BABEL_ENV=default webpack --watch"

You don’t really need to understand any of the things in this file because npm knows how to read this file and automatically install the required packages. Next, we open the root directory of our plugin in the command line and type:

npm install

This will automatically install all the tools required to compile our code.

A couple of the tools we just installed require their own configuration files.


Babel is the compiler that will compile our JSX and ES6 code back into regular Javascript. The Babel config file is named .babelrc and is placed in the root folder of our plugin. The .babelrc file should contain the following code:

	"presets": [
		[ "env", {
			"modules": false,
			"targets": {
				"browsers": [
					"last 2 Chrome versions",
					"last 2 Firefox versions",
					"last 2 Safari versions",
					"last 2 iOS versions",
					"last 1 Android version",
					"last 1 ChromeAndroid version",
					"ie 11"
		} ]
	"plugins": [
		[ "transform-react-jsx", {
			"pragma": "wp.element.createElement"
		} ]


Webpack is the build tool that will listen for changes to our Javascript file and automatically compile it. The Webpack config file is called webpack.config.js and is located in the root directory of our plugin. It contains the following settings:

module.exports = {
	entry: './js/block.js',
	output: {
		path: __dirname,
		filename: 'js/',
	module: {
		loaders: [
				test: /.js$/,
				loader: 'babel-loader',
				exclude: /node_modules/,


All of our PHP code is placed in the gutenberg-block-static-jsx-example.php file:

 * Plugin Name: Gutenberg Block: Static JSX Example
 * Plugin URI:
 * Description: An example Gutenberg block with static content. Built with JSX and ES6.
 * Author: ModularWP
 * Author URI:
 * Version: 1.0.0
 * License: GPL2+
 * License URI:

defined( 'ABSPATH' ) || exit;

 * Enqueue the block's assets for the editor.
 * wp-blocks:  The registerBlockType() function to register blocks.
 * wp-element: The wp.element.createElement() function to create elements.
 * wp-i18n:    The __() function for internationalization.
 * @since 1.0.0
function mdlr_block_static_jsx_example_backend_enqueue() {
		'mdlr-block-static-jsx-example-backend-script', // Unique handle.
		plugins_url( 'js/', __FILE__ ), // block.js: We register the block here.
		array( 'wp-blocks', 'wp-i18n', 'wp-element' ) // Dependencies, defined above.
add_action( 'enqueue_block_editor_assets', 'mdlr_block_static_jsx_example_backend_enqueue' );

This file simply loads the js/ file which holds our compiled Javascript code.


Since this tutorial is focused on setting up the build tools to use JSX, I’ve kept the functionality of the rest of the plugin as simple as possible. The Javascript for our plugin is located in a file named block.js which is in the js folder. The entire block.js file looks like this:

const { __ } = wp.i18n;
const { registerBlockType } = wp.blocks;

registerBlockType( 'mdlr/static-jsx-example', {
	title: __( 'Static Block Example with JSX' ),
	icon: 'lock',
	category: 'common',
	edit() {
		return (
			<p>Static block example built with JSX.</p>
	save() {
		return (
			<p>Static block example built with JSX.</p>
} );

This is the code that defines our custom Gutenberg block. There are a number of tutorials explaining how to build blocks, so I won’t go into detail about exactly what this code does.


Now that we have all the settings files and code in place, we need to compile our code. To compile, we open the root directory of our plugin in the terminal and enter the following command:

npm run dev

Based on the settings files we created earlier, this will listen for changes to the block.js file in our js directory and automatically compile it to the file in the same directory. As long as that command is still running, any change we make to block.js will automatically be compiled.


I found JSX and ES6 compilation intimidating at first. To be honest, I’m still not totally comfortable with it. However, most Gutenberg tutorials are written using JSX, so being able to work with it has been incredibly helpful for me. I hope this tutorial helps you get up and running with JSX as well.

If you want a more comprehensive tutorial covering Gutenberg block development without JSX, check out the Gutenberg Blocks Beginners Guide.