Make WordPress Core


Ignore:
Timestamp:
05/22/2023 07:11:36 PM (17 months ago)
Author:
flixos90
Message:

Media: Conditionally skip lazy-loading on images before the loop to improve LCP performance.

When the logic to exclude images that likely appear above the fold from being lazy-loaded was introduced in WordPress 5.9, initially only images that appear within the main query loop were being considered. However, there is a good chance that images above the fold are rendered before the loop starts, for example in the header template part.

It is particularly common for a theme to display the featured image for a single post in the header. Based on HTTP Archive data from February 2023, the majority of LCP images that are still being lazy-loaded on WordPress sites use the wp-post-image class, i.e. are featured images.

This changeset enhances the logic in wp_get_loading_attr_default() to not lazy-load images that appear within or after the header template part and before the query loop, using a new WP_Query::$before_loop property.

For block themes, this was for the most part already addressed in [55318], however this enhancement implements the solution in a more generally applicable way that brings the improvement to classic themes as well.

Props thekt12, flixos90, spacedmonkey, costdev, zunaid321, mukesh27.
Fixes #58211.
See #53675, #56930.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/query.php

    r54891 r55847  
    898898        $this->assertFalse( $q->is_tag( 'non-existent-tag' ) );
    899899    }
     900
     901    /**
     902     * Test if $before_loop is true before loop.
     903     *
     904     * @ticket 58211
     905     */
     906    public function test_before_loop_value_set_true_before_the_loop() {
     907        // Get a new query with 3 posts.
     908        $query = $this->get_new_wp_query_with_posts( 3 );
     909
     910        $this->assertTrue( $query->before_loop );
     911    }
     912
     913    /**
     914     * Test $before_loop value is set to false when the loop starts.
     915     *
     916     * @ticket 58211
     917     *
     918     * @covers WP_Query::the_post
     919     */
     920    public function test_before_loop_value_set_to_false_in_loop_with_post() {
     921        // Get a new query with 2 posts.
     922        $query = $this->get_new_wp_query_with_posts( 2 );
     923
     924        while ( $query->have_posts() ) {
     925            // $before_loop should be set false as soon as the_post is called for the first time.
     926            $query->the_post();
     927
     928            $this->assertFalse( $query->before_loop );
     929            break;
     930        }
     931    }
     932
     933    /**
     934     * Test $before_loop value is set to false when there is no post in the loop.
     935     *
     936     * @ticket 58211
     937     *
     938     * @covers WP_Query::have_posts
     939     */
     940    public function test_before_loop_set_false_after_loop_with_no_post() {
     941        // New query without any posts in the result.
     942        $query = new WP_Query(
     943            array(
     944                'category_name' => 'non-existent-category',
     945            )
     946        );
     947
     948        // There will not be any posts, so the loop will never actually enter.
     949        while ( $query->have_posts() ) {
     950            $query->the_post();
     951        }
     952
     953        // Still, this should be false as there are no results and entering the loop was attempted.
     954        $this->assertFalse( $query->before_loop );
     955    }
     956
     957    /**
     958     * Get a new query with a given number of posts.
     959     *
     960     * @param int $no_of_posts Number of posts to be added in the query.
     961     */
     962    public function get_new_wp_query_with_posts( $no_of_posts ) {
     963        $post_ids = self::factory()->post->create_many( $no_of_posts );
     964        $query    = new WP_Query( array( 'post__in' => $post_ids ) );
     965        return $query;
     966    }
    900967}
Note: See TracChangeset for help on using the changeset viewer.