Performance improvements to the REST API

WordPress 6.1 brings a number of key improvements to the REST APIREST API The REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”) https://developer.wordpress.org/rest-api/ to increase performance. These improvements decrease the number of database queries that are run on each REST API request. 

Avoid unnecessarily preparing item links

Prior to WordPress 6.1, the prepare_links method in the REST API was called in all controllers. If the _fields parameter is passed to the REST API request, it might mean that the links field is not requested and would never be returned in the response. This is wasteful, as prepare_links can contain database calls or other complex logic that would be run even if it never returned the response. 

In 6.1 prepare_links are only called if requested in the response, when links are requested in fields or the _embedded parameter is passed. As part of this work, the taxonomyTaxonomy A taxonomy is a way to group things together. In WordPress, some common taxonomies are category, link, tag, or post format. https://codex.wordpress.org/Taxonomies#Default_Taxonomies. and post type controllers have now been updated to implement said prepare_links method to bring them in line with other REST API controllers. 

This is the code example of implementing this change in custom REST API controllers.

Before

$response = rest_ensure_response( $data );
$links = $this->prepare_links( $post );
$response->add_links( $links );

return $response;

After

$response = rest_ensure_response( $data );

if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) {
  $links = $this->prepare_links( $post );
  $response->add_links( $links );
}

return $response;

This logic conditionally calls prepare_links only if _links or _embedded is requested. This logic only applies when using the _fields query parameter. When not using _fields, links are included in the response as normal. 

For more info see 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.: #52992, #56019, #56020

Improvement to the Posts controller

When running profiling tools against the responses of REST API requests, it was discovered that post controllers request a lot of linked data to each post. For example, when returning a post in a REST API response, linked data such as author (user), featured imageFeatured image A featured image is the main image used on your blog archive page and is pulled when the post or page is shared on social media. The image can be used to display in widget areas on your site or in a summary list of posts., and parent post were all requested. As these linked items were not primed in caches, it could mean that for each post in the REST API response there would be 3 separate database queries: one for the user, one for the featured image, and another for the parent post. 

In WordPress 6.1 all the caches are primed in a single database query and there are new helper functions to enable this:

update_post_author_caches

Takes an array of posts and primes users caches in a single query. 

update_post_parent_caches

Takes an array of posts and primes post parents in a single query. 

update_menu_item_cache

Takes an array of posts and primes post / terms link to menu items single query. 

The existing function update_post_thumbnail_cache was used to prime featured image caches. These functions are also being rolled out to other parts of the coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. that can benefit from priming caches in a single place. 

For more info see Trac tickets: #55592, #55593, #55620    

Improvements to other controllers

The comments and user controllers have also been improved: User controller now primes user metaMeta Meta is a term that refers to the inside workings of a group. For us, this is the team that works on internal WordPress sites like WordCamp Central and Make WordPress. in a single query and the comments controller now primes the linked post cache in a single query. Improvements were made to the post search controller to improve database performance along with the media controller. 

For more info see Trac tickets: #55674, #56272, #55677, #55716

Props to @flixos90 and @milana_cap for peer review and @mxbclang and @webcommsat for proofreading.

#6-1, #core-restapi, #dev-notes, #dev-notes-6-1, #performance, #rest-api

Block styles generation (Style Engine)

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., known as the “Style Engine”, has been shipped in WordPress 6.1 to provide a single, centralized agent responsible for generating and rendering consistent 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. supports styles on the client-side and server-side.

For the 6.1 release, the focus has been on consolidating how WordPress generates block supports (border, color, spacing, and typography) and layout styles in the editor and frontend.

Before 6.1, a multitude of instances existed where block supports CSSCSS Cascading Style Sheets. and class names were compiled and/or enqueued, both in JavaScriptJavaScript JavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser. https://www.javascript.com and PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher, resulting in a great deal of duplication in both code and frontend output. 

It’s imperative to note that the primary and very specific goal of the Style Engine is to improve how the Block editor compiles and renders block CSS, not to provide a universal approach to generating CSS.

