Make WordPress Core

Opened 6 weeks ago

Closed 5 weeks ago

Last modified 5 weeks ago

#64178 closed defect (bug) (fixed)

Increased styles_inline_size_limit pushes down oEmbed discovery tags

Reported by: swissspidy's profile swissspidy Owned by: westonruter's profile westonruter
Milestone: 6.9 Priority: normal
Severity: normal Version: 6.9
Component: Embeds Keywords: has-patch needs-unit-tests
Focuses: performance Cc:

Description

A consequence of #63018 seems to be that it pushes down oEmbed discovery meta tags. WordPress only fetches the first 150 KB of a page to scan for those. So now if you try to embed a page such as https://make.wordpress.org/core/2021/10/12/proposal-for-a-performance-team/, the tags are not be within those 150 KB anymore and embedding doesn't work.

Changing priority of wp_oembed_add_discovery_links might help. Or fetching more than 150 KB, but that seems wasteful.

Change History (14)

This ticket was mentioned in Slack in #core by swissspidy. View the logs.


6 weeks ago

#2 @westonruter
6 weeks ago

  • Owner set to westonruter
  • Status changed from new to accepted

#3 @westonruter
6 weeks ago

There's quite a bit more inline CSS on that page than expected, namely 98,691 bytes:

IDLength (bytes)External SourceSource URL
wp-img-auto-sizes-contain-inline-css 135Nowp-img-auto-sizes-contain-inline-css
admin-bar-inline-css 703Noadmin-bar-inline-css
wp-emoji-styles-inline-css 340Nowp-emoji-styles-inline-css
wp-block-library-inline-css 47Nowp-block-library-inline-css
jetpack-block-subscriptions-inline-css 8667Yeshttps://make.wordpress.org/core/wp-content/plugins/jetpack/_inc/blocks/subscriptions/view.css?minify=false
core-block-supports-inline-css 808Nocore-block-supports-inline-css
wporg-chapter-list-style-inline-css 5620Yeshttps://make.wordpress.org/core/wp-content/mu-plugins/pub-sync/blocks/chapter-list/build/style-index.css
wporg-favorite-button-style-inline-css 2105Yeshttps://make.wordpress.org/core/wp-content/mu-plugins/pub-sync/blocks/favorite-button/build/style-index.css
wporg-google-map-style-inline-css 2685Yeshttps://make.wordpress.org/core/wp-content/mu-plugins/pub-sync/blocks/google-map/build/style.css
wporg-language-suggest-style-inline-css 1015Yeshttps://make.wordpress.org/core/wp-content/mu-plugins/pub-sync/blocks/language-suggest/build/style.css
wporg-latest-news-style-inline-css 3733Yeshttps://make.wordpress.org/core/wp-content/mu-plugins/pub-sync/blocks/latest-news/build/style.css
wporg-link-wrapper-style-inline-css 873Yeshttps://make.wordpress.org/core/wp-content/mu-plugins/pub-sync/blocks/link-wrapper/build/style.css
wporg-modal-style-inline-css 2226Yeshttps://make.wordpress.org/core/wp-content/mu-plugins/pub-sync/blocks/modal/build/style-index.css
wporg-query-filter-style-inline-css 14351Yeshttps://make.wordpress.org/core/wp-content/mu-plugins/pub-sync/blocks/query-filter/build/style-index.css
wporg-ratings-bars-style-inline-css 1334Yeshttps://make.wordpress.org/core/wp-content/mu-plugins/pub-sync/blocks/ratings-bars/build/style-index.css
wporg-ratings-stars-style-inline-css 653Yeshttps://make.wordpress.org/core/wp-content/mu-plugins/pub-sync/blocks/ratings-stars/build/style-index.css
wporg-sidebar-container-style-inline-css 2785Yeshttps://make.wordpress.org/core/wp-content/mu-plugins/pub-sync/blocks/sidebar-container/build/style.css
wporg-screenshot-preview-style-inline-css 2487Yeshttps://make.wordpress.org/core/wp-content/mu-plugins/pub-sync/blocks/screenshot-preview-block/build/style-index.css
wporg-site-breadcrumbs-style-inline-css 1234Yeshttps://make.wordpress.org/core/wp-content/mu-plugins/pub-sync/blocks/site-breadcrumbs/build/style.css
wporg-table-of-contents-style-inline-css 4134Yeshttps://make.wordpress.org/core/wp-content/mu-plugins/pub-sync/blocks/table-of-contents/build/style.css
jetpack-sharing-buttons-style-inline-css 793Yeshttps://make.wordpress.org/core/wp-content/plugins/jetpack/_inc/blocks/sharing-buttons/view.css
wporg-notice-style-inline-css 2615Yeshttps://make.wordpress.org/core/wp-content/mu-plugins/pub-sync/blocks/notice/build/style.css
global-styles-inline-css 39348Noglobal-styles-inline-css

