0

I'm having trouble understanding the build/compile setup and file structure when creating multiple blocks in Gutenberg.

Both React and Gutenberg are new to me. But I've had a pretty good primer on React via Stephen Griders course on Udemy.

It became clear to me that I hadn't properly understood the Gutenberg structure when I needed to implement the render_callback function for a dynamic block.

Until now I've been using a file structure like the one listed below, where all blocks where registered with a single register_block_type call. ( This is how I would normally have done it in React. )

- Plugin/
-- plugin-init.php
-- package.json
-- package-lock.json
-- node_modules/
-- build/
--- index.js
--- index.js.map
-- src/
--- index.js
--- blocks/
---- custom-outer-block.js
---- custom-inner-block.js
---- custom-dynamic-block.js
--- components/

If I understand it correctly - from looking at the Gutenberg Examples repo ( https://github.com/WordPress/gutenberg-examples ) - each block has to be registered separately in WordPress for the render_callback to work. And therefore needs its own build file for the register_block_type call.

In the repo it also looks like each block is a separate React project. Which has to be generated and started separately with a npm create-react-app and npm start command.

Meaning that Gutenberg projects should have a file structure similar to this.

- Plugin/
-- plugin-init.php
-- custom-outer-block/
--- package.json
--- package-lock.json
--- node_modules/
--- build/
---- index.js
---- index.js.map
--- src/
---- index.js
-- custom-inner-block/
--- package.json
--- package-lock.json
--- node_modules/
--- build/
---- index.js
---- index.js.map
--- src/
---- index.js
-- custom-dynamic-block/
--- package.json
--- package-lock.json
--- node_modules/
--- build/
---- index.js
---- index.js.map
--- src/
---- index.js
-- components/

It seems a bit strange to have that many React projects and duplicate node moduels in a single plugin or theme. Also shifting between the different blocks while developing, having to start them separately, doesn't make much sense to me.

I'm certain that there's something I'm not getting.

So long story short; Is there a way to combine all blocks into a single React project, so I only have to run create-react-app once - and have the files compile to separate build files that can be used with register_block_type?

  • create-react-app is meant as a helper for people who may not be familiar with React and js build tools in general. In your case, it sounds like it's just making things more complicated. You can load a single js file that contains multiple blocks without multiple npm configs. I have an "editor.js" file that just imports the index.js file for each block I'm adding, which contains a "registerBlockType()" call. You might look into other build tools. I use laravel.mix, which is just a simplified wrapper on webpack. – SkyShab Sep 8 '19 at 14:29
1

Gutenberg-examples isn't a single plugin, you can consider it five plugins at once, it is intended to be working example for each part of the tutorial.

You have a lot of patterns you can follow, currently, core blocks are defined each in a folder like this, coblocks also follows the same pattern.

block-library/
  - image/
    -- edit.js
    -- index.js
    -- save.js
    -- styles.css
  - quote/
    -- edit.js
    -- index.js
    -- save.js
    -- styles.css
  - index.js (root index)
  - styles.css (root style)

Each save.js & edit.js file contains the code for that function.

Each index.js for a block contains references to said files, plus some other settings like title & category

preformed code block index.js file example (simplified)

import edit from './edit';
import save from './save';

export const name = 'core/code';

export const settings = {
    title: 'Code',
    description: 'Display code snippets that respect your spacing and tabs.',
    category: 'formatting',
    icon: 'image',
    edit,
    save,
};

root styles.css just import each block style css.

root index.js file is the one responsible for calling & registering the blocks, so it goes something like this (simplified)

import { registerBlockType } from '@wordpress/blocks';

import * as image from './image';
import * as quote from './quote';
import * as code from './code';

const blocks = [
    image,
    quote,
    code
];

function registerBlock( block ) {
    const { name, setting } = block;
    registerBlockType( name, settings );
}

blocks.forEach( registerBlock );

or a larger example at coblocks

your plugin should call that index and register each block with the same file, just different block name.

see how coblocks does it

As for the build process, you don't need node modules at each block, you just need to run it at the root index.js file.

For even a more simpler approach, you can use wp-scripts it's used internally by gutenberg and also by gutenberg-examples, you install it at the root file of your plugin and add those scripts to your package.json

"scripts": {
    "build": "wp-scripts build",
    "start": "wp-scripts start"
}

it assumes that your code (root index.js) is in src/index.js and your output is at build/index.js (you can change that).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.