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.json file 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 directory
This should:
- Scan all block directories for
block.json files
- 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 manifest
Implementation 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
References
Summary
WordPress 6.7 introduced
wp_register_block_metadata_collection()and WordPress 6.8 addedwp_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 individualblock.jsonfiles 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:
block.jsonfile on diskFor 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.phpfile returns an associative array where keys are block directory names and values are the block metadata:Registration Code
With the manifest, registration becomes a single function call:
Proposal for 10up-toolkit
1. Add Manifest Generation to Build Process
Generate
blocks-manifest.phpautomatically when building blocks:This should:
block.jsonfilesbuild/blocks-manifest.php)2. Configuration Options
Allow configuration via
10up-toolkit.config.js:3. Watch Mode Support
Regenerate the manifest when
block.jsonfiles 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:
Handling
renderCallbacksThe
wp_register_block_types_from_metadata_collection()function doesn't supportrender_callbackdirectly. Projects using dynamic blocks with PHP render callbacks need to use theblock_type_metadata_settingsfilter: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/cardandblocks/frontend/card), only one will be included. This is a known limitation of the WordPress manifest format.10up-toolkit should either:
Comparison with @wordpress/scripts
The
@wordpress/scriptspackage 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
References