New block type registration APIs to improve performance in WordPress 6.7

WordPress 6.7 introduces a new function wp_register_block_metadata_collection() which allows plugins to improve the performance of registering their blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. types, especially for plugins that register multiple block types.

Expanding WordPress CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. behavior to plugins

Since WordPress 6.1, WordPress Core has included a mechanism to improve performance for loading all of the built-in block types: As part of the build process, the individual block.json files are being parsed into a single blocks-json.php file that returns all of their data in an array. This notably enhances performance by avoiding many costly filesystem and JSONJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. operations on every single WordPress request. See #55005 and its dev note for context on the original change.

The way this mechanism was implemented only worked for WordPress Core itself though. Plugins so far have not been able to achieve the same benefits. Especially for plugins that include many block types themselves, this effectively meant a performance penalty. This is going to change as part of WordPress 6.7.

Registering block metadata collections

Plugins can now optionally register a PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher “manifest” file, which includes all the metadata for their block types. For any block type that is being registered, WordPress Core will now check whether such a manifest file is present covering the block type, and if so, it will use the data from the manifest file instead of reading and parsing the block type’s block.json file directly.

In order to use this new capability, pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party developers need to use the new wp_register_block_metadata_collection() function, which takes two parameters:

  • $path: The base path in which block files for the collection reside.
  • $manifest: The path to the manifest file for the collection.

Every block.json file that is supposed to be part of the collection must reside within the provided $path, within its own directory matching the block type name (without the block namespace). Please see the full example for further clarification.

Note that registering block metadata collections does not replace the need to register individual block types at this point. You will still need to call register_block_type() or register_block_type_from_metadata() for every block type that is part of a collection. Usage of the new function is optional to help performance, but it is strongly recommended particularly for plugins that register several block types. Please continue reading for additional tooling to facilitate this process.

Automatically generating a block metadata collection manifest

Plugin developers are responsible for generating and maintaining the manifest file they register for their plugin’s block types metadata collection. To make this process simple, a new command build-blocks-manifest has been implemented as part of the @wordpress/scripts NPM package, released as part of version 30.3.0.

The wp-scripts build-blocks-manifest command accepts two arguments:

  • --input: The directory in which the block types reside. The default for this is “build”.
  • --output: The file path for where to store the built block metadata collection manifest. The default for this is “build/blocks-manifest.php”.

Effectively, the arguments for this command are equivalent to the parameters for wp_register_block_metadata_collection(): The --input argument is the equivalent of the $path parameter, and the --output argument is the equivalent of the $manifest parameter.

Full example

For this example, let’s say you have a plugin my-block-library that registers 3 block types:

  • my-block-library/pricing
  • my-block-library/services
  • my-block-library/testimonial

The source code for these block types is implemented in the plugin’s src directory, more specifically in directories as follows:

  • src/pricing for the my-block-library/pricing block.
  • src/services for the my-block-library/services block.
  • src/testimonial for the my-block-library/testimonial block.

By using the existing wp-scripts build command, the code gets built into the plugin’s build directory, with the same subdirectories for each block type.

After running the build, you can use the new wp-scripts build-blocks-manifest command. Since the plugin is using the default location for its block types, you don’t need to pass any arguments to the command. Simply run wp-scripts build-blocks-manifest, and it will read the block.json metadata for all three blocks from the build directory and combine them into a build/blocks-manifest.php file.

The manifest file will look something like this:

<?php
// This file is generated. Do not modify it manually.
return array(
	'pricing' => array( /* Block metadata. */ ),
	'services' => array( /* Block metadata. */ ),
	'testimonial' => array( /* Block metadata. */ )
);

You can use the same two commands in the future, whenever you have made changes to the block types and their implementation:

wp-scripts build
wp-scripts build-blocks-manifest

With the manifest file generated, you can now register the block metadata collection as follows:

wp_register_block_metadata_collection(
	WP_PLUGIN_DIR . '/my-block-library/build',
	WP_PLUGIN_DIR . '/my-block-library/build/blocks-manifest.php'
);

Last but not least, don’t forget to register the actual block types:

register_block_type_from_metadata( WP_PLUGIN_DIR . '/my-block-library/build/pricing' );
register_block_type_from_metadata( WP_PLUGIN_DIR . '/my-block-library/build/services' );
register_block_type_from_metadata( WP_PLUGIN_DIR . '/my-block-library/build/testimonial' );

And that’s already it, you have everything in place for improved performance of the plugin’s block types registration.

Summary and further reading