Key enhancements in 6.1

WordPress 6.1 introduces a common way to compile, optimize and sanitize block supports styles. Previously block support CSS and class names were generated on demand creating inconsistencies and duplicated code.

Moreover, and one of the biggest improvements, 6.1 brings a way to add styles across the application to a single stylesheet, and also combine repetitive layout-specific CSS rules.

This functionality reduces the number of inline HTMLHTML HyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. style tags printed to the page: all block supports and layout styles will be rendered to the page as a single, combined stylesheet.

For example, before 6.1, when a page included multiple block layout styles, a CSS rule for each block would be printed in a separate HTML style tagtag A directory in Subversion. WordPress uses tags to store a single snapshot of a version (3.6, 3.6.1, etc.), the common convention of tags in version control systems. (Not to be confused with post tags.). The amount of unique style tags for a single page were potentially without limit.

<style>.wp-block-columns.wp-container-1 { flex-wrap: nowrap; }</style>
<style>.wp-block-columns.wp-container-2 { flex-wrap: nowrap; }</style>
<style>.wp-block-columns.wp-container-3 { flex-wrap: nowrap; }</style>

As of 6.1, layout CSS rules with matching CSS definitions are combined in a single HTML style tag:

<style>.wp-block-columns.wp-container-1, .wp-block-columns.wp-container-2, .wp-block-columns.wp-container-3 { flex-wrap: nowrap; }</style>

Public Functions (API)

The following is a general overview of the public functions introduced in 6.1.

Please refer to the API documentation: @wordpress/style-engine for detailed information and example usage.

wp_style_engine_get_styles()

A global public function to generate block styles – CSS and class names – from a style object, e.g. the value of a block’s `attributes.style` object or the top-level styles in theme.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.. Through it, one can store CSS for later retrieval and eventual enqueuing on the frontend.

wp_style_engine_get_stylesheet_from_css_rules()

This function compiles and returns a stylesheet for a set of any CSS rules. Through it, one can store CSS for later retrieval and eventual enqueuing on the frontend.

wp_style_engine_get_stylesheet_from_context()

Returns compiled CSS stylesheet from stored styles, if any have been stored. The style engine will automatically merge declarations and combine selectors. 

JavaScript public functions

The JavaScript API is limited to use within the editor, and compiles only block support styles for now. It ensures that the styles in the editor match those you see on the frontend site. 

compileCSS()

Compiles and returns a CSS stylesheet for a given style object and selector. 

getCSSRules()

Given a style object, it returns a collection of objects containing the selector, if any, the CSS property key (camel case) and the parsed CSS value.

Example usage

WordPress 6.1 primarily uses the public methods cited above to create and enqueue block supports styles from a “style” object usually available as a property on the block attributes

An individual block’s style object may look like this:

$block_styles = array(
     'spacing'    => array(
        'padding' => '10px',
        'margin'  => array(
            'top' => '1em'
            ),
        ),
     'typography' => array(
        'fontSize' => '2.2rem'
    ),
);

wp_style_engine_get_styles() parses and sanitizes the incoming values, then compiles and returns CSS (a compiled string and an array of declarations), which can be used immediately or, if a context is specified in the options, stored for later retrieval.

$styles = wp_style_engine_get_styles(
    $block_styles,
    'options' => array( 'context' => 'block-supports' ),
);

/* 
    $styles is equal to:
    array(
       'css'          => 'padding:10px;margin-top:1em;font-size:2.2rem',
       'declarations' => array( 'padding' => '10px', 'margin-top' => '1em', 'font-size' => '2.2rem' )
    )
*/

Multiple instances of such styles may be “stored” across the application, before the page is rendered, and then retrieved and printed together as a single stylesheet when the page is rendered.

Note: The ‘context’ value is used to group and identify styles, so all styles that belong in the same stylesheet should be stored using the same context value.

The editor could then retrieve the stylesheet for all styles stored under the context value of ‘block-supports’ and enqueue them to be printed to the page in a single style tag:

