eurobyte.ru - мощные сервера с Дата-центрами в Нидерландах и Москве. От 159 ₽/мес.

Спекулятивная загрузка в WordPress 6.8

В WordPress 6.8 функция спекулятивной загрузки интегрирована в ядро. Эта новинка может обеспечить почти мгновенную загрузку страниц за счёт предварительной загрузки браузером до того, как пользователь перейдёт по ссылке.

Функция спекулятивной загрузки до внедрения в WordPress Core успешно использовалась на 50 000+ сайтах через плагин Speculative Loading. По данным HTTP Archive и CrUX, она улучшила LCP на ~2%.

Speculation Rules API появился в 2023 году и используется уже в 8% навигаций в Chrome. Cloudflare также внедрил его через функцию Speed Brain.

Что такое спекулятивная загрузка?

Спекулятивная загрузка (Speculative Loading) — веб-API от Google, который позволяет задавать правила для того, какие URL на текущей странице можно предварительно загружать/рендерить, и в какой момент должна срабатывать такая предварительная загрузка.

Цель — ускорить переходы между страницами и улучшить показатели производительности (например, LCP).

Слово "спекулятивная" (от англ. speculative) означает "предположительная", "на основе догадки". Происходит от латинского speculatio — наблюдение, размышление, предугадывание.

В контексте "спекулятивная загрузка" используется, потому что браузер не знает наверняка, перейдёт ли пользователь по ссылке, но предполагает это и заранее загружает ресурс.

Какие страницы подходят для speculative loading?

  • Любые не модифицируемые пользователем. Хорошее правило — избегать предварительную загрузку страниц оформления заказа и корзины. Также Google рекомендует делать prerender только тех страниц, которые пользователь откроет с вероятностью более 80%, если не уверены в этом, то используйте prefetch.

Как это работает?

  • Разработчик задаёт правила: какие URL подходят и как их следует загружать (prefetch или prerender).
  • Браузер использует эти правила, чтобы заранее загрузить контент, не дожидаясь клика.

Инициализация (определение правил)

Разработчики могут задавать правила в формате JSON, указывая, какие УРЛ (страницы) следует предварительно загружать или рендерить.

Эти правила могут быть:

  • Переданы через HTTP-заголовок Speculation-Rules:

    Speculation-Rules: "/rules/prefetch.json","/rules/prerender.json"
  • Внедрены в HTML-документ внутри script тега:

    <script type="speculationrules">
    {
      "prerender": [
    	{
    	  "source": "document",
    	  "where": {
    		"and": [
    		  {
    			"href_matches": "/*"
    		  },
    		  {
    			"not": {
    			  "href_matches": [
    				"/wp-login.php",
    				"/wp-admin/*"
    			  ]
    			}
    		  }
    		]
    	  },
    	  "eagerness": "moderate"
    	}
      ]
    }
    </script>

Параметры (опции)

Основные параметры

  • Тип загрузки — API поддерживает два типа предварительной загрузки:

    • prefetch — загружает только HTML-страницу без подресурсов. Это ускоряет загрузку при переходе.

    • prerender — загружает и рендерит всю страницу заранее (включая JS и стили) в скрытой вкладке, обеспечивая почти мгновенное открытие.

      Но prerender расходует больше памяти и трафика, поэтому его нужно использовать с осторожностью — ресурсы могут быть потрачены зря, если пользователь не перейдёт на страницу.

  • eagerness ― Уровень "нетерпеливости" — определяет, когда браузер должен начать предварительную загрузку:
    • conservative — загрузка при нажатии на ссылку (pointerdown или касании).
    • moderate — загрузка при наведении курсора на ссылку в течение 200 мс (или при pointerdown, если это раньше, особенно актуально для мобильных устройств, где нет наведения).
    • eager — загрузка сразу после появления ссылки на странице.
    • immediate — загружает сразу после обнаружений правил спекулятивной загрузки. Не используется в WordPress.

Все параметры

Общая структура:

{
  "prerender": [ /* правила */ ],
  "prefetch": [ /* правила */ ]
}

Каждое из полей (prerender, prefetch) содержит массив объектов правил, в которых указываются параметры ниже:

Ключ Тип Описание
source string Обязательный. Где брать URL-адреса: list или document
urls string[] Обязательно, если source: list. Список URL или путей
where object Обязательно, если source: document. Определяет, какие элементы участвуют
eagerness string Настойчивость: conservative, moderate, eager, immediate
requires string[] Необязательное. Указывает, что должно быть включено (например, ["anonymous-client"])
target_hint string Необязательное. Подсказка, куда ведёт переход: self, blank, download, и др.
referrer_policy string Необязательное. Политика отправки заголовка Referer
credentials string Необязательное. Указывает, отправлять ли cookies: include, same-origin, omit

Вложенное поле where (если source: "document"):

Ключ Тип Описание
selector_matches string CSS-селектор, ссылки внутри которого участвуют
selector_excludes string CSS-селектор, ссылки внутри которого исключаются
href_matches string URL Pattern для фильтрации ссылок
href_excludes string URL Pattern для исключения ссылок

Пример для source: "document":

{
  "source": "document",
  "where": {
	"selector_matches": ".prerender-link"
  },
  "eagerness": "conservative"
}

Пример для source: "list":

{
  "source": "list",
  "urls": ["/page-1", "/page-2"],
  "eagerness": "moderate"
}

Ограничения

Chrome учитывает различные факторы перед началом предварительной загрузки:​

  • Уровень заряда батареи устройства.
  • Скорость интернет-соединения.
  • Наличие пользовательских данных (например, cookies) для целевого сайта.

Конфиденциальность

Для защиты пользовательских данных при кросс-доменных предварительных загрузках Chrome использует:​

  • Анонимный прокси: позволяет скрыть IP-адрес пользователя при загрузке ресурсов с других доменов.

  • Политику реферера: например, strict-origin, чтобы ограничить информацию, передаваемую в заголовке Referer.​

Если у пользователя есть cookies для целевого сайта, Chrome может отказаться от использования предварительно загруженного контента, чтобы избежать потенциальных проблем с конфиденциальностью.

Реализация в WordPress 6.8

В WordPress 6.8 спекулятивная загрузка включена по умолчанию если соблюдаются следующие условия:

  • Это форнт-энд.
  • И пользвоатель не авторизован.
  • И на сайте включены ЧПУ ссылки.

По умолчанию используется prefetch с eagerness = conservative. Это означает, что пред-загрузка инициируется при начале клика по ссылке. Хоть клик обычно происходит всего за долю секунды, этого всё же достаточно, чтобы заметно улучшить производительность.

Почему спекулятивная загрузка отключена по умолчанию для авторизованных пользователей и сайтов без ЧПУ ссылок (pretty permalinks):

  1. Безопасность: Случайная загрузка URL с пользовательскими параметрами.
  2. Конфиденциальность: Защита приватного контента.
  3. Сложность идентификации: Для сайтов без pretty permalinks сложно отличить стандартные параметры запроса от пользовательских.

По умолчанию исключены следующие типы ссылок:

  • ссылки на админку (/wp-admin/*).
  • ссылки на файлы плагинов и тeкущей темы (/wp-content/themes/mytheme/*).
  • ссылки на файлы из папки загрузок (/wp-content/uploads/*).
  • ссылки на php файлы из wp- скоупа (/wp-*.php).
  • ссылки с параметрами запроса (/*?.+).

Почему такие исключения важны?

Админ-URL (/wp-admin/*) исключён из speculative loading, потому что пререндер динамических и чувствительных страниц (вход, выход, действия с nonces) может непредсказуемо менять состояние сайта или раскрывать приватные данные, поэтому WordPress префетчит/пререндерит только фронтенд.

Пример раскрытия приватных данных

  • /wp-admin/options-general.php — HTML выдаёт e-mail администратора и прочие чувствительные поля.

  • /wp-admin/profile.php или любая страница профиля выводит имя, логин, e-mail и nonce-токен пользователя.

Основаня суть утечки тут в том, что фоновая загрузка - это другая процесс-группа, доступ к которой могут иметь например:

  • Service Worker сайта;
  • Расширение браузера c правом webRequest;
  • Скрипты, уже встроенные в админку (аналитика, SaaS-виджеты) выполняются во время prerender-сессии и успевают отправить e-mail, логин, nonce на сторонние сервера до того, как страница станет видимой.

Т.е. другой процесс может получить содержимое приватной HTML страницы.

Нежелательные действия

Например, если прелоад запускается по наведению на ссылку, то неосознано можно:

  • Активировать плагин.
  • Удаление записи в корзину.
  • и т.д.

По умолчанию правила WP выглядят так:

{
  "prefetch": [
	{
	  "source": "document",
	  "where": {
		"and": [
		  {
			"href_matches": "/*"
		  },
		  {
			"not": {
			  "href_matches": [
				"/wp-*.php",
				"/wp-admin/*",
				"/wp-content/uploads/*",
				"/wp-content/*",
				"/wp-content/plugins/*",
				"/wp-content/themes/mytheme/*",
				"/*\\?(.+)"
			  ]
			}
		  },
		  {
			"not": {
			  "selector_matches": "a[rel~=\"nofollow\"]"
			}
		  },
		  {
			"not": {
			  "selector_matches": ".no-prefetch, .no-prefetch a"
			}
		  }
		]
	  },
	  "eagerness": "conservative"
	}
  ]
}

Функций и хуки WordPress

Функции:

Хуки:

Кастомизация в WordPress

Изменение конфигурации

WordPress позволяет изменить стандартную конфигурацию speculative loading — например, можно включить режим prerender или повысить eagerness (степень “настойчивости” подгрузки).

Для этого используется фильтр wp_speculation_rules_configuration. Колбэк фильтра получает и может вернуть:

  • null — чтобы полностью отключить speculative loading.
    По умолачнию предеается, когда пользователь залогинен или отключены “красивые” URL (ЧПУ).

  • Массив:
    [ 'mode' => 'auto', 'eagerness' => 'auto' ]

    Допустимые значения:

    • mode: auto, prefetch, prerender
    • eagerness: auto, conservative, moderate, eager
      (значение immediate не поддерживается, так как слишком агрессивно)

При auto WordPress сам выбирает режим:

  • mode=auto - prefetch
  • eagerness=auto - conservative

Примеры изменения конфигурации:

Пример: поменяем режим eagerness на moderate:

add_filter( 'wp_speculation_rules_configuration', 'my_change_specrules_config' );
function my_change_specrules_config( $config ) {
	if ( is_array( $config ) ) {
		$config['eagerness'] = 'moderate';
	}

	return $config;
}

Пример: включить prerender и moderate eagerness:

add_filter( 'wp_speculation_rules_configuration', 'my_change_specrules_config' );
function my_change_specrules_config( $config ) {
	if ( is_array( $config ) ) {
		$config['mode']      = 'prerender';
		$config['eagerness'] = 'moderate';
	}

	return $config;
}

Пример: принудительно включить speculative loading на сайте без ЧПУ:

add_filter( 'wp_speculation_rules_configuration', 'my_change_specrules_config' );
function my_change_specrules_config( $config ) {
	if ( ! $config && ! get_option( 'permalink_structure' ) ) {
		$config = [
			'mode'      => 'auto',
			'eagerness' => 'auto',
		];
	}

	return $config;
}

Пример: принудительно включить для авторизованных юзеров:

add_filter( 'wp_speculation_rules_configuration', 'my_change_specrules_config' );
function my_change_specrules_config( $config ) {
	if ( ! $config && is_user_logged_in() ) {
		$config = [
			'mode'      => 'auto',
			'eagerness' => 'auto',
		];
	}

	return $config;
}

Исключение URL

Некоторые плагины используют "action URLs" — переход по ссылке меняет состояние сайта — например, добавление товара в корзину. Такие URL важно исключать из speculative loading (prefetch/prerender), особенно при агресивном eagerness, когда пользователь наведет на ссылку и действие будет выполнено.

Исключить кастомные пути можно с помощью фильтра wp_speculation_rules_href_exclude_paths.

Нарпимер, исключим все URL, которые начинаются с /cart/:

add_filter( 'wp_speculation_rules_href_exclude_paths', 'my_specrules_exclude' );
function my_specrules_exclude( $exclude ) {
	$exclude[] = '/cart/*';
	return $exclude;
}

Можно также проверить текущий тип загрузки, и, например, добавить правила только для prerender типа:

add_filter( 'wp_speculation_rules_href_exclude_paths', 'my_specrules_exclude', 10, 2 );
function my_specrules_exclude( $exclude, $mode ) {
	if ( 'prerender' === $mode ) {
		$exclude[] = '/personalized-area/*';
	}
	return $exclude;
}

Все пути должны соответствовать URL Pattern спецификации и считаются относительно корня. WordPress автоматически добавит префикс, если сайт установлен в поддиректории.

Добавление дополнительных правил

По умолчанию используется одно основное правило. Но можно добавить дополнительные кастомные правила через хук wp_load_speculation_rules.

Хук передаёт в коллбэк функцию WP_Speculation_Rules объект, с которым можно работать — например, добавлять новые правила с нужной конфигурацией.

Пример: включаем prerender с eagerness = moderate для конкретных URL, при этом не меняем общее поведение сайта:

add_action( 'wp_load_speculation_rules', 'my_additional_specrules' );
function my_additional_specrules( WP_Speculation_Rules $specrules ): void {
	$specrules->add_rule(
		'prerender',
		'my-moderate-prerender-url-rule',
		[
			'source'    => 'list',
			'urls'      => [
				'/some-url/',
				'/another-url/',
				'/yet-another-url/',
			],
			'eagerness' => 'moderate',
		]
	);
}

Если список URL часто изменяется, можно вместо этого использовать правило на уровне документа — оно будет применяться ко всем ссылкам с определённым CSS-классом:

add_action( 'wp_load_speculation_rules', 'my_additional_specrules' );
function my_additional_specrules( WP_Speculation_Rules $specrules ): void {
	$specrules->add_rule(
		'prerender',
		'my-moderate-prerender-optin-rule',
		[
			'source' => 'document',
			'where'  => [
				'selector_matches' => '.moderate-prerender, .moderate-prerender a',
			],
			'eagerness' => 'moderate',
		]
	);
}

Теперь можно добавить класс .moderate-prerender к блоку или ссылке — к ним будет применено правило: prerender с eagerness = moderate.

Больше деталей о формате правил можно найти в спецификации Speculation Rules API.

Кастомизация через UI

WordPress поддерживает два специальных CSS-класса для управления предварительной загрузкой:

  • no-prefetch — отключает prefetch и prerender;
  • no-prerender — отключает только prerender.

Многие блоки в редакторе имеют поле "Дополнительные CSS-классы" в метабоксе "Дополнительно".

Добавьте эти классы к блоку, чтобы отключить speculative loading для всех ссылок внутри него.

Этот способ позволяет гибко управлять speculative loading прямо через UI редактора записей.

no-prefetch отключает всё speculative loading, т.к. prerender включает в себя prefetch.

Определение в JS

Проверка поддержки Speculation API

Проверить поддерживает ли браузер Speculation Rules API можно так:

if (
  HTMLScriptElement.supports &&
  HTMLScriptElement.supports("speculationrules")
) {
  console.log( "Ваш браузер поддерживает Speculation Rules API." );
}

Обнаружение prefetch режима в JS

Когда страница загружена с префетчем, свойство deliveryType объекта PerformanceResourceTiming вернёт значение "navigational-prefetch". Можно использовать такой код, чтобы выполнить функцию, если страница была префетчена:

if (
  performance.getEntriesByType("navigation")[0].deliveryType ===
  "navigational-prefetch"
) {
	respondToPrefetch();
}

Этот способ полезен для откладывания действий, которые могут вызвать проблемы при префетчинге (см. Unsafe prefetching).

Обнаружение prerender режима в JS

Чтобы выполнить действие во время prerender, можно проверить свойство document.prerendering. Например, отправить данные аналитики:

if( document.prerendering ){
  analytics.sendInfo( 'Страница в режиме пререндер' );
}

Проверим, находится ли страница в режиме prerender или была prerender-страницей:

function pagePrerendered() {
  return (
	document.prerendering ||
	performance.getEntriesByType("navigation")[0]?.activationStart > 0
  );
}

Когда prerender-документ активируется, PerformanceNavigationTiming.activationStart получает значение типа DOMHighResTimeStamp, представляющее время между началом prerender и фактической активацией документа.

Запуск JS в обычном режиме (при пререндере)

Если нужно запустить JS код только когда пользователь реально перешел на страницу, а не в режиме prerender, то можно использвоать:

  • свойство document.prerendering, чтобы проверить, что страница не в режиме prerender
  • и событие prerenderingchange, которое сработывает, когда пользователь переходит на prerender-страницу.

Например, запустим скрипт аналитики, только при реальном посещении страницы:

if( document.prerendering ){
	document.addEventListener( "prerenderingchange", initAnalytics, { once: true } );
} else {
	initAnalytics();
}

Определение частоты активации prerender

Чтобы измерить, как часто происходит активация prerender, можно объедините все три API:

  • document.prerendering — для определения, находится ли страница сейчас в режиме prerender.
  • prerenderingchange — для отслеживания активации в этом случае.
  • activationStart — для проверки, была ли страница prerender в прошлом.
if (document.prerendering) {
	document.addEventListener(
		'prerenderingchange',
		() => console.log('Страница активировалась из prerender-режима'),
		{ once: true }
	);
} else if (performance.getEntriesByType('navigation')[0]?.activationStart > 0) {
	console.log('Страница была prerender-ена и уже активна к моменту выполнения скрипта');
} else {
	console.log('Страница загружена обычным способом (без prerender)');
}

Отладка

Дебаг в JS

Событие prerenderingchange — отличный способ запустить код при активации страницы, если вы не хотите, чтобы этот код выполнялся в фоновом режиме до фактического перехода. Это может быть полезно, например, для аналитики и рекламы.

//
document.addEventListener( 'prerenderingchange', loadWhenPageIsActivated );
function loadWhenPageIsActivated(){
	console.log( `Страница активирована!` );

	const activationStart = Math.round( performance.getEntriesByType('navigation')[0].activationStart );
	console.log( `Время активации: ${activationStart} млсек` );
}

Теперь если перейти на пререндер страницу, например, нажмем кнопку мыши на ссылку, подождем 3 сек и отпустим, нас перенапрпавит на страницу, которая была пререндерена, то мы увидим в консоли DevTools:

Страница активирована!
Время активации: 3500 млсек (активирована через 3500 млсек после начала загрузки)

По порядку логов видно, что событие активации срабатывает первым, до появления LCP. Хотя страница к этому моменту уже полностью загружена, LCP требует "отрисовки" (paint) — это и отражено в названии! То есть страница загружается в фоне во время prerender, но реальная отрисовка начинается только после активации. Поэтому между моментом активации и временем LCP будет небольшая задержка (например 100 мс. Что, по сути, мгновенно для пользователя!)

Отладка с помощью DevTools

Логирование в консоль (console.log) — наше все! Но вам обязательно нужно знать, что в Chrome DevTools есть поддержка спекулятивной загрузки.

На вкладке Application в DevTools есть раздел Speculative loads:

Поддержка браузеров

Актуальные на сегодня данные: https://caniuse.com/?search=speculation

Speculation Rules API поддерживается в следующих браузерах:

  • Chrome 121+
  • Edge 121+
  • Opera (на базе Chromium)

В других браузерах (например, Firefox, Safari) API игнорируется без негативных последствий.

Заключение

Спекулятивная загрузка — это мощный инструмент оптимизации, позволяющий значительно ускорить загрузку страниц (сайта) за счёт предварительной подгрузки контента. Использование Speculation Rules API (спекулятивные правила загрузки) в сочетании с механизмами prefetch и prerender повышает производительность сайта, улучшает метрику LCP и общую отзывчивость интерфейса. Внедрение этой технологии особенно важно для SEO, Core Web Vitals и улучшения пользовательского опыта. Благодаря гибкой настройке через хуки WordPress, возможность исключать чувствительные URL, а также кастомизировать правила через фильтры и классы, speculative loading становится надёжным решением для современных сайтов на WordPress. Если вы хотите повысить скорость сайта, улучшить показатели PageSpeed и обеспечить плавную навигацию — обязательно активируйте и настройте speculative loading уже сегодня.

5 комментариев
    Войти