The new wp_register_block_metadata_collection() and its tooling support in @wordpress/scripts are a powerful combination to improve performance of register block types from your plugin. They make the process almost effortless, so if your plugin registers block types, please consider incorporating this approach into your development workflow and plugin codebase.

Please see the following links for further reading:

  • TracTrac An open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress. ticketticket Created for both bug reports and feature development on the bug tracker. #62002 for implementing the wp_register_block_metadata_collection() function.
  • GutenbergGutenberg The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc. https://wordpress.org/gutenberg/ pull request #65866 for implementing the wp-scripts build-blocks-manifest command.

Props @gziolo and @mreishus for review and proofreading.

#6-7, #dev-notes, #dev-notes-6-7

Roster of design tools per block (WordPress 6.7 edition)

Below you find a table that lists all coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. blocks available in the inserter marks in the grid the feature they support in the blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. editor. It’s a basic lookup table that helps developers to find the information quickly.

While this post is released as part of 6.7, the content summarizes changes between 6.1 and 6.7. This is an updated of the 6.6 edition and provides a cumulative list of design supports added with the last six WordPress releases. The icon ☑️ indicates new in 6.7.

Besides adding Border Controls to a long array of blocks, In version 6.7 writingMode was added to Site title, Site tagline, verse blocks and the button element. As that’s typography subletting it’s not indicated separately in below roster.

The features covered are:

  • Align
  • Typography,
  • Color,
  • Dimension,
  • Border,
  • Layout,
  • Gradient,
  • Duotone,
  • Shadow,
  • Background image
  • Pattern overrides / Block Bindings (PO/BB)

Work in progress

The issue Tracking: Addressing Design Tooling Consistency lists tracking issues for individual block supports.

Props to @fabiankaegy for review.

#6-7, #dev-notes, #dev-notes-6-7, #editor

Subscribe to changes in the Interactivity API state and context on client-side navigation in 6.7

Interactivity APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. offers a region-based navigation feature that dynamically replaces a part of the page without a full page reload. In fact, the Query blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. natively supports this feature when the “Force page reload” toggle is disabled. Developers can use the same functionality in custom blocks by calling action.navigate from the @wordpress/interactivity-router script module. In WordPress 6.7, several changes were introduced to improve the developer experience by making the behavior fully predictable.

During WordPress 6.7 development, we found an issue with the client-side navigation feature the @wordpress/interactivity-router provides: interactive blocks outside of interactive regions could be updated as a result of an actions.navigate call if they depended on state properties. The main problem was that the state properties were always overwritten with the values from the new HTMLHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. page, leading to unexpected updates.

Moreover, the same issue affected blocks using the data-wp-context directive, making them work differently depending on whether they were placed inside a router region. In that case, the context was overwritten anytime the HTML was updated with an actions.navigate call.

As a result, this “overwrite behavior” was turned off for both the Interactivity API state and context. Calling actions.navigate will now only add new properties to the state or context and will never overwrite existing properties.

However, updating blocks based on state/context changes is still a legitimate use case. Since WordPress 6.7, a new API is available to subscribe to those changes, exposed from the @wordpress/interactivity module: getServerState() and getServerContext().

These functions return an object that is analogous to the state/context returned by store()/getContext(), with a couple of differences:

  • The object returned is read-only.
  • The object is updated after actions.navigate() calls, using the values defined in the HTML of the page loaded by actions.navigate().
  • Developers cannot directly use its properties in directives, but they can use callbacks to subscribe to changes in its properties and update the usual state/context.

The following example is incomplete but explains how to use the new API. Let’s say we want to develop an interactive Quiz block that updates the question on the screen every time the user submits the answer. Below is a simplified HTML snippet for such a block.

<form
  class="wp-block-quiz-question"
  data-wp-interactive="example/quiz"
  data-wp-router-region="quiz-question"
  data-wp-on--submit="actions.goToNextQuestion"
  data-wp-watch="callbacks.updateQuestion"
  data-wp-context='
    {
      "question": "What is the capital of France?",
      "answers": ["Paris", "London", "Rome", "Berlin"],
      "correctAnswer": 0,
      "nextQuestion": "/link-to-next-question"
    }
  '
>
  <fieldset>
    <legend data-wp-text="context.question"></legend>
    <template data-wp-each--answer="context.answers">
      <div>
        <input
          type="radio"
          data-wp-bind--id="context.answer"
          data-wp-bind--value="context.answer"
        />
        <label
          data-wp-bind--for="context.answer"
          data-wp-text="context.answer"
        ></label>
      </div>
    </template>
    <button type="submit">Submit</button>
  </fieldset>