function enqueue_my_block_supports_styles() {
    $block_supports_stylesheet = wp_style_engine_get_stylesheet_from_context( 'block-supports' );

    if ( ! empty( $block_supports_stylesheet ) ) {
       wp_register_style( 'my-block-supports-stylesheet', false, array(), true, true );
       wp_add_inline_style( 'my-block-supports-stylesheet', $stylesheet );
       wp_enqueue_style( 'my-block-supports-stylesheet' );
    }
}

add_action( 'wp_enqueue_scripts', 'enqueue_my_block_supports_styles' );

Using wp_style_engine_get_stylesheet_from_css_rules() is similar only that, instead of a block styles object, the first argument is a collection of CSS rules from which you can create a stylesheet.

$my_styles = array(
   array(
       'selector'     => '.orange',
       'declarations' => array( 'color' => 'orange' )
   ),
   array(
       'selector'     => '.red',
       'declarations' => array( 'color' => 'red' )
   ),
);

$my_stylesheet = wp_style_engine_get_stylesheet_from_css_rules(
   $my_styles,
   array(
       'context' => 'my-styles',
   )
);

Please refer to the API documentation: @wordpress/style-engine for detailed information and example usage.

Backwards compatibility and best practices

The Style Engine is a new API and, while it replaces the way block supports to generate CSS and class names, it does not modify the functionality of any existing global methods.

While backwards compatibility is a priority, the Style Engine is in its first iteration and therefore the underlying mechanics will be subject to some degree of transformation in the 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/ 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. and, ultimately, future versions of WordPress. 

To ensure ongoing compatibility, it is recommended to only use the above-mentioned public functions, and avoid calling public methods of any Style Engine utility class.

Current limitations and future enhancements

The Style Engine’s sole function in 6.1 is to generate coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. block supports CSS for the following styles:

  • border
  • color
  • spacing
  • typography

In future iterations, this list may be extensibleExtensible This is the ability to add additional functionality to the code. Plugins extend the WordPress core software..

The next milestones for the Style Engine are:

  • to assume the responsibility of processing and rendering optimized frontend CSS for Global styles
  • providing a way to generate all theme-related styles in one place, and
  • further reducing the footprint of rendered styles

Ongoing development is taking place in WordPress/gutenberg: see the tracking issue and project board.

You can find more context on the history and planned features of the Style Engine on Block editor styles: initiatives and goals.

Further reading

  • Block editor styles: initiatives and goals 
  • 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 by the repository owner. https://github.com/ tracking issue #38167
  • GitHub project board.
  • API documentation: @wordpress/style-engine

Props: @webcommsat and @bph for review

#6-1, #core-editor, #dev-notes, #dev-notes-6-1, #editor, #gutenberg

Multisite improvements in WordPress 6.1

NOTE: Due to issues reported in #56845, this enhancementenhancement Enhancements are simple improvements to WordPress, such as the addition of a hook, a new feature, or an improvement to an existing feature. was reverted in r54637 and will not be included in the final 6.1 release. Work will continue in 6.2 and beyond. Please follow along in the original 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. (#37181)

Using the metadata 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. for networknetwork (versus site, blog) options

The way that network options are accessed is changing in WordPress 6.1. Network options have always been stored in a meta table called sitemeta. This name is confusing, as “site” in this context means “network,” not to be confused with blogblog (versus network, site) meta, used to store site metadata. Prior to WordPress 6.1, the functions get_network_option, add_network_option, update_network_options, and delete_network_option used custom database queries and caching. This resulted in some performance issues and lots of code to maintain.

In WordPress 6.1, the network options functions have been updated to use the more established metadata API, which is already used for metadata of other object types like posts, terms, and users. This effectively makes a function like get_network_option a wrapper around get_metadata. This has a number of advantages including:

  • Consistency with other metadata types
  • Support for register_meta functionality, such as default values
  • Improved cache priming 
  • Fewer database queries, as all network options are primed in a single request 

Along with these improvements, WP_Network_Query has a new parameter called update_network_meta_cache that allows for all networks in the query to prime the network options in a single query. 

