In the first part of this tutorial series of how to create custom Gutenberg blocks we need to set up our development environment. We need a place where we can write our code in ES6/ESNext syntaxes and compiling it on the go to. It is possible to write custom Gutenberg blocks by using ES5 syntax without setting up Webpack and Babel. But the code will be truly cumbersome to read and write. If you are unsure why we need to do all this, or what the difference is, read my post explaining this. I can guarantee you that when you come back you’ll be convinced to take this extra step in order to write better code.

I assume you already have a local WordPress running on a LAMP stack or similar. And that you are either writing a theme or a plugin. As for me, I’m putting my code in a theme I’ve developed, awp-starter-theme, located in my WordPress theme folder. I want to separate out my Gutenberg development from all the other theme files so I create a subdirectory gutenberg-dev inside my theme root folder. That’ll be my project folder and the folder I’ll refer to for the rest of the tutorial series.

I have already written a detailed guide in how to setup a development environment for Gutenberg, so I’ll just quickly go through the steps here. If you have never done this before I recommend reading the linked post below, as it contains more information than what you’ll find here!

Set up the project with webpack

Using terminal (iOS terminal or Windows cmd both works fine) navigate to your project folder, (in my case awp-starter-theme/gutenberg-dev). We initiate a new project by asking npm to generate a package.json with generic content.

Creating package.json

npm init -y

Next I’ll install WordPress’ scripts that will help us a lot with configuration with this command (which will add the subfolder node_modules and package-lock.json as well):

npm install --save-dev --save-exact @wordpress/scripts

Open the package.json file in your project folder in an editor and find the scripts property. We replace it with two scripts from the WordPress package we just installed:

package.json
"scripts": {
	"build": "wp-scripts build",
	"start": "wp-scripts start"
},

The “build” script will compile my files. But as it has to be run manually every time a change is made, we will rather use the “start” script while we develop. It will then initiate a “watch mode” where it listens to changes made in any of your script files, and recompiles them whenever you save changes.

Webpack config

The next step is creating a webpack configuration file. I do this because I don’t want to use the default source and output filenames and folders. I want to decide for myself where my source files are, and where the compiled files should end up.

With the help of the @wordpress/scripts package we installed we can inherit WordPress’ webpack config, and override just the parts we want to change.

In our project folder create a new file named webpack.config.js and open it in an editor. Add this content:

webpack.config.js
const defaultConfig = require("@wordpress/scripts/config/webpack.config");
const path = require('path');

module.exports = {
	...defaultConfig,
	entry: {
		'block-awhitepixel-myfirstblock': './src/block-awhitepixel-myfirstblock.js'
	},
	output: {
		path: path.join(__dirname, '../assets/js'),
		filename: '[name].js'
	}
}

What this does is defining my entry file (currently just one) in the entry property, located in a subfolder src in my project folder, named block-awhitepixel-myfirstblock.js. Obviously name your files whatever you want, but remember to change both the key and the value. Because in the output property I’m asking webpack to compile my entry files with the entry key as filename. In the path property I ask to place all the compiled files one step out of my project folder, and into the theme’s assets/js folder. Adjust the filenames and location to fit your project. Refer to my detailed guide if you are confused.

Create a subfolder src/ in the project folder and this is where we’ll put all source files. (Adjust if you changed the entry location in webpack.config.js). Create a file block-awhitepixel-myfirstblock.js here, and leave it empty for now.

There’s one more step – and this goes for us who want to use the newest features in ESNext. The default WordPress Babel config is unfortunately missing this. And because I want to use functionality like arrow functions I need to set up Babel as well.

Setting up Babel

First we need to install some packages for our Babel configuration by typing this command:

npm install --save-dev @babel/preset-env @babel/preset-react @babel/plugin-proposal-class-properties

When that’s done, create a new file .babelrc in our project folder. This is where we’ll put our Babel configuration:

.babelrc
{
	"presets": ["@babel/preset-env", "@babel/preset-react"],
	"plugins": [
		[
			"@babel/plugin-proposal-class-properties"
		]
	]
}

And that’s it for our development environment setup!

Build commands

Throughout while developing you’ll need to compile your Javascript files. In our package.json we added two scripts for just this.

Whenever we want to develop in our Javascript files we run this in terminal:

npm run build

This command will perform compilation whenever you run this in terminal. Give it a go, and you should see that it generates the file block-awhitepixel-myfirstblock.js (along with one or two other “asset” files) in your defined output folder that you defined in webpack.config.js. In my case it appears in awp-starter-theme/assets/js/.

Using the above command works fine, but gets annoying to repeat every time you make changes in your files. You’d probably prefer running this command instead:

npm run start

This will set your terminal in “watch mode”, detecting any changes saved in your Javascript files and compile them as you go. Anytime your files contain errors, the terminal will spew out the error messages. Press CTRL + C to stop the watch process.

As a reference my project folder now looks like the image. I prefer separating out all the config files and especially the subfolder node_modules/ (which contains literally tens of thousands of files) from the rest of my theme code. Makes it easier for setting up rules for ignoring – for example SCSS compilers or git ignore. We already set up the webpack config to compile the final files directly into awp-starter-theme/assets/js/ along with other Javascript files for my theme.

We are now ready for the next part where we’ll start with registering our first custom block.