Table derived via:

console.table( Array.from(document.querySelectorAll('head > style[id*="-inline-css"]')).map(( style ) => { const matches = style.textContent.match( /\/\*#\s*sourceURL=(.+?)\s*\*\// ); return { id: style.id, length: style.textContent.length, hasExternal: matches[1].includes('.css'), sourceURL: matches[1] }})  )

Of these styles, ~57KB appear to have been automatically inlined via wp_maybe_inline_styles(). This is larger than the 50,000 styles_inline_size_limit, however.

There is a very large global styles inline style at almost 40KB.

I'm also noticing that there are stylesheets being enqueued for blocks which don't actually occur on the page (e.g. wporg-google-map). This would seem to indicate on-demand enqueues aren't working as expected per #64099. This may be due to how the P2 theme works, however, in that it has some client-side rendering logic which may necessitate adding more CSS up front than is actually needed, just in case it is needed later?

#4 @westonruter
5 weeks ago

Changing the priority is going to be complicated because there are many instances of ecosystem code removing the action:

<?php
remove_action( 'wp_head', 'wp_oembed_add_discovery_links' );

See GitHub Search (1.7k files) and WPDirectory (145 plugins).

This ticket was mentioned in PR #10449 on WordPress/wordpress-develop by @westonruter.


5 weeks ago
#5

  • Keywords has-patch added

This addresses an issue whereby if there is a lot of markup printed at wp_head (e.g. inline styles from Core-63018), WordPress sites looking for the oEmbed discovery links will fail to find them because they only read the first 150KB of the HTML response, by default:

https://github.com/WordPress/wordpress-develop/blob/bafd51b8ff87c8f51357e01def21489dc38e2474/src/wp-includes/class-wp-oembed.php#L444

Note that scripts and styles are printed at priorities 8 and 9:

https://github.com/WordPress/wordpress-develop/blob/bafd51b8ff87c8f51357e01def21489dc38e2474/src/wp-includes/default-filters.php#L355-L356

In order to ensure the oEmbed links remain discoverable, it seems prudent to print them early, specifically right after other similar links are printed, namely feed_links() and feed_links_extra().

It is not so simple as changing the action priority from 10 to 4:

https://github.com/WordPress/wordpress-develop/blob/bafd51b8ff87c8f51357e01def21489dc38e2474/src/wp-includes/default-filters.php#L707

This is because there are many plugins which remove the oEmbed discovery links via:

remove_action( 'wp_head', 'wp_oembed_add_discovery_links' );

See GitHub Search (1.7k files) and WPDirectory (145 plugins).

Aside: The better way to do this would be to do:

add_filter( 'oembed_discovery_links', '__return_empty_string' );

In order to maintain backwards-compatibility with the ecosystem which unhooks the action in this way, it is necessary to add a _second instance_ of wp_oembed_add_discovery_links running at wp_head with the earlier priority of 4. Inside of wp_oembed_add_discovery_links(), when it runs first at priority 4, it can check if it has been unhooked at priority 10, and if so, short-circuit. Otherwise, it can continue with printing the oEmbed discovery links, but also preventing them from being duplicated by itself doing:

remove_action( 'wp_head', 'wp_oembed_add_discovery_links' );

In order to facilitate this, it is necessary to extend the has_action()/has_filter() functions with a new $priority parameter to be able to check whether a given callback is added at a specific priority. This is something I've missed in the past.

A similar approach to backwards-compatibility has been done recently, for with emoji in example r60910. The difference there is that a new function was introduced, whereas here the function remains the same.

  • [ ] Add tests

Trac ticket: https://core.trac.wordpress.org/ticket/64178

#6 @westonruter
5 weeks ago

I have a solution I like for changing the priority: https://github.com/WordPress/wordpress-develop/pull/10449

However, I think it may make sense to back off of increasing the styles_inline_size_limit as well. Instead of bumping from 20K to 50K, perhaps it would make more sense to meet in the middle at 35K or 40K.

Note the graphs showing the LCP-TTFB for Fast 4G (raw data) and broadband (raw data) from #63018. In the two graphs, the uncached curve starts to flatten out at 40K:

https://core.trac.wordpress.org/raw-attachment/ticket/63018/increasing-css-inline-size-limit.png

https://core.trac.wordpress.org/raw-attachment/ticket/63018/increasing-css-inline-size-limit-broadband.png

Reducing the inline limit wouldn't solve the problem for the page in question, however, since the oEmbed discover links appear at byte 178,831. So reducing reducing 10K-15K of inline CSS would still leave them above the 150K threshold for discovery.

This ticket was mentioned in Slack in #core by westonruter. View the logs.


5 weeks ago

#8 @westonruter
5 weeks ago

  • Keywords needs-unit-tests added

#9 @westonruter
5 weeks ago

In 61117:

Script Loader: Reduce styles_inline_size_limit down to 40K from 50K.

In [61013] the CSS inline limit was increased from 20K to 50K. However, based on benchmarking the performance improvements of increasing the limit, the relative improvement from 40K to 50K is not as great as from 30K to 40K. The performance improvements start to flatten out beginning at 40K. This 40K is still double the previous limit of 20K. Being more conservative will allow for a more gradual impact to be observed before considering a larger increase. Furthermore, the 50K limit of inline CSS can cause the oEmbed discovery links to be positioned after the first 150K bytes which prevents them from being discovered. See #64178.

Follow-up to [61013].

Props westonruter, mukesh27, szepeviktor.
See #64178.
Fixes #63018.

#10 @westonruter
5 weeks ago

I've opened #64186 specifically to document the addition of the $priority parameter to has_action()/has_filter().

@westonruter commented on PR #10449:


5 weeks ago
#11

I've opened https://github.com/WordPress/wordpress-develop/pull/10456 to introduce the has_filter()/has_action() change in isolation. Tests have been added there.

#12 @westonruter
5 weeks ago

In 61118:

Plugins: Add missing $priority parameter to has_filter() and has_action().

This brings has_filter()/has_action() in parity with add_filter()/add_action() and remove_filter()/remove_action(), all of which support a $priority parameter.

Props westonruter, swissspidy.
Fixes #64186.
See #64178.

#13 @westonruter
5 weeks ago

  • Resolution set to fixed
  • Status changed from accepted to closed

In 61119:

Embeds: Add wp_oembed_add_discovery_links() to run earlier at wp_head priority 4.

This results in the oEmbed discovery links being printed before scripts and styles are printed. This helps ensure they appear within the first 150K bytes of the HTML response, which is required by WP_oEmbed::discover(). With increasing the styles_inline_size_limit from 20K to 40K in #63018, it becomes more probable that the oEmbed discovery links will be pushed out of range.

For backwards compatibility with themes and plugins that disable the oEmbed discovery links by unhooking wp_oembed_add_discovery_links() from running at wp_head priority 10 (even though the oembed_discovery_links filter is available to disable such links), this callback is added a second time to run earlier at priority 4. The first time the function runs, it checks to see if the callback is still hooked at priority 10. If not, the function short circuits. If it is still hooked at priority 10, however, the function then unhooks itself at priority 10 so that it won't run a second time later during the wp_head action, before proceeding with printing the discovery links. A similar back-compat approach was taken previously in [60910]. The back-compat checks are only performed if the function is invoked during the wp_head action, allowing the function to be called "idempotently" elsewhere.

Developed in https://github.com/WordPress/wordpress-develop/pull/10449

Follow-up to [61118], [61117].

Props westonruter, swissspidy.
See #64186, #63018.
Fixes #64178.

#14 @westonruter
5 weeks ago

As of 6.9-beta3, the amount of inlined styles (aside from global-styles-inline-css), amount to 49K. This is still above the 40K limit. Maybe this indicates a bug in the wp_maybe_inline_styles() logic for determining when to cut off inlining.

In any case, the issue with oEmbed discovery tags is now resolved, as they are printed before the styles.

Note: See TracTickets for help on using tickets.