WordPress: kiedy lazy loading źle zgaduje i jak go wyłączyć dla obrazu 🔥

WordPress dodaje loading="lazy" do obrazów, a obraz widoczny od razu po wejściu na stronę ładuje się przez to później i psuje LCP. WordPress Core sam pomija lazy loading dla pierwszych 3 elementów multimedialnych w treści i dodaje fetchpriority="high" dla kwalifikującego się obrazu. W większości przypadków nic nie musisz robić 🚀

Problem zaczyna się, gdy obraz above the fold (na pierwszym ekranie, zanim zaczniesz przewijać stronę) jest 4. elementem w treści: po kilku ikonach albo w układzie z kolumnami. WordPress Core liczy elementy, a nie to, co widać w oknie przeglądarki. Dwa sposoby, od prostszego.

Sposób 1: zwiększ próg (jedna linia PHP)

function my_theme_omit_loading_attr_threshold() {
	return 5;
}
add_filter( 'wp_omit_loading_attr_threshold', 'my_theme_omit_loading_attr_threshold' );

Ustaw tyle, ile obrazów bywa above the fold na Twoich stronach. Funkcja ma nazwę, więc możesz ją odpiąć przez remove_filter. Próg działa na całej witrynie, więc za wysoka wartość wyłączy lazy loading obrazom, które na niego zasługują.

Sposób 2: przełącznik w bloku Obraz

Wybierz go, gdy redaktor ma decydować dla każdego obrazu osobno. Potrzebujesz dwóch rzeczy: przełącznika w edytorze i filtra PHP, który coś z nim zrobi.

Przełącznik w edytorze (JS)

WordPress Core rozszerza bloki przez filtry edytora (blocks.registerBlockType, editor.BlockEdit, blocks.getSaveContent.extraProps i inne), bez jednej funkcji do tego. Używam registerBlockExtension z pakietu 10up, który podpina je za Ciebie:

npm install @10up/block-components
import { registerBlockExtension } from '@10up/block-components';
import { __ } from '@wordpress/i18n';
import { InspectorControls } from '@wordpress/block-editor';
import { PanelBody, ToggleControl } from '@wordpress/components';

const extraAttributes = {
	lazyLoadingDisabled: {
		type: 'boolean',
		default: false,
	},
};

const Edit = ( { attributes, setAttributes } ) => (
	<InspectorControls>
		<PanelBody title={ __( 'Additional Settings', 'my-theme' ) }>
			<ToggleControl
				label={ __( 'Disable image lazy loading', 'my-theme' ) }
				help={ __( 'Use it for images above the fold.', 'my-theme' ) }
				checked={ attributes.lazyLoadingDisabled }
				onChange={ ( value ) => setAttributes( { lazyLoadingDisabled: value } ) }
			/>
		</PanelBody>
	</InspectorControls>
);

const classNameGenerator = ( { lazyLoadingDisabled } ) =>
	lazyLoadingDisabled ? 'no-lazyload' : '';

registerBlockExtension( 'core/image', {
	extensionName: 'my-theme/disable-lazy-loading',
	attributes: extraAttributes,
	classNameGenerator,
	Edit,
} );
  • classNameGenerator dodaje klasę no-lazyload do głównego elementu bloku, czyli do <figure>
  • Skrypt musi trafić do edytora przez enqueue_block_editor_assets
  • Przełącznik pojawia się w panelu bloku Obraz, na karcie Ustawienia (ikona zębatki)
  • Zamień my-theme na własny prefiks

Ustaw loading=”eager” (PHP)

Sama klasa niczego nie wyłącza. Filtr szuka <figure> z tą klasą i ustawia obrazowi loading="eager". WordPress Core nie nadpisuje atrybutów, które już są w znaczniku, więc lazy loading się nie doda:

function my_theme_image_disable_lazy_loading( $content ) {
	$html = new WP_HTML_Tag_Processor( $content );

	if ( $html->next_tag( array( 'class_name' => 'no-lazyload' ) ) && $html->next_tag( 'img' ) ) {
		$html->set_attribute( 'loading', 'eager' );
	}

	return $html->get_updated_html();
}
add_filter( 'render_block_core/image', 'my_theme_image_disable_lazy_loading', 16 );
  • WP_HTML_Tag_Processor działa od WordPressa 6.2, a render_block_{nazwa} od 5.7
  • Priorytet 16, bo od WordPressa 6.4 blok Obraz z opcją „Powiększ po kliknięciu” ma własny filtr z priorytetem 15

Sprawdź

Otwórz źródło strony. Obraz above the fold ma mieć loading="eager" (albo brak lazy), a pozostałe loading="lazy". Pamiętaj, żeby zrobić test w Lighthouse przed zmianą i po niej, na tej samej stronie.

Który sposób wybierasz? Napisz w komentarzu, jak zmienił się LCP 👏

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Wymagane pola są oznaczone *