Make WordPress Core


Ignore:
Timestamp:
10/14/2025 12:10:31 AM (4 months ago)
Author:
westonruter
Message:

Editor: Avoid enqueueing assets for blocks which do not render content.

This change prevents scripts, styles, and script modules from being enqueued for blocks that do not render any HTML content. This is common for hidden blocks or blocks like the Featured Image block when no image is present. This change reduces the amount of unused CSS and JavaScript on a page, improving performance.

A new filter, enqueue_empty_block_content_assets, is introduced to allow developers to override this behavior and enqueue assets for empty blocks if needed.

The implementation involves capturing the asset queues before and after a block is rendered. The newly enqueued assets are only merged if the block's rendered content is not empty. This is done recursively for nested blocks to ensure that assets for inner blocks are also not enqueued if a parent block is hidden.

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

Props westonruter, aristath, peterwilsoncc, gziolo, krupajnanda, dd32, jorbin.
See #50328.
Fixes #63676.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-script-modules.php

    r60704 r60930  
    2424
    2525    /**
    26      * Holds the script module identifiers that were enqueued before registered.
    27      *
    28      * @since 6.5.0
    29      * @var array<string, true>
    30      */
    31     private $enqueued_before_registered = array();
     26     * An array of IDs for queued script modules.
     27     *
     28     * @since 6.9.0
     29     * @var string[]
     30     */
     31    public $queue = array();
    3232
    3333    /**
     
    123123                'src'           => $src,
    124124                'version'       => $version,
    125                 'enqueue'       => isset( $this->enqueued_before_registered[ $id ] ),
    126125                'dependencies'  => $dependencies,
    127126                'fetchpriority' => $fetchpriority,
     
    214213     */
    215214    public function enqueue( string $id, string $src = '', array $deps = array(), $version = false, array $args = array() ) {
    216         if ( isset( $this->registered[ $id ] ) ) {
    217             $this->registered[ $id ]['enqueue'] = true;
    218         } elseif ( $src ) {
     215        if ( ! in_array( $id, $this->queue, true ) ) {
     216            $this->queue[] = $id;
     217        }
     218        if ( ! isset( $this->registered[ $id ] ) && $src ) {
    219219            $this->register( $id, $src, $deps, $version, $args );
    220             $this->registered[ $id ]['enqueue'] = true;
    221         } else {
    222             $this->enqueued_before_registered[ $id ] = true;
    223220        }
    224221    }
     
    232229     */
    233230    public function dequeue( string $id ) {
    234         if ( isset( $this->registered[ $id ] ) ) {
    235             $this->registered[ $id ]['enqueue'] = false;
    236         }
    237         unset( $this->enqueued_before_registered[ $id ] );
     231        $this->queue = array_diff( $this->queue, array( $id ) );
    238232    }
    239233
     
    246240     */
    247241    public function deregister( string $id ) {
     242        $this->dequeue( $id );
    248243        unset( $this->registered[ $id ] );
    249         unset( $this->enqueued_before_registered[ $id ] );
    250244    }
    251245
     
    305299     */
    306300    public function print_script_module_preloads() {
    307         foreach ( $this->get_dependencies( array_keys( $this->get_marked_for_enqueue() ), array( 'static' ) ) as $id => $script_module ) {
     301        foreach ( $this->get_dependencies( array_unique( $this->queue ), array( 'static' ) ) as $id => $script_module ) {
    308302            // Don't preload if it's marked for enqueue.
    309             if ( true !== $script_module['enqueue'] ) {
     303            if ( ! in_array( $id, $this->queue, true ) ) {
    310304                echo sprintf(
    311305                    '<link rel="modulepreload" href="%s" id="%s"%s>',
     
    346340    private function get_import_map(): array {
    347341        $imports = array();
    348         foreach ( $this->get_dependencies( array_keys( $this->get_marked_for_enqueue() ) ) as $id => $script_module ) {
     342        foreach ( $this->get_dependencies( array_unique( $this->queue ) ) as $id => $script_module ) {
    349343            $imports[ $id ] = $this->get_src( $id );
    350344        }
     
    360354     */
    361355    private function get_marked_for_enqueue(): array {
    362         $enqueued = array();
    363         foreach ( $this->registered as $id => $script_module ) {
    364             if ( true === $script_module['enqueue'] ) {
    365                 $enqueued[ $id ] = $script_module;
    366             }
    367         }
    368         return $enqueued;
     356        return wp_array_slice_assoc(
     357            $this->registered,
     358            $this->queue
     359        );
    369360    }
    370361
     
    458449    public function print_script_module_data(): void {
    459450        $modules = array();
    460         foreach ( array_keys( $this->get_marked_for_enqueue() ) as $id ) {
     451        foreach ( array_unique( $this->queue ) as $id ) {
    461452            if ( '@wordpress/a11y' === $id ) {
    462453                $this->a11y_available = true;
Note: See TracChangeset for help on using the changeset viewer.