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

Editor Chat Agenda: October 12, 2022

Facilitator and notetaker: @bph

This is the agenda for the weekly editor chat scheduled for Wednesday, October 12 2022, 2:00 PM UTC. This meeting is held in the #core-editor channel in the Making WordPress SlackSlack Slack is a Collaborative Group Chat Platform https://slack.com/. The WordPress community has its own Slack Channel at https://make.wordpress.org/chat/.

General Announcements and Links.

  • WordPress RCrelease candidate One of the final stages in the version release cycle, this version signals the potential to be a final release to the public. Also see alpha (beta). 6.1 – schedule for Tuesday Oct 11
  • Field GuideField guide The field guide is a type of blogpost published on Make/Core during the release candidate phase of the WordPress release cycle. The field guide generally lists all the dev notes published during the beta cycle. This guide is linked in the about page of the corresponding version of WordPress, in the release post and in the HelpHub version page. – published also Tuesday Oct 11
  • 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. 14.3 to be released Oct 12. (RC is already available)

Key project updates

Task Coordination.

Open Floor – extended edition.

If you cannot attend the meeting, you are encouraged to share anything relevant for the discussion:

  • If you have an update for the main site editing projects, please feel free to share as a comment or come prepared for the meeting itself.
  • If you have anything to share for the Task Coordination section, please leave it as a comment on this post.
  • If you have anything to propose for the agenda or other specific items related to those listed above, please leave a comment below.

Post reviewed by @paaljoachim. Thank you.

#agenda, #core-editor, #core-editor-agenda, #meeting

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