One side effect of this change is that newly updated network options using an integer value may result in a string being returned. When using values like this with an integer comparison, it is important to allow cast to an int. In the old implementation, the second page load of the option would have resulted in returning a string. This change can be considered a fix but it is different from the current behavior. 

This change makes cache group site-options no longer in use and a candidate to be removed in future releases. 

For more information, visit Trac ticket #37181

Store main site ID of network in network options

When a multisitemultisite Used to describe a WordPress installation with a network of multiple blogs, grouped by sites. This installation type has shared users tables, and creates separate database tables for each blog (wp_posts becomes wp_0_posts). See also network, blog, site is created in WordPress 6.1, the main site ID on the network is stored in network options. As the main site on the network does not change in most cases, this is a value that can be stored for future reference. This saves a call to WP_Site_Query to look up the main site by domain and path in the bootstrap process which makes This lookup wasteful and not needed. This change also helps setup multiple networks, as noted above, since network options are primed in a single request. This means that when looking up multiple networks, the main site ID is now primed in along with other network options, resulting in fewer database queries / cache lookups. 

For more information, visit Trac ticket #55802

Thanks to @flixos90 and @milana_cap for peer review, and @mxbclang and @webcommsat for proofreading.

#6-1, #core-multisite, #dev-notes, #dev-notes-6-1, #multisite, #performance

Introducing WP_List_Table::get_views_links() in WordPress 6.1

The Problem

Previously, the code to generate markup for views links had to be added in the get_views() method of each child class. This led to repetitive and inconsistent code to achieve the same result, increasing the maintenance burden for CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. and extenders alike.

The Solution

A new method was proposed in ticketticket Created for both bug reports and feature development on the bug tracker. #42066, WP_List_Table::get_views_links(), which abstracts the link generation to the parent class.

This new protected method accepts a $link_data array argument containing the following for each view:

  • $url (string) The link URLURL A specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org.
  • $label (string) The link label.
  • $current (bool) Optional. Whether this is the currently selected view.

If $current is true, aria-current="page" and class="current" will be added to the item’s link markup.

Usage

  1. In the get_views() method, create an array of link data as documented above.
  2. Pass the array to the new method.
class My_List_Table extends WP_List_Table {
	protected function get_views() {
		// Create link data.
		$base_url  = add_query_arg( 'post_type', 'my_cpt', admin_url( 'edit.php' ) );
		$link_data = array(
			'all' => array(
				'url'     => $base_url,
				'label'   => __( 'All', 'my_textdomain' ),
				'current' => true, // Optional.
			),
			'trash' => array(
				'url'   => add_query_arg( 'post_status', 'trash', $base_url ),
				'label' => __( 'Trash', 'my_text_domain' ),
			),
		);

		// Generate link markup.
		return $this->get_views_links( $link_data );
	}
}

Core Child Class Updates

The following Core child classes now use the new method:

Thanks to @davidbaumwald for peer review.

#6-1, #dev-notes, #dev-notes-6-1

Escaping Table and Field names with wpdb::prepare() in WordPress

This has been postponed from WordPress 6.1. See also Postponed to WP 6.2: Escaping Table and Field names with wpdb::prepare()

