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

Improve Optimization Detective documentation #1782

Merged
merged 11 commits into from
Feb 11, 2025
2 changes: 1 addition & 1 deletion plugins/image-prioritizer/readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ This plugin optimizes the loading of images (and videos) with prioritization to

The current optimizations include:

1. Add breakpoint-specific `fetchpriority=high` preload links (`LINK[rel=preload]`) for image URLs of LCP elements:
1. Add breakpoint-specific `fetchpriority=high` preload links (both as `LINK[rel=preload]` elements and `Link` response headers) for image URLs of LCP elements:
1. An `IMG` element, including the `srcset`/`sizes` attributes supplied as `imagesrcset`/`imagesizes` on the `LINK`.
2. The first `SOURCE` element with a `type` attribute in a `PICTURE` element. (Art-directed `PICTURE` elements using media queries are not supported.)
3. An element with a CSS `background-image` inline `style` attribute.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,5 @@
* Exception thrown when failing to validate URL Metrics data.
*
* @since 0.1.0
* @access private
*/
final class OD_Data_Validation_Exception extends Exception {}
1 change: 0 additions & 1 deletion plugins/optimization-detective/class-od-element.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
* @todo The above implements tag should account for additional undefined keys which can be supplied by extending the element schema. May depend on <https://github.com/phpstan/phpstan/issues/8438>.
*
* @since 0.7.0
* @access private
*/
class OD_Element implements ArrayAccess, JsonSerializable {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
* Extension to WP_HTML_Tag_Processor that supports injecting HTML and obtaining XPath for the current tag.
*
* @since 0.1.1
* @access private
*/
final class OD_HTML_Tag_Processor extends WP_HTML_Tag_Processor {

Expand Down
15 changes: 14 additions & 1 deletion plugins/optimization-detective/class-od-link-collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,23 @@
*
* @since 0.3.0
* @since 0.4.0 Renamed from OD_Preload_Link_Collection.
* @access private
*/
final class OD_Link_Collection implements Countable {

/**
* Links grouped by rel type.
*
* @since 0.4.0
*
* @var array<string, Link[]>
*/
private $links_by_rel = array();

/**
* Adds link.
*
* @since 0.3.0
*
* @phpstan-param LinkAttributes $attributes
*
* @param array $attributes Attributes.
Expand Down Expand Up @@ -111,6 +114,8 @@ public function add_link( array $attributes, ?int $minimum_viewport_width = null
* When two links are identical except for their minimum/maximum widths which are also consecutive, then merge them
* together. Also, add media attributes to the links.
*
* @since 0.4.0
*
* @return LinkAttributes[] Prepared links with adjacent-duplicates merged together and media attributes added.
*/
private function get_prepared_links(): array {
Expand All @@ -133,6 +138,8 @@ function ( array $links ): array {
/**
* Merges consecutive links.
*
* @since 0.4.0
*
* @param Link[] $links Links.
* @return LinkAttributes[] Merged consecutive links.
*/
Expand Down Expand Up @@ -228,6 +235,8 @@ static function ( array $link ): array {
/**
* Gets the HTML for the link tags.
*
* @since 0.3.0
*
* @return string Link tags HTML.
*/
public function get_html(): string {
Expand All @@ -249,6 +258,8 @@ public function get_html(): string {
/**
* Constructs the Link HTTP response header.
*
* @since 0.4.0
*
* @return non-empty-string|null Link HTTP response header, or null if there are none.
*/
public function get_response_header(): ?string {
Expand Down Expand Up @@ -302,6 +313,8 @@ static function ( $matches ) {
/**
* Counts the links.
*
* @since 0.3.0
*
* @return non-negative-int Link count.
*/
public function count(): int {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,23 @@
* @implements IteratorAggregate<string, TagVisitorCallback>
*
* @since 0.3.0
* @access private
*/
final class OD_Tag_Visitor_Registry implements Countable, IteratorAggregate {

/**
* Visitors.
*
* @since 0.3.0
*
* @var array<non-empty-string, TagVisitorCallback>
*/
private $visitors = array();

/**
* Registers a tag visitor.
*
* @since 0.3.0
*
* @phpstan-param TagVisitorCallback $tag_visitor_callback
*
* @param non-empty-string $id Identifier for the tag visitor.
Expand All @@ -46,6 +49,8 @@ public function register( string $id, callable $tag_visitor_callback ): void {
/**
* Determines if a visitor has been registered.
*
* @since 0.3.0
*
* @param non-empty-string $id Identifier for the tag visitor.
* @return bool Whether registered.
*/
Expand All @@ -56,6 +61,8 @@ public function is_registered( string $id ): bool {
/**
* Gets a registered visitor.
*
* @since 0.3.0
*
* @param non-empty-string $id Identifier for the tag visitor.
* @return TagVisitorCallback|null Whether registered.
*/
Expand All @@ -69,6 +76,8 @@ public function get_registered( string $id ): ?callable {
/**
* Unregisters a tag visitor.
*
* @since 0.3.0
*
* @param non-empty-string $id Identifier for the tag visitor.
* @return bool Whether a tag visitor was unregistered.
*/
Expand All @@ -83,6 +92,8 @@ public function unregister( string $id ): bool {
/**
* Returns an iterator for the URL Metrics in the group.
*
* @since 0.3.0
*
* @return ArrayIterator<string, TagVisitorCallback> ArrayIterator for tag visitors.
*/
public function getIterator(): ArrayIterator {
Expand All @@ -92,6 +103,8 @@ public function getIterator(): ArrayIterator {
/**
* Counts the URL Metrics in the group.
*
* @since 0.3.0
*
* @return int<0, max> URL Metric count.
*/
public function count(): int {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
* @implements IteratorAggregate<int, OD_URL_Metric_Group>
*
* @since 0.1.0
* @access private
*/
final class OD_URL_Metric_Group_Collection implements Countable, IteratorAggregate, JsonSerializable {

Expand All @@ -31,6 +30,7 @@ final class OD_URL_Metric_Group_Collection implements Countable, IteratorAggrega
* even to when there are zero breakpoints: there will still be one group
* in this case, in which every single URL Metric is added.
*
* @since 0.1.0
* @var OD_URL_Metric_Group[]
* @phpstan-var non-empty-array<OD_URL_Metric_Group>
*/
Expand All @@ -54,13 +54,15 @@ final class OD_URL_Metric_Group_Collection implements Countable, IteratorAggrega
* This array may be empty in which case there are no responsive breakpoints and all URL Metrics are collected in a
* single group.
*
* @since 0.1.0
* @var positive-int[]
*/
private $breakpoints;

/**
* Sample size for URL Metrics for a given breakpoint.
*
* @since 0.1.0
* @var int<1, max>
*/
private $sample_size;
Expand All @@ -70,13 +72,15 @@ final class OD_URL_Metric_Group_Collection implements Countable, IteratorAggrega
*
* A freshness age of zero means a URL Metric will always be considered stale.
*
* @since 0.1.0
* @var int<0, max>
*/
private $freshness_ttl;

/**
* Result cache.
*
* @since 0.3.0
* @var array{
* get_group_for_viewport_width?: array<int, OD_URL_Metric_Group>,
* is_every_group_populated?: bool,
Expand All @@ -94,6 +98,8 @@ final class OD_URL_Metric_Group_Collection implements Countable, IteratorAggrega
/**
* Constructor.
*
* @since 0.1.0
*
* @throws InvalidArgumentException When an invalid argument is supplied.
*
* @phpstan-param positive-int[] $breakpoints
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
* @implements IteratorAggregate<int, OD_URL_Metric>
*
* @since 0.1.0
* @access private
*/
final class OD_URL_Metric_Group implements IteratorAggregate, Countable, JsonSerializable {

Expand Down Expand Up @@ -95,6 +94,8 @@ final class OD_URL_Metric_Group implements IteratorAggregate, Countable, JsonSer
*
* This class should never be directly constructed. It should only be constructed by the {@see OD_URL_Metric_Group_Collection::create_groups()}.
*
* @since 0.1.0
*
* @access private
* @throws InvalidArgumentException If arguments are invalid.
*
Expand Down
8 changes: 6 additions & 2 deletions plugins/optimization-detective/class-od-url-metric.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,21 @@
* }
*
* @since 0.1.0
* @access private
*/
class OD_URL_Metric implements JsonSerializable {

/**
* Data.
*
* @since 0.1.0
* @var Data
*/
protected $data;

/**
* Elements.
*
* @since 0.7.0
* @var OD_Element[]
*/
protected $elements;
Expand All @@ -89,6 +90,8 @@ class OD_URL_Metric implements JsonSerializable {
/**
* Constructor.
*
* @since 0.1.0
*
* @phpstan-param Data|array<string, mixed> $data Valid data or invalid data (in which case an exception is thrown).
*
* @throws OD_Data_Validation_Exception When the input is invalid.
Expand All @@ -105,6 +108,8 @@ public function __construct( array $data ) {
/**
* Prepares data with validation and sanitization.
*
* @since 0.6.0
*
* @throws OD_Data_Validation_Exception When the input is invalid.
*
* @param array<string, mixed> $data Data to validate.
Expand Down Expand Up @@ -350,7 +355,6 @@ public static function get_json_schema(): array {
* @param array<string, mixed> $properties_schema Properties schema to extend.
* @param array<string, mixed> $additional_properties Additional properties.
* @param string $filter_name Filter name used to extend.
*
* @return array<string, mixed> Extended schema.
*/
protected static function extend_schema_with_optional_properties( array $properties_schema, array $additional_properties, string $filter_name ): array {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ final class OD_Visited_Tag_State {

/**
* Constructor.
*
* @since 1.0.0
*/
public function __construct() {
$this->reset();
Expand Down
6 changes: 4 additions & 2 deletions plugins/optimization-detective/docs/extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ As mentioned above, this plugin is a dependency that doesn't provide features on

**[Image Prioritizer](https://wordpress.org/plugins/image-prioritizer/) ([GitHub](https://github.com/WordPress/performance/tree/trunk/plugins/image-prioritizer)):**

1. Add breakpoint-specific `fetchpriority=high` preload links (`LINK[rel=preload]`) for image URLs of LCP elements:
1. Add breakpoint-specific `fetchpriority=high` preload links (both as `LINK[rel=preload]` elements and `Link` response headers) for image URLs of LCP elements:
1. An `IMG` element, including the `srcset`/`sizes` attributes supplied as `imagesrcset`/`imagesizes` on the `LINK`. ([1](https://github.com/WordPress/performance/blob/f5f50f9179c26deadeef966734367d199ba6de6f/plugins/image-prioritizer/class-image-prioritizer-img-tag-visitor.php#L167-L177), [2](https://github.com/WordPress/performance/blob/f5f50f9179c26deadeef966734367d199ba6de6f/plugins/image-prioritizer/class-image-prioritizer-img-tag-visitor.php#L304-L349))
2. The first `SOURCE` element with a `type` attribute in a `PICTURE` element. (Art-directed `PICTURE` elements using media queries are not supported.) ([1](https://github.com/WordPress/performance/blob/f5f50f9179c26deadeef966734367d199ba6de6f/plugins/image-prioritizer/class-image-prioritizer-img-tag-visitor.php#L192-L275), [2](https://github.com/WordPress/performance/blob/f5f50f9179c26deadeef966734367d199ba6de6f/plugins/image-prioritizer/class-image-prioritizer-img-tag-visitor.php#L304-L349))
3. An element with a CSS `background-image` inline `style` attribute. ([1](https://github.com/WordPress/performance/blob/f5f50f9179c26deadeef966734367d199ba6de6f/plugins/image-prioritizer/class-image-prioritizer-background-image-styled-tag-visitor.php#L62-L92), [2](https://github.com/WordPress/performance/blob/f5f50f9179c26deadeef966734367d199ba6de6f/plugins/image-prioritizer/class-image-prioritizer-background-image-styled-tag-visitor.php#L182-L203))
Expand All @@ -22,7 +22,9 @@ As mentioned above, this plugin is a dependency that doesn't provide features on
1. Apply lazy loading to `IMG` tags based on whether they appear in any breakpoint’s initial viewport. ([1](https://github.com/WordPress/performance/blob/f5f50f9179c26deadeef966734367d199ba6de6f/plugins/image-prioritizer/class-image-prioritizer-img-tag-visitor.php#L124-L133))
2. Implement lazy loading of CSS background images added via inline `style` attributes. ([1](https://github.com/WordPress/performance/blob/f5f50f9179c26deadeef966734367d199ba6de6f/plugins/image-prioritizer/class-image-prioritizer-background-image-styled-tag-visitor.php#L205-L238), [2](https://github.com/WordPress/performance/blob/f5f50f9179c26deadeef966734367d199ba6de6f/plugins/image-prioritizer/helper.php#L365-L380), [3](https://github.com/WordPress/performance/blob/f5f50f9179c26deadeef966734367d199ba6de6f/plugins/image-prioritizer/lazy-load-bg-image.js))
3. Lazy-load `VIDEO` tags by setting the appropriate attributes based on whether they appear in the initial viewport. If a `VIDEO` is the LCP element, it gets `preload=auto`; if it is in an initial viewport, the `preload=metadata` default is left; if it is not in an initial viewport, it gets `preload=none`. Lazy-loaded videos also get initial `preload`, `autoplay`, and `poster` attributes restored when the `VIDEO` is going to enter the viewport. ([1](https://github.com/WordPress/performance/blob/f5f50f9179c26deadeef966734367d199ba6de6f/plugins/image-prioritizer/class-image-prioritizer-video-tag-visitor.php#L163-L246), [2](https://github.com/WordPress/performance/blob/f5f50f9179c26deadeef966734367d199ba6de6f/plugins/image-prioritizer/helper.php#L365-L380), [3](https://github.com/WordPress/performance/blob/f5f50f9179c26deadeef966734367d199ba6de6f/plugins/image-prioritizer/lazy-load-video.js))
5. Ensure that [`sizes=auto`](https://make.wordpress.org/core/2024/10/18/auto-sizes-for-lazy-loaded-images-in-wordpress-6-7/) is added to all lazy-loaded `IMG` elements. ([1](https://github.com/WordPress/performance/blob/f5f50f9179c26deadeef966734367d199ba6de6f/plugins/image-prioritizer/class-image-prioritizer-img-tag-visitor.php#L148-L163))
5. Responsive image sizes:
1. Compute the `sizes` attribute using the widths of an image collected from URL Metrics for each breakpoint (when not lazy-loaded since then handled by `sizes=auto`). ([1](https://github.com/WordPress/performance/blob/6459571471b26aee4f63f00e2ba9dfe6f5ce2f39/plugins/image-prioritizer/class-image-prioritizer-img-tag-visitor.php#L170-L184), [2](https://github.com/WordPress/performance/blob/6459571471b26aee4f63f00e2ba9dfe6f5ce2f39/plugins/image-prioritizer/class-image-prioritizer-img-tag-visitor.php#L412-L444))
2. Ensure [`sizes=auto`](https://make.wordpress.org/core/2024/10/18/auto-sizes-for-lazy-loaded-images-in-wordpress-6-7/) is set on `IMG` tags after setting correct lazy-loading (above). ([1](https://github.com/WordPress/performance/blob/6459571471b26aee4f63f00e2ba9dfe6f5ce2f39/plugins/image-prioritizer/class-image-prioritizer-img-tag-visitor.php#L156-L168))
6. Reduce the size of the `poster` image of a `VIDEO` from full size to the size appropriate for the maximum width of the video (on desktop). ([1](https://github.com/WordPress/performance/blob/f5f50f9179c26deadeef966734367d199ba6de6f/plugins/image-prioritizer/class-image-prioritizer-video-tag-visitor.php#L84-L125))

**[Embed Optimizer](https://wordpress.org/plugins/embed-optimizer/) ([GitHub](https://github.com/WordPress/performance/tree/trunk/plugins/embed-optimizer)):**
Expand Down
16 changes: 16 additions & 0 deletions plugins/optimization-detective/helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ function od_initialize_extensions(): void {
/**
* Fires when extensions to Optimization Detective can be loaded and initialized.
*
* This action is useful for loading extension code that depends on Optimization Detective to be running. The version
* of the plugin is passed as the sole argument so that if the required version is not present, the callback can short circuit.
*
* Example:
*
* add_action( 'od_init', function ( string $version ) {
* if ( version_compare( $version, '1.0', '<' ) ) {
* add_action( 'admin_notices', 'my_plugin_warn_optimization_plugin_outdated' );
* return;
* }
*
* // Bootstrap the Optimization Detective extension.
* require_once __DIR__ . '/functions.php';
* // ...
* } );
*
* @since 0.7.0
*
* @param string $version Optimization Detective version.
Expand Down
2 changes: 1 addition & 1 deletion plugins/optimization-detective/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/**
* Plugin Name: Optimization Detective
* Plugin URI: https://github.com/WordPress/performance/tree/trunk/plugins/optimization-detective
* Description: Provides an API for leveraging real user metrics to detect optimizations to apply on the frontend to improve page performance.
* Description: Provides a framework for leveraging real user metrics to detect optimizations for improving page performance.
* Requires at least: 6.6
* Requires PHP: 7.2
* Version: 1.0.0-beta2
Expand Down
Loading