# Block Editor Development with HMR Support

[bud.js](https://bud.js.org/) has extensions that help with developing for the WordPress block editor, and as of v6.11.0, the [@roots/wordpress-hmr](https://www.npmjs.com/package/@roots/wordpress-hmr) library is included in [@roots/bud-preset-wordpress](https://bud.js.org/extensions/bud-preset-wordpress/editor-integration), 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](https://roots.io/sage/), 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](https://github.com/WordPress/gutenberg/blob/trunk/packages/create-block/README.md) (we will in the future!), but it does offer an easier to use API for working with webpack over the [wp-scripts](https://github.com/WordPress/gutenberg/blob/trunk/packages/scripts/README.md) package as well as an improved developer experience.

![Building a block with @wordpress/create-block versus bud.js](/app/uploads/wordpress-create-block-vs-bud.png)Building a block with @wordpress/create-block versus bud.jsThe 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](https://www.kadamwhite.com/) 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](https://github.com/roots/bud/tree/main/examples/wordpress-editor) 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](https://roots.io/products/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](https://github.com/roots/bud/blob/main/examples/wordpress-editor/src/example.block.js) 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](https://bud.js.org/docs/bud.setProxyUrl/) and [setUrl](https://bud.js.org/docs/bud.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.