Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Module Proposal: oEmbed Optimizer #888

Closed
adamsilverstein opened this issue Nov 27, 2023 · 0 comments · Fixed by #1059
Closed

Module Proposal: oEmbed Optimizer #888

adamsilverstein opened this issue Nov 27, 2023 · 0 comments · Fixed by #1059
Labels
[Plugin] Embed Optimizer Issues for the Embed Optimizer plugin [Type] (Legacy) Module Proposal A new module proposal (legacy)

Comments

@adamsilverstein
Copy link
Member

adamsilverstein commented Nov 27, 2023

Overview

  • Proposed module name: oEmbed optimizer
  • Proposed module slug: oembed-optimizer
  • Proposed module owner GitHub username(s): adamsilverstein

About the module

Purpose

Optimize loading of oEmbeds by ensuring they are lazy loaded and that scripts are only loaded as the embed enters the viewport.

Scope

Adjust core's loading of oEmbeds to make them lazier.

Rationale

oEmbeds are embedded visual blocks and on WordPress sites, they are typically inserted by pasting a URL, for example a tweet or youtube video into the block editor. This URL is transformed by the editor into an embed block.

oEmbeds represent an unpredictable contributor to performance. Since they by nature include third party resources, they tend to compete for resources with the main page thread. While an oEmbed could be simple, they can also be incredibly impactful - loading on additional resources dynamically in unpredictable ways.

oEmbed Stats

I gathered some stats about oEmbed usage in WordPress by querying httparchive:

  • Around 1% of WordPress pages in httparchive contain at least one oEmbed (query)
  • Of WP sites using an oEmbed, ~70% have a YouTube oEmbed and ~10% have a Twitter(X) embed (query)
  • Some of the top oEmbeds are among the top INP offenders in WordPress (query)

How oEmbeds work

oEmbeds are typically implemented either as an iframe or using a script tag that expands a block of content.

Example: YouTube oEmbed which is implemented as an iframe:

<figure class="wp-block-embed">
<div class="wp-block-embed__wrapper">
<iframe title="TITLE" width="840" height="473" src="https://www.youtube.com/embed/YT_LINK?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen>
</iframe>
</div>
</figure>

Of note for iframe oEmbeds:

  • WordPress core will already add the loading=”lazy” attribute to iframes that meet the proper heuristics. However, it might be worth using more aggressive lazy loading for oEmbeds which are less likely to be LCP elements.
  • oEmbed providers can also include the lazy loading attribute in their iframe markup.

Example: Twitter (X) oEmbed which is implemented with a script loader:

<figure class="wp-block-embed is-type-rich is-provider-twitter wp-block-embed-twitter">
<div class="wp-block-embed__wrapper">
<blockquote class="twitter-tweet" data-width="474" data-dnt="true">
<p lang="en" dir="ltr">TWEET_TITLE
<a href="https://t.co/TWEET_LINK">https://t.co/TWEET_LINK</a>
</p>
<a href="LINK_TO_ORIGINAL">DATE</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div></figure>

Notes: A couple of things to note about the Twitter oEmbed (and similar oEmbeds that use a loader script):
A minimal version of the tweet itself still loads and works even before the JavaScript loads or if JavaScript is disabled

  • The https://platform.twitter.com/widgets.js script is generic and is loaded for every Twitter oEmbed. Its job is to expand fill its container div content with a full visual representation, including an image preview:

  • In the Twitter example, the widget.js script replaces the oEmbeds parent div (wp-block-embed__wrapper) content entirely with an iframe that provides the visual representation:

image

  • Loaders are typically loaded async, however it still may be advantageous to delay loading these scripts until the embed approaches the viewport. This prevents any resource contention until the user actually scrolls near to the embed.

WordPress post embeds

WordPress itself provides an oEmbed capability, and pasting a post URL into the editor results in a WordPress embed - a mini version of the linked post embedded into the post. These embeds are a bit of a special case and while implemented as an iframe, they are hidden until a signal is received from the inner frame, making them a poor match for lazy loading

Optimizing oEmbeds

In my PR I propose optimizing oEmbeds using two techniques:

For oEmbeds delivered as iframes:

  • ensure the loading=lazy attribute is always present. My hypothesis is this will result in improved metrics at the median.

For oEmbeds built using script tags:

  • move the script src to a data attribute
  • add a page level interaction observer that resets src (or injects the script tag anew) before the user scrolls to the oEmbed

To Do

WordPress oEmebds need special treatment as mentioned above
The scroll tolerance should be bandwidth based (higher speed connections get a smaller preload window)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Plugin] Embed Optimizer Issues for the Embed Optimizer plugin [Type] (Legacy) Module Proposal A new module proposal (legacy)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants