Block Editor Development with HMR Support
Kelly Mears on
bud.js has extensions that help with developing for the WordPress block editor, and as of v6.11.0, the @roots/wordpress-hmr library is included in @roots/bud-preset-wordpress, making it easy to register blocks and other editor specific code with hot reload (HMR) support.
While bud.js is included with our WordPress starter theme, it can be used independently of Sage, including on any sort of site or application that requires building front-end assets. Moreover, the wordpress-hmr package can be used independently of bud.js or even webpack.
bud.js vs create-block package
Bud does not currently support scaffolding new blocks like the official @wordpress/create-block package (we will in the future!), but it does offer an easier to use API for working with webpack over the wp-scripts package as well as an improved developer experience.
The biggest improvement is out-of-the-box support for hot module reloading, which persists block state when editing source code. We owe a debt of gratitude to K Adam White for the initial work he did on this problem, which was instrumental to crafting our solution.
Block editor development setup
The bud.js repo contains a wordpress-editor example as a helpful reference for getting started.
If you aren’t already using bud.js in your project, you might want to integrate it as a build tool for your WordPress plugin that contains your block related assets. You can reference Radicle for a working plugin with an example block and editor plugin that is built with bud.js.
Since blocks shouldn’t be included in your WordPress theme, the following setup is based on being configured from a directory for a plugin.
package.json
Create a package.json
file in your plugin’s directory:
{
"name": "example/wordpress-block",
"private": true,
"browserslist": [
"extends @roots/browserslist-config"
],
"scripts": {
"build": "bud build",
"dev": "bud dev"
},
"devDependencies": {
"@roots/bud": "6.11.0",
"@roots/bud-preset-wordpress": "6.11.0"
}
}
bud.config.mjs
Create a bud.config.mjs
file in your plugin’s directory:
/**
* @param {import('@roots/bud').Bud} bud
*/
export default (bud) => {
bud.entry(`editor`, `@src/index.js`)
};
src/index.js
Create a src/
directory along with an index.js
file to load your block editor customizations:
roots.register.blocks(`./`)
roots.register.formats(`./`)
roots.register.variations(`./`)
roots.register.plugins(`./`)
if (import.meta.webpackHot) {
import.meta.webpackHot.accept(console.error);
}
src/example.block.js
Add an example block to the src/
directory with a filename that ends in .block.js
:
/* Block name */
export const name = `example/example-block-a`
/* Block title */
export const title = `Example block`
/* Block category */
export const category = `text`
/* Block edit */
export const edit = () => <></>
/* Block save */
export const save = () => <></>
/* Block styles */
export const styles = [
{ name: 'default', label: 'Default', isDefault: true },
{ name: 'custom', label: 'Custom' },
]
/* Block variations */
export const variations = [
{ name: `example/example-block-b`, title: 'Example block variant' }
]
At this point, you can run yarn && yarn build
to build your assets for the first time.
Enqueuing the assets
Enqueue the editor assets in your WordPress plugin by using the following code:
if (! $manifest = realpath(__DIR__.'/dist/entrypoints.json')) {
throw new \Exception('Example: you must run `yarn build` before using this plugin.');
}
$entrypoints = json_decode(file_get_contents($manifest));
add_action('wp_enqueue_editor', fn () => wp_enqueue_script(
'example/editor',
plugins_url('dist/js/editor.js', dirname(__FILE__)),
$entrypoints->editor->dependencies,
null,
true,
), 100);
Getting HMR working for block editor development
To enable the use of HMR during dev mode (yarn dev
), modify your Bud config to define the setProxyUrl and setUrl methods for the development server. In the following bud.config.mjs
file, http://example.test
is the URL to the working WordPress local development site, and http://localhost:3000
is the URL to access the Bud dev server:
export default (bud) => {
bud
.entry(`editor`, `@src/index.js`)
.setUrl(`http://localhost:3000`)
.setProxyUrl(`http://example.test`)
};
Future improvements
As mentioned at the beginning of this post, bud.js does not currently offer scaffolding tools for quickly creating new blocks and block related customizations (plugins, filters, formats, variations). We’ll be adding this functionality to bud.js in the future.