4

I have created a custom block and can create another one in the same plugin but it will get messy if I carry on because everything has to be done in the same index.js file and php file or so it would seem. This is new to me so perhaps there is a simple way to do this.

But I tried to create a blocks folder and then put a src folder in there as well as an index.js file, so each block folder basically had its own css file and js file etc. But when I run npm run start it does not create the build folders in the subfolders like it does in the root.

So my current folder structure looks like:

build 
index.php
package.json
src
 - index.js
 - index.scss

where I was wondering if I could have multiple blocks something like this perhaps

build
index.php
hero.php
call-to-action.php
package.json
blocks
 - hero
  -- src
    --- index.js
    --- index.scss
 - call-to-action
  -- src
   --- index.js
   --- index.scss

package.json

{
  "name": "custom-blocks",
  "version": "1.0.0",
  "description": "",
  "main": "index",
  "scripts": {
    "build": "wp-scripts build",
    "start": "wp-scripts start",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@wordpress/scripts": "^19.1.0"
  }
}

index.php

<?php
/*
Plugin Name: custom blocks
Description: custom blocks
Version: 1.0
Author: ...
Author URI: ...
License: GPLv2 or later
*/

if ( ! defined( 'ABSPATH' ) ) exit;

class myCustomBlocks {
    function __construct() {
        add_action('init', array($this, 'adminAssets'));
    }
    
    function adminAssets() {
        wp_register_style('quizeditcss', plugin_dir_url(__FILE__) . 'build/index.css');
        wp_register_script('ournewblocktype', plugin_dir_url(__FILE__) . 'build/index.js', array('wp-blocks', 'wp-element', 'wp-editor'));
        register_block_type('ourplugin/hero-block', array(
            'editor_script' => 'ournewblocktype',
            'editor_style'  => 'quizeditcss',
            'render_callback' => array($this, 'theHTML')
        ));
    }

    function theHTML($attributes) {
       ob_start(); ?>
            <p>Here is some data: <?php echo esc_html($attributes['someAttribute']); ?></p>
       <?php return ob_get_clean();
    }
}

$myCustomBlocks = new myCustomBlocks();

index.js

import "./index.scss";
import {
  TextControl,
  Flex,
  FlexBlock,
  FlexItem,
  Button,
  Icon,
} from "@wordpress/components";

wp.blocks.registerBlockType("ourplugin/hero-block", {
  title: "Hero block",
  icon: "smiley",
  category: "common",
  attributes: {
    title: {
      type: "string",
    },
  },
  edit: EditComponent,
  save: function () {
    return null;
  },
});

function EditComponent(props) {
  return (
    <div className="some-jsx">
      Some block jsx here
    </div>
  );
}
1
  • it's definitely possible to have more than one block in a plugin, though you'll need multiple block.json files and registrations. The building separate files for JS for each block part though I'm not sure how to do with WP Scripts, though you don't need to use WP Scripts to do it
    – Tom J Nowell
    Nov 14, 2021 at 18:02

1 Answer 1

5

I've updated this answer with more than one way to accomplish this. Though maybe it could go without saying the context of these is using the @wordpress/scripts package for development.

Single bundle for all blocks

This setup is most suitable for building some combination of blocks that have parent/child relationships (like Columns/Column) and thus one wouldn't be used without the other.

Specify multiple entry points in the build and start scripts. Example with start:

"start": "wp-scripts start --entry ./hero/src/index.js ./call-to-action/src/index.js"

That will bundle the js into main.js as opposed to the default of index.js so the editorScript path in the block’s json will need updated. (Since a single bundle is output only one of the blocks’ json files will actually need to specify it).

Separate bundles per block

To have separate files output for each block there are two ways I'm aware of.

Provide your own webpack config file

This will end up being the most flexible option and can be quite simple. For the blocks in the question a config like the following should do:

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

module.exports = {
    ...defaultConfig,
    entry: {
        'hero': './blocks/hero/src',
        'call-to-action': './blocks/call-to-action/src',
    },
};

Ryan Welcher has an example repo and a video walk-through of its creation (that link is to the part about creating the custom webpack config).


An update re: Ryan Welcher repo and video.

@wordpress/scripts package now supports multiple blocks by default. Check out this video for more

A very informative video around this subject. The relevance here is that a custom webpack config is not needed if folder structure is like:

src/(block-1|block-2|something-else)/block.json.

Specify multiple entry points in the build and start scripts without using (--entry)

This is the way the official docs currently demonstrate:

"build:custom": "wp-scripts build entry-one.js entry-two.js --output-path=custom"

A potential catch here is that with the latest versions of @wordpress/scripts (19.1.0 and probably back to 18) the filenames of each entry point must be unique or else files will be left out of the build. So for a project structure as exemplified in the question, it would fail to include both blocks because they’re both named index.js. In earlier versions of @wordpress/scripts both would be included although bundled into a single file. This behavior may change.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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