-
Notifications
You must be signed in to change notification settings - Fork 22
Description
Summary
WordPress 6.7 introduced wp_register_block_metadata_collection() and WordPress 6.8 added wp_register_block_types_from_metadata_collection() to improve block registration performance. These APIs allow plugins to register blocks from a pre-compiled PHP manifest file instead of parsing individual block.json files at runtime.
10up-toolkit should support generating this manifest file as part of its build process.
The Problem
Currently, when WordPress registers blocks, it must:
- Locate each
block.jsonfile on disk - Read the file contents
- Parse the JSON
- Process the metadata
For plugins with multiple blocks, this filesystem I/O and JSON parsing happens on every request, adding unnecessary overhead.
The Solution: Block Manifests
A block manifest is a single PHP file that contains all block metadata as a PHP array. Since PHP can load arrays directly without parsing, this eliminates the JSON parsing overhead and reduces filesystem reads to a single file.
Manifest File Format
The blocks-manifest.php file returns an associative array where keys are block directory names and values are the block metadata:
<?php
// This file is generated. Do not modify it manually.
return array(
'accordion' => array(
'$schema' => 'https://schemas.wp.org/trunk/block.json',
'apiVersion' => 3,
'name' => 'my-plugin/accordion',
'title' => 'Accordion',
'category' => 'design',
'icon' => 'menu',
'editorScript' => 'file:./index.js',
'editorStyle' => 'file:./index.css',
'style' => 'file:./style-index.css',
'render' => 'file:./render.php',
// ... rest of block.json contents
),
'tabs' => array(
'$schema' => 'https://schemas.wp.org/trunk/block.json',
'apiVersion' => 3,
'name' => 'my-plugin/tabs',
'title' => 'Tabs',
// ... rest of block.json contents
),
);Registration Code
With the manifest, registration becomes a single function call:
function my_plugin_register_blocks() {
$blocks_dir = __DIR__ . '/build/blocks';
$manifest = __DIR__ . '/build/blocks-manifest.php';
// WordPress 6.8+: Single call registers all blocks
if ( function_exists( 'wp_register_block_types_from_metadata_collection' ) ) {
wp_register_block_types_from_metadata_collection( $blocks_dir, $manifest );
return;
}
// WordPress 6.7: Register collection, then loop
if ( function_exists( 'wp_register_block_metadata_collection' ) ) {
wp_register_block_metadata_collection( $blocks_dir, $manifest );
$blocks = require $manifest;
foreach ( array_keys( $blocks ) as $block_slug ) {
register_block_type_from_metadata( $blocks_dir . '/' . $block_slug );
}
return;
}
// WordPress < 6.7: Traditional registration
$blocks = require $manifest;
foreach ( array_keys( $blocks ) as $block_slug ) {
register_block_type( $blocks_dir . '/' . $block_slug );
}
}
add_action( 'init', 'my_plugin_register_blocks' );Proposal for 10up-toolkit
1. Add Manifest Generation to Build Process
Generate blocks-manifest.php automatically when building blocks:
# Current
10up-toolkit build
# Would also generate blocks-manifest.php in the output directoryThis should:
- Scan all block directories for
block.jsonfiles - Combine them into a single PHP array
- Output to a configurable location (default:
build/blocks-manifest.php)
2. Configuration Options
Allow configuration via 10up-toolkit.config.js:
module.exports = {
blocksManifest: {
// Enable/disable manifest generation (default: true)
enabled: true,
// Input directory containing blocks (default: 'build/blocks' or detected)
input: 'build/blocks',
// Output path for manifest file
output: 'build/blocks-manifest.php',
// Optional: Custom transformation for manifest entries
// transform: (blockMetadata, blockSlug) => blockMetadata,
}
};3. Watch Mode Support
Regenerate the manifest when block.json files change during development:
10up-toolkit start
# Watches for block.json changes and regenerates manifestImplementation Considerations
Directory Structure Detection
10up-toolkit should detect where blocks are located. Common patterns:
# Pattern 1: Blocks in subdirectories
src/blocks/accordion/block.json
src/blocks/tabs/block.json
# Pattern 2: Blocks at root
src/block.json (single block)
# Pattern 3: Multiple entry points
src/blocks/editor/accordion/block.json
Handling render Callbacks
The wp_register_block_types_from_metadata_collection() function doesn't support render_callback directly. Projects using dynamic blocks with PHP render callbacks need to use the block_type_metadata_settings filter:
add_filter( 'block_type_metadata_settings', function( $settings, $metadata ) {
if ( isset( $metadata['name'] ) && str_starts_with( $metadata['name'], 'my-plugin/' ) ) {
// Add render callback based on block name
$block_slug = str_replace( 'my-plugin/', '', $metadata['name'] );
$render_file = __DIR__ . "/build/blocks/{$block_slug}/render.php";
if ( file_exists( $render_file ) ) {
$settings['render_callback'] = function( $attributes, $content, $block ) use ( $render_file ) {
ob_start();
include $render_file;
return ob_get_clean();
};
}
}
return $settings;
}, 10, 2 );This is worth documenting but shouldn't affect manifest generation.
Block Slug Conflicts
The manifest uses directory names as keys. If a project has blocks in directories with identical names (e.g., blocks/editor/card and blocks/frontend/card), only one will be included. This is a known limitation of the WordPress manifest format.
10up-toolkit should either:
- Warn when duplicate directory names are detected
- Use full relative paths as keys (would require changes to registration code)
Comparison with @wordpress/scripts
The @wordpress/scripts package already supports this via:
{
"scripts": {
"build": "wp-scripts build --blocks-manifest",
"start": "wp-scripts start --blocks-manifest"
}
}10up-toolkit should provide equivalent functionality with similar ease of use.
Benefits
- Performance: Eliminates JSON parsing and reduces filesystem reads on every request
- Simpler registration: One function call registers all blocks
- Future-proof: Aligns with WordPress core's recommended approach
- Backward compatible: Manifest can be used with fallback logic for older WordPress versions