As part of WordPress 6.2, wpdb::prepare() has been updated to escape Identifiers (such as Table and Field names) with the %i placeholder (#52506).

This ensures these values are escaped correctly and don’t lead to SQL Injection Vulnerabilities.

Example

$table = 'my_table';
$field = 'my_field';
$value = 'my_value';

$wpdb->prepare('SELECT * FROM %i WHERE %i = %s', $table, $field, $value);

// Output:
//   SELECT * FROM `my_table` WHERE `my_field` = 'my_value'

While this protects you against SQL Injection, where possible you should limit the values the user (attacker) can choose via an allow-list of trusted values; e.g.

$fields = array(
    'name'    => 'user_nicename',
    'url'     => 'user_url',
    'created' => 'DATE(created)',
  );

$sql .= ' ORDER BY ' . ($fields[$order_field] ?? 'user_login');

Performance Improvement

The change to add support for %i has a small performance improvement, as there is a little bit less Regular Expression work involved (generally the more parameters, the better the improvement).

In the Future

This was going to be released in WordPress 6.1, but a problem was identified in RC5 where the use of '%%%s%%' (which can often be seen in LIKE queries) stopped working. For reference, the documentation says “numbered or formatted string placeholders” will not have quotes added by this function (an old/unsafe feature), but this also happens when a placeholder immediately follows a “%”.

WordPress is looking to use %i in coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. (#56091).

This change will help developers use the literal-string type for the $query parameter (this is where the $query is written as a developer-defined string, and all user values are provided separately).

Props to @davidbaumwald for reviewing this dev notedev note Each important change in WordPress Core is documented in a developers note, (usually called dev note). Good dev notes generally include a description of the change, the decision that led to this change, and a description of how developers are supposed to work with that change. Dev notes are published on Make/Core blog during the beta phase of WordPress release cycle. Publishing dev notes is particularly important when plugin/theme authors and WordPress developers need to be aware of those changes.In general, all dev notes are compiled into a Field Guide at the beginning of the release candidate phase..

#6-1, #dev-notes, #dev-notes-6-1, #performance, #wpdb

Create-block scaffolding tool updates

WordPress 6.1 introduces new features and updates to the @wordpress/create-block package used by developer to scaffold new blocks.

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. Variants

The new --variant flag allows users of the tool to choose a block variant to be scaffolded. The internal templates provided by the create-block package support a dynamic and static variant with will scaffold a dynamic and static block respectively. If no variant is passed, the static variant is used.

Scaffolding using the dynamic variant:

npx @wordpress/create-block custom-block --variant=dynamic

Template authors can define variants by adding a variants object to the template definition with each property being the name of a variant and its value an object containing values that can add to or overwrite the default values defined in the defaultValues key. See the create-block-tutorial-template file for an example of defining variants.

Related pull requests: #41289, #43481.

Add additional blocks to an existing 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.

A highly requested feature for the package was to be able to add additional blocks to an existing plugin. With the addition of the --no-plugin flag that is now possible! 

When the command is run with the flag, the tool creates a new set of block files in a subdirectory to the current directory named with the slug passed.

npx @wordpress/create-block custom-block --no-plugin

Related pull requests: #41642.

Enhancements:

  • I18ni18n Internationalization, or the act of writing and preparing code to be fully translatable into other languages. Also see localization. Often written with a lowercase i so it is not confused with a lowercase L or the numeral 1. Often an acquired skill. references have been removed from the internal templates to avoid potential issues with translated strings causing block validation errors ( #43035 )
  • Improvements to the developer experience by prompting to continue the scaffolding process if the tool thinks system requirements are not met ( #42151, #42254 ) and some more general fixes to the scaffold to remove some warnings and errors ( #40479, #41273 ).
  • Adds support for the new render block.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. key ( #44185 )

Documentation

The documentation around creating External Templates has been split into a separate section ( #43718 ) and links to the documentation in the associated create-block-tutorial-template have been fixed to link to the correct places ( #42839 ).

Direct links to all documentation pages for the create-block scaffolding tool:

Props @pbiron, @bph for review

#6-1, #dev-notes, #dev-notes-6-1

Introduction of presets across padding, margin and block gap

WordPress 6.1 introduces preset values for padding, margin and 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. gap. With those the editor implements consistent spacing of blocks and nested blocks out of the box.

The problem

The block editor design tools allowed users only to add custom values for the spacing around block content, eg. padding, margin, or gap.

Dimensions window for padding, margin and block spacing

This means that theme and 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. authors had no ability to either limit users to a fixed list of spacing options, or to easily change spacing across all of a site’s content if custom spaces have been set on some blocks.

The solution: spacingScale object

theme.json has been extended to include a spacing sizes preset option, similar to the existing font size presets. By default, the editor will generate a range of seven preset sizes that are shared across padding, margin and block gap.

This range is auto-generated from a spacingScale object in the theme.json settings section:

"spacing": {
	"spacingScale": {
		"operator": "*",
		"increment": 1.5,
		"steps": 7,
		"mediumStep": 1.5,
		"unit": "rem"
	}
},

In the above case, the three steps on either side of the medium step of 1.5rem are generated using a multiplier of 1.5, which results in the following array of spacingSizes:

[
  {name: '1', slug: '20', size: '0.44rem'},
  {name: '2', slug: '30', size: '0.67rem'},
  {name: '3', slug: '40', size: '1rem'},
  {name: '4', slug: '50', size: '1.5rem'},
  {name: '5', slug: '60', size: '2.25rem'},
  {name: '6', slug: '70', size: '3.38rem'},
  {name: '7', slug: '80', size: '5.06rem'},
]

It is possible to generate as many steps as needed, and also to use a + operator instead of * to generate these. If a theme has a spacing scale that can’t be auto-generated, then it is possible to include a static array of values in theme.json settings.spacing.spacingSizes.

The spacing sizes are converted to CSSCSS Cascading Style Sheets. properties in the following format:

--wp--preset--spacing--20: 0.44rem;
--wp--preset--spacing--30: 0.67rem;
--wp--preset--spacing--40: 1rem;
--wp--preset--spacing--50: 1.5rem;
--wp--preset--spacing--60: 2.25rem;
--wp--preset--spacing--70: 3.38rem;
--wp--preset--spacing--80: 5.06rem;

Enable fallbacks on Theme switch

There are three reasons for the choice of slugs in the 10,20,30 format:

  1. It is much easier to sort the sizes from smallest to highest, than if the likes of t-shirt sizes were used
  2. For themes that wish to insert additional values between the CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. ones, e.g. a value between Medium and Large, it is easy to do so with a slug of 55
  3. Allow for cross-theme/site compatibility of content if a theme does not support a spacing preset slug in existing content, e.g., a pattern from the pattern library. Numeric values enable a fall back to the nearest match in the current theme. This is also the reason the spacing sizes are generated on either side of Medium. Having a known Medium slug of 50 can hopefully make these fallbacks as accurate as possible.

In the editor UIUI User interface spacing options default to providing the preset option with a toggle to switch back to custom values:

Spacing presets UI

Disable Spacing Presets

  • Disable the spacing presets option by adding the value 0 to settings.spacing.spacingScale.steps in theme.json.
  • Disable the custom spacing sizes by setting settings.spacing.customSpacingSize to false.

Documentation of all theme.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. settings & styles:

How to Guide: Global Settings & Styles (Theme.json)
Theme.json Reference (v2)

Background information

Finalizing the details around these spacing presets has involved a lot of discussion with both theme authors and Core contributorsCore Contributors Core contributors are those who have worked on a release of WordPress, by creating the functions or finding and patching bugs. These contributions are done through Trac. https://core.trac.wordpress.org. These discussions can be found at the links:

Props to: @glendaviesnz for writing, @webcommsat and @bph for reviewing.

#6-1, #dev-notes, #dev-notes-6-1, #gutenberg

Improved PHP performance for core blocks registration

WordPress 6.1 also comes with a considerable performance improvement for handling blocks in plugins and in the WordPress backend (PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher).

Early block.json Registration Method

Starting with WordPress 5.8, extenders were encouraged to begin to utilize block.json to register blocks through a unified registration process. The benefits offered by this update provide consistency and convenience when registering blocks through PHP or JavaScriptJavaScript JavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser. https://www.javascript.com.

However, while this block.json scanning convention is extremely convenient, it does add additional processing when coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. blocks are instantiated. On each page load, 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. registration undergoes the following steps:

  • Scan folders for block.json files.
  • When a block.json file is found, read its contents into memory.
  • Call json_decode on the file contents to convert it to a PHP array.
  • Register the block using the decoded data.

With over 70 core block files to scan and load, this presented an opportunity for optimization.

Core Block Registration Update

To reduce filesystem reads and processing of block.json files, which should benefit all WordPress sites and improve performance, block registration has been updated to:

  • Introduce a new Grunt task (copy:block-json) that scans and converts core block.json files to PHP arrays and stores them in a single blocks-json.php at build time.
  • Use the new blocks-json.php file in the register_block_type_from_metadata() function.
  • Assign the block registration data to a static variable (cache) so that it’s only loaded once per request.

The addition of an extra build task to compile the decoded 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. data to PHP reduces block registration filesystem reads from ~70 files to just a single file. And since blocks-json.php is a native PHP array, it can be used directly without additional conversion.

The conversion from block.json files to PHP arrays is achieved through the json2php package, which is already utilized in Core and 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/.

References

Props to @aristath for source material and collaboration, and to @milana_cap for review of this dev notedev note Each important change in WordPress Core is documented in a developers note, (usually called dev note). Good dev notes generally include a description of the change, the decision that led to this change, and a description of how developers are supposed to work with that change. Dev notes are published on Make/Core blog during the beta phase of WordPress release cycle. Publishing dev notes is particularly important when plugin/theme authors and WordPress developers need to be aware of those changes.In general, all dev notes are compiled into a Field Guide at the beginning of the release candidate phase..

#6-1, #dev-notes, #dev-notes-6-1, #performance

Improvements to WP_Query performance in 6.1

Adding caching to database queries in WP_Query

WordPress 6.1 includes an improvement to how database queries are performed in the WP_Query class, resulting in database queries will be cached. This means that if the same database query is run more than once, the result will be loaded from cache. For those using persistent object caching, this will mean that the database query will not run again until caches are invalidated, resulting in far fewer queries to the database. Sites using in-memory caching will also see the benefit of not repeating these queries, though the performance improvement will not be as significant. 

For those doing custom development, please ensure that you are using coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. functions such as wp_insert_post to add posts to the database. These functions are well-maintained, and by using them, you ensure that caches are correctly invalidated. If you are updating the database directly, then it is strongly recommended that you call the clean_post_cache function after updating the database row. 

It is worth noting that by default, all calls to WP_Query will be cached going forward. It is possible to opt out of caching queries by simply passing the cache_results parameter as false. See example:

$args = array(
   'posts_per_page' => 50,
   'cache_results'  => false
);
$query = new WP_Query( $args );

It is also possible to globally disable caching, using a 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.:

function disable_caching( $wp_query ) {
   $wp_query->query_vars['cache_results'] = false;
}
add_action( 'parse_query', 'disable_caching' );

Disabling caching like this should only be done in extreme cases. For best performance, it is highly recommended to keep caching enabled and invalidate caches using the clean_post_cache function. 

Cache keys are generated using the parameters passed to the WP_Query class instance. However, the following parameters are ignored:

  • suppress_filters
  • cache_results
  • fields
  • update_post_meta_cache
  • update_post_term_cache
  • update_menu_item_cache
  • lazy_load_term_meta

These parameters do not affect the database query that is run. The most important ignored parameter is fields. This means that if you run the following: 

$args1 = array(
	'posts_per_page' => 50,
	'fields'  => 'ids'
);
$query1 = new WP_Query( $args1 );

$args2 = array(
	'posts_per_page' => 50,
	'fields'  => 'all'
);
$query2 = new WP_Query( $args2 );

In both cases, the query will now request all fields, so that the result can be cached and then be used regardless of the fields parameter. Prior to this change, the database query for those two was different, but keeping it like that would have resulted in multiple caches for effectively subsets of the same data. This means that there is now less of a performance improvement when limiting fields ids than there was in the previous version of WordPress. 

This change also means that the update_post_meta_cache and update_post_term_cache caches are always respected. 

In cases where caching was added to WP_Query by using plugins such as advanced-post-cache, Enhanced Post Cache or Cache WP_Query, it is recommended that these plugins are disabled and removed as they are no longer required.

For more info, see 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. #22176

Prime users cache in WP_Query

WordPress 6.1 introduces a new function, update_post_author_caches. Prior to 6.1, sites with multiple authors required several single database queries to get author information, as the user is loaded as part of the loopLoop The Loop is PHP code used by WordPress to display posts. Using The Loop, WordPress processes each post to be displayed on the current page, and formats it according to how it matches specified criteria within The Loop tags. Any HTML or PHP code in the Loop will be processed on each post. https://codex.wordpress.org/The_Loop. Instead of loading each user one by one, user (author) caches are now primed in a single database call by calling update_post_author_caches at the start of the loop, resulting in far fewer database queries. 

This function accepts an array of post objects and will prime user caches. Calls to update_post_author_caches have also been added in key parts of the codebase to improve database performance.

For more info, see Trac ticket #55716

Prime linked objects for menu items

A new function has been added to core called update_menu_item_cache. It accepts an array of post objects and will prime caches for post or terms referenced in a menu item. A new parameter for WP_Query has been added called update_menu_item_cache. When set to true it will call update_menu_item_cache which will allow you to prime menu items in a two database queries (one for posts and one for terms). 

For more info, see Trac ticket #55620

get_page_by_title now uses WP_Query

The function get_page_by_title now uses WP_Query. Previously,  this function used a raw database query to get the page by title. As noted above, WP_Query is now cached, meaning that calls to get_page_by_title will also be cached. This also has the benefit of running through all the filters in WP_Query

For more info, see Trac ticket #36905 

Thanks to @flixos90@milana_cap@peterwilsoncc for peer review and @mxbclang for proofreading.

#6-1, #dev-notes, #dev-notes-6-1, #performance

Introducing “Update URI” theme header in WordPress 6.1

WordPress 6.1 introduces a new headerHeader The header of your site is typically the first thing people will experience. The masthead or header art located across the top of your page is part of the look and feel of your website. It can influence a visitor’s opinion about your content and you/ your organization’s brand. It may also look different on different screen sizes. available for theme authors. This allows third-party themes to avoid accidentally being overwritten with an update of a theme of a similar name from the WordPress.orgWordPress.org The community site where WordPress code is created and shared by the users. This is where you can download the source code for WordPress core, plugins and themes as well as the central location for community conversations and organization. https://wordpress.org/ Theme Directory.

Previously, any custom theme which used the same slug as a theme hosted on WordPress.org was taking a significant risk of being overwritten by an update of the latter.

WordPress 6.1 introduces a new Update URI theme header field. If the value of this new field matches any URI other than https://wordpress.org/themes/{$slug}/ or w.org/theme/{$slug}, WordPress will not attempt to update it.

If set, the Update URI header field should be a URI and have a unique hostname.

Some examples include:

  • https://wordpress.org/themes/example-theme/
  • https://example.com/my-theme/
  • my-custom-theme-name

Update URI: false also works, and unless there is code handling the false hostname, the theme will never get an update notification.

If the header is present, the WordPress.org 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. will currently only return updates for the theme if it matches the following format:

  • https://wordpress.org/themes/{$slug}/
  • w.org/theme/{$slug}

If the header has any other value, the API will not return a result and will ignore the theme for update purposes.

Additionally, WordPress 6.1 introduces the update_themes_{$hostname} 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., which third-party themes can use to offer updates for a given hostname. They can be used to filter the update response in multiple use cases.

This new hook filters the update response for a given theme hostname. The dynamic portion of the hook name, $hostname, refers to the hostname of the URI specified in the Update URI header field.

The hook has four arguments:

  • $update: The theme update data with the latest details. Default false.
  • $theme_data: The list of headers provided by the theme.
  • $theme_stylesheet: The theme stylesheet.
  • $locales: Installed locales to look translations for.

Please note that authors of themes hosted by WordPress.org don’t need to use this new header.

For reference, see tickets #14179, and changeset [53933].

Special thanks to @audrasjb and @sergeybiryukov as this post closely plagarizes Introducing “Update URI” plugin header in WordPress 5.8 and the commit message. Thanks to @costdev and @pbiron for review.

#6-1, #dev-notes, #dev-notes-6-1