What’s the right way to instantiate new blocks and/or the plugin itself in toto when using wppb architecture?

Question

Long story on how I got here, but I’m building a plugin for a new block, and I’m doing it starting from the WordPress Plugin Boilerplate. I think something is not playing well between the way the plugin itself is run and the way the blocks are called. The reason I think this is, although everything works fine on the public side, on the admin side, if I add one of the new blocks to a post, the plugin gets run at least four times (and more, if there are more of the same block type on the page). Maybe this is right, but it doesn’t seem right, so: what’s the best way to register new blocks from within the WPPB framework; and/or, if the plugin is a new block, does something different need to be done with where the plugin is hooked/run? Here’s what I have right now:

the plugin runs the same way it does in the base template:

/**
 * Begins execution of the plugin.
 *
 * Since everything within the plugin is registered via hooks,
 * then kicking off the plugin from this point in the file does
 * not affect the page life cycle.
 *
 * @since    0.99.1
 */
function run_my_block_plugin() {

        $plugin = new My_Block_Plugin();
        $plugin->run();

}
run_my_block_plugin();

I’ve left that comment from the template at the beginning, because I’m wondering if it’s not true — is this supposed to still Just Work, or should I be doing something different because of the block registration (see below)? As I said, if I add a block to a page, on the admin side, this $plugin->run happens at least four times … which doesn’t seem right.

This core class then loads dependencies, sets up i18n, and registers "public hooks" and "private hooks". Given this architecture, I’ve split things so the block registration and edit function are on the admin side of things, and the rendering is on the public side of things (I needed to do ServerSideRender, anyhow, so this division kind of works out).

On the public side, I define the callback for the server-side render as a public function, and enqueue the javascript:

class My_Block_Plugin_Public {
        // ...
        public function enqueue_scripts() {

                wp_enqueue_script( $this->plugin_name . '-public',
                    plugin_dir_url( __FILE__ )
                        . 'js/my-block-plugin-public.js',
                    array( 'here', 'are', 'some', 'dependencies' ),
                    $this->date_version(
                        'js/my-block-plugin-public.js'), false ); // add file mtime to version
                // ... do wp_localize_script and enqueue dependencies
        }
        // ...
        public function render( $block_attributes, $content = '' ) {
                // returns a string that is the html to be modified by my-block-plugin-public.js
        }
}

The core class uses the loader class’s add_action method to add the above enqueue_scripts, and I have it adding them to init:

    $this->loader->add_action( 'init',
        $this->plugin_public, 'enqueue_scripts' );

On the admin side of things, I’ve added a new method for registering the block:

class My_Block_Plugin_Admin {
        // ...
        public function enqueue_gutenberg_scripts() {
                // everything in block/js is the transpile output from ESNext
                $asset_file = include( plugin_dir_path( __FILE__ )
                    . 'block/js/my-block-plugin-admin.asset.php');
                    
                // register the compiled JS for the backend
                wp_register_script( $this->plugin_name . '-block-edit',
                    plugin_dir_url( __FILE__ )
                        . 'block/js/my-block-plugin-admin.js',
                    $asset_file['dependencies'],
                    $this->date_version(
                        'block/js/my-block-plugin-admin.js'));
                        
                register_block_type( 'my-block-plugin/my-block',
                    array(  
                        'attributes' => array(
                            // ...
                        ),
                        'editor_script' => $this->plugin_name . '-block-edit',
                        'render_callback' => array( $this->plugin_public,
                            'render')
                ) );
        }                         
}

As with the public scripts, the core class uses the loader class’s add_action method to add the above enqueue__gutenberg_scripts, and here I’m also adding them to init, although as I type this, I’m wondering if that isn’t a problem. init is what the WordPress Create A Block Tutorial uses, but the WPPB templated uses admin_enqueue_scripts for the other admin scripts. In any case:

    $this->loader->add_action( 'init',
        $plugin_admin, 'enqueue_gutenberg_scripts' );

The block is also registered from the JavaScript side (although it seems redundant, I believe this is required). In ESNext,

// index.js
/**
 * WordPress dependencies
 */
import { __, _x } from "WPBeginner - WordPress Tutorials/i18n";
import { registerBlockType } from "WPBeginner - WordPress Tutorials/blocks";

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

const { name } = metadata;

const settings = {
    title: __('My Block Plugin', 'my-text-domain'),
    description: __('A New Block Type!',
      'my-text-domain'),
    keywords: [ _x('a word', 'block keywords', 'my-text-domain') ],
    icon: 'chart-bar',
    category: 'widgets',
    attributes: {
        // ...
    },
    edit,
}

registerBlockType( name, settings );

// block.json
{
        "apiVersion": 2,
        "name": "my-block-plugin/my-block",
        "category": "widgets"
}

// edit.js
export default function MyBlockPluginEdit( props ) {
const {
attributes: {
// …
},
clientId,
setAttributes,
} = props;
console.log(‘Post ID is ‘, post_id); // this is where I 1st noticed the problem
// …

    const BlockRender = () => {
            return(
                <ServerSideRender
                    block={ name }
                    attributes={{ ...attributes }} />
            );
    }

    const BlockPlaceholder = () => {
        return(
            <Placeholder
              icon='chart-bar'
              label="My Block"
              instructions={ __( 'Get started!', 'my-text-domain') }>
                { <MoreJavaScript /> }
            </Placeholder>
        );
    };

    const Component = myTest
            ? BlockRender
            : BlockPlaceholder;

    return <Component />;

}

So, general question: does this seem like the Right Way to do new blocks in WPPB? Specific question: is it right that the plugin gets run many, many times? See the "this is where I first noticed the problem" comment, above. It was logging 4, 6, 10, 12 times to console. But, after digging into things, I realized it’s actually executing the run_my_block_plugin(); from the core template that many times, which makes me question how I’m doing all of this.

Background / The Long Story
Back in September, I decided I wanted to add some "simple" functionality to my blog. Given the nature of things, I thought it would be better to add it as a plugin, than to add functions to my template. In general, I try to do things the Right Way, so I looked around for the best, current way to do plugins, and found WPPB referenced as a good way to do things from the WordPress developer Best Practices. After a while, I decided that it would make even more sense to do this as a new block type, but I was already many weekends down the road of doing things in the WPPB architecture, and after digging into block development, and realizing I was going to need PHP and server-side rendering anyhow, I decided to stay there. Now I’m neck deep in JavaScript and React (about neither of which do I know anything), and TBH all of the above seems rather over-complicated and I’m slightly regretting this decision, but I’m hoping at the end I come out with a plugin that is well architected, easy to maintain, and that at least a few other people will find useful (and hopefully enough other people that some of them can help support it, because I am not a developer by day 🙂 ).

0
philolegein 1 month 0 Answers 8 views 0

Leave an answer