How to easily register all blocks in your theme/plugin

By Ian Svoboda

If you’re making a theme or plugin that has multiple custom blocks in it, manually registering each one can definitely feel cumbersome. In this post I’ll show you a simple way to easily register all your blocks according to modern best practices.

How to register blocks

When you make a new custom block you need to tell WordPress about it by “registering” it. Registering your blocks correctly is essential for them to properly function and doing so requires you to register the block using PHP (server side) and JavaScript (client side). This is the current best practice recommended in the Block Development handbook but isn’t always obvious or intuitive especially if you’ve built blocks in the past.

In the past, blocks were only registered via JavaScript. As of WordPress 5.8, the recommended way is to use both PHP and JavaScript to allow your blocks to work properly. This can be done using two different functions: register_block_type (PHP) and registerBlockType (JavaScript). Let’s take a look at a few examples.

Firstly, let’s assume we have a plugin that is roughly structured like this:

- /plugin-folder
  - /build
    - /blocks
  - /src
    - /blocks
      - is-multiple-of
        - block.json
        - edit.js
        - editor.scss
        - index.js
        - save.js
        - style.scss
      - bazinga-block
        - block.json
        - edit.js
        - editor.scss
        - index.js
        - save.js
        - style.scss      
- example-plugin.php

In the build/blocks folder, we have the built assets for each of the blocks including the block.json file for each block. Here’s a simple example of a block.json file:

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "lwptd/is-multiple-of",
  "version": "0.1.0",
  "title": "Is Multiple Of",
  "category": "widgets",
  "icon": "smiley",
  "description": "Show the remainder of division between two numbers.",
  "example": {},
  "supports": {
    "html": false
  },
  "attributes": {
    "firstNumber": {
      "type": "number",
      "default": 2
    },
    "secondNumber": {
      "type": "number",
      "default": 4
    },
    "result": {
      "type": "boolean",
      "default": true
    }
  },
  "textdomain": "is-multiple-of",
  "editorScript": "file:./index.js",
  "editorStyle": "file:./index.css",
  "style": "file:./style-index.css"
}

The block.json file is a configuration file for your block which includes various things, including which scripts and stylesheets are associated with your block.

To register these blocks with PHP, we can use the register_block_type function and provide the folder inside build that contains the block.json file for the block which in this case would be the block folder itself.

<?php
// example-plugin.php

function register_plugin_blocks() {
  // Here __DIR__ is a "magic constant" that points to the directory/folder this file is in.
	register_block_type( __DIR__ . '/build/example-block' );
	register_block_type( __DIR__ . '/build/bazinga-block' );
}
add_action( 'init', 'register_plugin_blocks' )

The above code runs on the “init” action, which fires when WordPress is mostly loaded and registers the two blocks on the server. Each of those blocks has it’s own index.js file where the JavaScript equivalent (registerBlockType) is run. Since we have registered our blocks on the server and included the scripts in each block’s block.json file, the JavaScript for the blocks is automatically enqueued where it needs to be.

So in each block’s index.js file we’ll find a call to registerBlockType which references the block.json file and will also provide the Edit and Save components of the block. You can see the example output from the ever handy @wordpress/create-block package:

/**
 * Registers a new block provided a unique name and an object defining its behavior.
 *
 * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
 */
import { registerBlockType } from '@wordpress/blocks';

/**
 * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
 * All files containing `style` keyword are bundled together. The code used
 * gets applied both to the front of your site and to the editor.
 *
 * @see https://www.npmjs.com/package/@wordpress/scripts#using-css
 */
import './style.scss';

/**
 * Internal dependencies
 */
import Edit from './edit';
import save from './save';
import metadata from './block.json';

/**
 * Every block starts by registering a new block type definition.
 *
 * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
 */
registerBlockType( metadata, {
	/**
	 * @see ./edit.js
	 */
	edit: Edit,

	/**
	 * @see ./save.js
	 */
	save,
} );

So here, registerBlockType is doing client-side registration and allows us to override any configuration values from the metadata (block.json) or provide values that are client-side only, such as edit (How the settings/controls look for a block in the editor) and save which determines how a static block gets saved to the database. Note: if your block is dynamic, it won’t have a save component at all!

If we didn’t register these blocks on the server, we’d have to enqueue the scripts and stylesheets for these blocks ourselves which is a pain to manage for multiple blocks and will be worse for performance if you don’t take the extra time to ensure they only are enqueued when the block is actually used!

Yikes, that sounds like a lot of work. I’m getting tired just writing about it! Registering on the server and the client is definitely important. But it sucks having to manually enqueue each block in this plugin especially if we have many or add new ones over time.

Register all blocks in one go

From here, we can use some simple PHP to look for all of the block.json files in our build folder and register the blocks whenever it finds one. This is way simpler and since each block already has it’s client-side registration covered, this will automatically work with no extra effort required!

This code should be included in the main plugin file (example-plugin.php, in our case) or some other PHP file that the plugin loads every time WordPress loads.

functions.php
<?php
// example-plugin.php

function register_plugin_blocks() {
  // Get the directory containing all blocks in the build folder.
	$blocks_dir = __DIR__ . '/build/blocks/';

  // Check if the directory is valid.
	if ( is_dir( $blocks_dir ) ) {
		$block_json_files = glob( $blocks_dir . '*/block.json' );

		foreach ( $block_json_files as $filename ) {
			register_block_type( $filename );
		}
	}
}
add_action( 'init', 'register_plugin_blocks' )

In the above code, we get the folder that contains the built assets for all our blocks, check if the directory is valid, and then get all block.json files contained therein. We then loop over all of the files we found and register each one in turn.

Now, any blocks we add to the project will automatically be registered, optimized, and available in the REST API!



Leave a Reply

Your email address will not be published. Required fields are marked *