</form>


As we can see, the <form> element contains the following directives:

  • data-wp-namespace, with value example/quiz.
  • data-wp-router-region, defining a region that should update on navigation.
  • data-wp-context, with all the data relative to a single question. On the HTML inside the <fieldset> element, we can see all the directives that depend on the context.
  • data-wp-on—submit, which assigns the actions.goToNextQuestion function to navigate to the next question.
  • data-wp-watch, with callbacks.updateQuestion to update the context. This one is important, as it will run every time any read properties inside change, including properties from getServerContext().

Next is a reduced implementation of these functions:

import {
  store,
  getContext,
  getServerContext,
} from "@wordpress/interactivity";

store("example/quiz", {
	actions: {
    *goToNextQuestion(event) {
      event.preventDefault();
      const { actions } =
        yield import("@wordpress/interactivity-router");
      yield actions.navigate(getContext().nextQuestion);
    },
  },
  callbacks: {
    updateQuestion() {
      const clientContext = getContext();
      const serverContext = getServerContext();
      clientContext.question = serverContext.question;
      clientContext.answers = serverContext.answers;
      clientContext.correctAnswer = serverContext.correctAnswer;
      clientContext.nextQuestion = serverContext.nextQuestion;
    },
  },
});


Now, imagine we click “submit” and navigate to the next question, and the Interactivity API runtime receives the HTML below. As we can see, the data-wp-context data has changed in the server. That will trigger the data-wp-watch directive using callbacks.updateQuestion, and the context will be updated in the client, making all the HTML inside <fieldset> to be modified accordingly.

<form
  class="wp-block-quiz-question"
  data-wp-interactive="example/quiz"
  data-wp-router-region="quiz-question"
  data-wp-on--submit="actions.goToNextQuestion"
  data-wp-watch="callbacks.updateQuestion"
  data-wp-context='
    {
      "question": "Which is the closest planet to the Sun?",
      "answers": ["Mercury", "Venus", "Earth", "Mars"],
      "correctAnswer": 0,
      "nextQuestion": "/link-to-another-question"
    }
  '
>
	<fieldset>
		<!-- The fieldset element's content remains the same. -->
	</fieldset>
</form>


In order not to extend too much, suffice it to say that the example would be similar for getServerState(), with the difference that the data is defined in the current page with the wp_interactivity_state() function in PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher, instead of the data-wp-context directive.

GitHubGitHub GitHub is a website that offers online implementation of git repositories that can easily be shared, copied and modified by other developers. Public repositories are free to host, private repositories require a paid subscription. GitHub introduced the concept of the ‘pull request’ where code changes done in branches by contributors can be reviewed and discussed before being merged be the repository owner. https://github.com/ Pull Request: #65151

#6-7, #dev-notes, #dev-notes-6-7

Updates to Script Modules in 6.7

WordPress 6.7 introduces a new @wordpress/a11y script module and a new APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. to pass script module data from the server to the client.

Continue reading

#6-7, #dev-notes, #dev-notes-6-7, #javascript

Automatic conversion of HEIC images to JPEG in WordPress 6.7

In WordPress 6.7, HEIC image uploads will be automatically converted to JPEG on the server when possible.

This allows you to view HEIC images in WP Adminadmin (and super admin) and use them in posts
and pages regardless of whether a visitor’s browser supports HEIC. Browser support for HEIC is low while the occurrence of HEIC images is common as they are the default storage format used by Apple devices.

 
The original HEIC image can be downloaded via a link on the attachment page.

Screenshot of an attachment in WordPress with 'Original image' field circled

Conversion is only done if the server has a version of Imagick that supports HEIC. You can see whether a server supports HEIC in Tools → Site Health → Info → Media Handling → ImageMagick supported file formats.

Screenshot of the 'ImageMagick supported file formats' field in WordPress

If conversion is not possible, a warning is displayed to the user encouraging them to manually convert the image to JPEG. This was the default behaviour prior to WordPress 6.7.

Screenshot of an error message in WordPress informing the user that the image cannot be displayed in a browser

Automatic conversion of HEIC images to JPEG can be disabled using the image_editor_output_format filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output..

add_filter( 'image_editor_output_format', function( $output_format ) {
    unset( $output_format['image/heic'] );
    return $output_format;
} );

#6-7 #core-media #dev-note #dev-notes #dev-notes-6-7