Кратко: отложенная загрузка — это приёмы, которые освобождают первый экран от второстепенных ресурсов: defer и async переносят выполнение скриптов на потом, loading=»lazy» откладывает загрузку изображений и фреймов до прокрутки, а font-display: swap убирает невидимый текст при загрузке шрифтов. В WordPress это настраивается плагином, фильтром script_loader_tag, параметром strategy у wp_enqueue_script или подгрузкой скрипта по событию. Ниже — рабочие примеры PHP и JavaScript, сравнительные таблицы и чек-лист проверки результата.
Почему скрипты тормозят загрузку: как браузер обрабатывает JavaScript
Когда браузер встречает в HTML обычный тег script, он останавливает разбор страницы, скачивает файл, выполняет его и только затем продолжает строить DOM. Это называется блокировкой парсера: пока грузится скрипт, пользователь смотрит на пустой экран. Если таких файлов десять, задержки складываются, и страница оживает заметно позже, чем могла бы.
<script src="/wp-content/plugins/my-plugin/assets/script.js"></script> В WordPress к скриптам темы добавляются файлы плагинов: слайдер, формы, галерея, всплывающие окна, счётчики, виджет чата. Каждый подключается через wp_enqueue_script, и по умолчанию все они загружаются синхронно. Основы правильного подключения разобраны в статье про подключение CSS и JS в WordPress через wp_enqueue_scripts, а здесь мы займёмся именно отложенной загрузкой: как перенести выполнение на потом и ничего не сломать.
Со стилями ситуация похожая, но ещё строже: CSS блокирует первую отрисовку целиком. Если стили уже оптимизированы по правилам критического CSS для первой отрисовки, логичный следующий шаг — разобраться со скриптами. С них и начнём.
Ещё один источник проблем — подгрузка «тяжёлых» библиотек ради мелких задач: jQuery-плагин для одной анимации, внешний виджет карты на главной, скрипт соцсетей в каждой статье. Каждый такой файл конкурирует за канал и откладывает момент, когда сайт становится интерактивным. Отложенная загрузка не уменьшает вес ресурсов — она меняет порядок работ так, чтобы приоритетное загружалось раньше второстепенного.
defer и async: разница, которую важно понимать
Два атрибута решают проблему блокировки по-разному. async говорит браузеру: скачивай файл параллельно с разбором и выполняй, как только он загрузится. defer — скачивай параллельно, но выполняй после того, как DOM построен, и обязательно в том порядке, в котором скрипты подключены.
| Подключение | Когда скачивается | Когда выполняется | Порядок | Кому подходит |
|---|---|---|---|---|
| Без атрибутов | При разборе HTML, с паузой | Сразу после загрузки файла | Сохраняется | Скриптам, которые нужны до первой отрисовки |
| async | Параллельно, без пауз | Как только файл скачается | Не гарантируется | Аналитике, счётчикам, экспериментам |
| defer | Параллельно, без пауз | После построения DOM, до DOMContentLoaded | Сохраняется | Интерфейсу темы и плагинам |
Из таблицы вытекают простые правила. Всё, что относится к интерфейсу темы — меню, мобильная навигация, слайдеры, формы, галереи — почти всегда подходит под defer: им нужен готовый DOM, и порядок подключения для них важен. Независимые счётчики и аналитику лучше переводить на async: они не связаны с разметкой и не должны никого ждать. А вот скрипты, которые обязаны выполниться до первой отрисовки, трогать не нужно — они редки, но существуют.
<script defer src="/wp-content/themes/my-theme/js/navigation.js"></script>
<script async src="https://analytics.example.com/tracker.js"></script> Кстати, о третьем варианте: скрипты с type=»module» по умолчанию ведут себя как defer, и добавлять им атрибут не нужно. Отдельно скажем про распространённое заблуждение: «поставим defer всем скриптам, и всё ускорится». На практике важна связка «дескриптор и его зависимости»: один и тот же файл в одном проекте безопасно отложить, а в другом его вызывает инлайн-код прямо в HTML — и после откладывания получится ошибка. Поэтому подход всегда такой: сначала понять, кто зависит от скрипта, потом выбирать атрибут.
Отложенная загрузка без кода: плагины для WordPress
Самый быстрый способ увидеть эффект — подключить плагин оптимизации. Все популярные решения умеют одно и то же ядро: агрегировать файлы, добавлять defer и async, откладывать выполнение «тяжёлых» скриптов до взаимодействия. Отличаются они глубиной настроек и наличием менеджера скриптов по страницам.
| Плагин | Что умеет | Когда выбирать |
|---|---|---|
| Autoptimize | Агрегация и минификация JS, вынос скриптов в футер, флаги defer и async | Когда нужен рабочий результат без бюджета |
| WP Rocket | Кэш и оптимизация вместе: отложенное выполнение JavaScript, стратегии загрузки, ленивая загрузка | Когда нужен комбайн из коробки |
| Perfmatters | Менеджер скриптов: отключение и отложенная загрузка файлов точечно, по страницам | Когда базовая оптимизация уже сделана и нужны детали |
| Clearfy | Бесплатный комплекс оптимизаций, включая отложенную загрузку JavaScript | Когда хочется собрать полезные настройки в одном месте |
Правило номер один: не включайте два оптимизатора одновременно. Пересекающиеся настройки дают непредсказуемый результат — скрипты могут задваиваться или исчезать, а причину придётся искать по всему сайту. Выберите один инструмент, включите нужные опции, очистите кэш и проверьте ключевые страницы: главную, запись, каталог, форму. Установить плагин можно из командной строки — это удобнее и быстрее, чем через админку.
wp plugin install autoptimize --activate Другие полезные команды WP-CLI — в гайде про WP-CLI для новичков. И не забывайте: минификация и объединение файлов дополняют отложенную загрузку, но не заменяют её — подробности в статье про минификацию и объединение CSS и JS.
Отложенная загрузка скриптов кодом: фильтры и параметр strategy
Если плагин не подходит, атрибуты добавляются двумя способами: при регистрации собственного скрипта и фильтром для чужих. Начнём с правильного — со своего файла. С версии WordPress 6.3 функция wp_enqueue_script принимает массив аргументов, в котором можно сразу указать стратегию загрузки.
<?php
add_action('wp_enqueue_scripts', function () {
wp_enqueue_script(
'my-theme-nav',
get_stylesheet_directory_uri() . '/js/navigation.js',
array(),
'1.0.0',
array('strategy' => 'defer', 'in_footer' => true)
);
}); Допустимые значения strategy — defer и async. Для скриптов плагинов, которые нельзя переподключить, остаётся фильтр script_loader_tag: он переписывает готовый тег script перед выводом в разметку.
<?php
add_filter('script_loader_tag', function ($tag, $handle) {
if (is_admin()) {
return $tag;
}
$defer = array('my-theme-nav', 'my-theme-slider', 'my-theme-lightbox');
if (in_array($handle, $defer, true)) {
return str_replace(' src=', ' defer src=', $tag);
}
$async = array('yandex-metrika');
if (in_array($handle, $async, true)) {
return str_replace(' src=', ' async src=', $tag);
}
return $tag;
}, 10, 2); Как узнать дескриптор? Посмотрите исходный код страницы: у каждого тега есть id вида my-theme-nav-js — отбросьте суффикс -js, и получите имя для фильтра. Сниппеты удобно хранить в functions.php дочерней темы — так обновление основного шаблона их не затрёт; как её сделать, рассказано в гайде про дочернюю тему WordPress.
Три правила безопасности. Первое: не откладывайте jQuery и всё, что от него зависит, вслепую — у зависимых скриптов ломается порядок, если стратегии разные. Второе: точечность важнее широты — добавляйте атрибут конкретным дескрипторам, а не всем подряд. Третье: после каждой правки проверяйте сайт в режиме инкогнито и следите, чтобы атрибут не задвоился, если его уже добавил плагин.
Lazy-load изображений и фреймов: нативный loading=»lazy»
Со временем WordPress научился ленивой загрузке из коробки: изображениям с указанными размерами ядро само добавляет атрибут loading=»lazy», а фреймам — например, вставкам видео с YouTube — тот же атрибут ставится при фильтрации контента. Само по себе это уже экономит трафик и ускоряет первую отрисовку: браузер не тратит канал на то, что находится за пределами экрана.
Проблема появляется, когда под ленивую загрузку попадает главное изображение страницы. Браузер откладывает его загрузку до расчёта разметки, и Largest Contentful Paint ухудшается: посетитель дольше ждёт картинку, которая формирует первое впечатление. Поэтому главное изображение — обложку записи, баннер на главной, логотип — стоит исключать из ленивой загрузки и помечать атрибутом fetchpriority со значением high.
Исключить отдельное изображение можно фильтром, который ищет его по имени файла. Пример ниже пропускает через себя все теги с автоматическим атрибутом и возвращает false для логотипа.
<?php
add_filter('wp_img_tag_add_loading_attr', function ($value, $image, $context) {
if (false !== strpos($image, 'logo')) {
return false;
}
return $value;
}, 10, 3); В собственной разметке, которую вы выводите вручную — в шаблоне, шорткоде или блоке, — атрибут ставится напрямую. Заодно укажите размеры и decoding, чтобы браузер резервировал место и не дёргал вёрстку.
<img src="/wp-content/uploads/2026/09/katalog-tovarov.jpg" alt="Каталог товаров после оптимизации" loading="lazy" decoding="async" width="1200" height="800"> Логичное продолжение работы с медиа — сжатие файлов и современные форматы: как перейти на WebP и настроить адаптивные картинки, мы рассказывали в статье про оптимизацию изображений в WordPress.
Подгрузка JavaScript по событию: паттерн delayed loading
Есть класс скриптов, которым на странице вообще нечего делать до первого взаимодействия: виджет чата, карта, кнопки соцсетей, плеер, всплывающее окно подписки. Их можно не просто отложить, а загружать по событию: посетитель прокрутил страницу, двинул мышью, коснулся экрана — тогда и подключаем файл. До этого момента скрипт не скачивается вовсе, и старт страницы получается максимально лёгким.
(function () {
var loaded = false;
function loadWidget() {
if (loaded) { return; }
loaded = true;
var s = document.createElement('script');
s.src = '/wp-content/plugins/my-chat/assets/widget.js';
s.defer = true;
document.body.appendChild(s);
}
['scroll', 'mousemove', 'touchstart', 'keydown'].forEach(function (event) {
window.addEventListener(event, loadWidget, { once: true, passive: true });
});
window.setTimeout(loadWidget, 8000);
})(); В коде есть страховка: если пользователь не взаимодействует со страницей вовсе, таймер всё равно подключит виджет через восемь секунд после загрузки — быстрый интернет и медленный читатель останутся с чатом в любом случае. Разместить паттерн можно в отдельном файле темы, а подключать его — стандартно через wp_enqueue_script; главное — не оборачивать так критичную функциональность вроде корзины или формы оформления заказа.
Если хочется обойтись без кода, у WP Rocket и Perfmatters есть опция Delay JavaScript Execution: вы указываете скрипты, которые должны выполниться после первого взаимодействия, и плагин сам расставляет задержки. Механизм тот же, просто упакованный в интерфейс — начните со списка из виджетов и аналитики, а не со всех файлов сразу.
Шрифты: font-display, preload и локальный хостинг
Шрифты тормозят страницу двумя способами. Первый — подключение через внешний сервис: пока не загрузится CSS шрифтов, текст может оставаться невидимым. Второй — вес файлов: несколько начертаний по 100–200 КБ каждое конкурируют за канал с остальными ресурсами.
Лечится это тремя шагами. Первый — правило font-display: swap в описании шрифта: браузер сразу рисует текст системным шрифтом и подменяет его, когда файл догрузился. Второй — предзагрузка самых нужных начертаний через тег preload, чтобы они скачивались с высоким приоритетом. Третий — локальный хостинг вместо внешних сервисов: файлы кладутся в тему, загрузка ускоряется, а внешних зависимостей становится меньше.
@font-face {
font-family: 'Inter';
src: url('/wp-content/themes/my-theme/fonts/inter-400.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
} В дочернюю тему файлы удобно положить рядом с CSS, а предзагрузку добавить в head через свой хук. Обратите внимание на атрибут crossorigin: без него браузер скачает файл дважды.
<link rel="preload" href="/wp-content/themes/my-theme/fonts/inter-400.woff2" as="font" type="font/woff2" crossorigin="anonymous"> Тот же результат, если вывод удобнее держать в PHP.
<?php
add_action('wp_head', function () {
$font = get_stylesheet_directory_uri() . '/fonts/inter-400.woff2';
echo '<link rel="preload" href="' . esc_url($font) . '" as="font" type="font/woff2" crossorigin="anonymous">';
}, 1); Не предзагружайте больше двух-трёх начертаний: каждая запись preload — это высокий приоритет, и десяток таких записей задушит остальную загрузку. Основной текст вполне обходится одним-двумя весами, а остальные пусть подтягиваются в фоне.
Как проверить результат: инструменты и метрики
Отложенная загрузка меняет порядок сетевых запросов, поэтому проверять её нужно не на глаз, а приборами. Базовый набор: браузерные DevTools и Lighthouse; для глубокого разбора — WebPageTest. Сравнивайте «до и после» на одинаковых условиях: режим инкогнито, очищенный кэш, включённое ограничение скорости сети.
| Инструмент | Что проверяем | Ориентир |
|---|---|---|
| PageSpeed Insights и Lighthouse | Блокирующие ресурсы, Total Blocking Time, LCP | Предупреждений о скриптах нет или они короче, TBT снижается |
| DevTools, вкладка Network | Когда начинается загрузка скриптов и фреймов | Виджеты грузятся после взаимодействия, а не в первых запросах |
| DevTools, вкладка Coverage | Доля неиспользованного JavaScript на старте | Стартовая загрузка худеет, «мусорный» код уходит в отложенные файлы |
| WebPageTest | Водопад запросов и раскадровка загрузки | Первый экран рисуется до тяжёлых скриптов |
Быстрая проверка в консоли — посмотреть, появляются ли долгие задачи при загрузке: это куски JavaScript, которые блокируют главный поток и мешают странице реагировать.
new PerformanceObserver(function (list) {
list.getEntries().forEach(function (entry) {
console.log('Долгая задача:', Math.round(entry.duration), 'мс');
});
}).observe({ type: 'longtask', buffered: true }); Полноценный отчёт собирается одной командой — это тот же движок, что работает в PageSpeed Insights.
npx lighthouse https://example.com --only-categories=performance --preset=desktop --view В отчёте смотрите на три вещи: исчезли ли предупреждения о блокирующих скриптах, сократился ли Total Blocking Time и не появилось ли новых проблем с вёрсткой. И помните про кэш: после правок очистите и серверный, и браузерный кэш, иначе будете тестировать старую версию файлов — общие принципы собраны в статье про кэширование WordPress.
Типичные ошибки и подводные камни
defer для jQuery-зависимых скриптов. Если отложить библиотеку, но не её «спутники», исполнится не то и не тогда: зависимый файл может обогнать jQuery. Проверяйте цепочки зависимостей и переводите связку целиком, следя за сохранением порядка.
Инлайн-код против defer. Маленький блок кода в HTML выполняется во время разбора страницы, а отложенный файл — после. Если инлайн-код вызывает функцию из файла, будет ошибка «функция не определена». Такие инициализации нужно переносить в отложенный файл или оборачивать в событие DOMContentLoaded.
Двойная оптимизация. Плагин уже добавил defer, а вы добавили его ещё раз фильтром. Дубли обычно безобидны, но ломают диагностику: непонятно, чей именно атрибут сработал. Перед добавлением проверьте, не управляет ли этим же скриптом плагин.
Ленивая загрузка главного изображения. Обложка статьи и баннер главной — не место для loading=»lazy»: LCP ухудшается, пользователь видит пустой блок. Главные изображения грузите сразу, с fetchpriority high, а лениво — только то, что ниже первого экрана.
Delay для критичной функциональности. Откладывать до взаимодействия корзину, калькулятор или форму заказа нельзя: человек нажмёт кнопку раньше, чем подгрузится скрипт, и решит, что сайт сломан. Список отложенного держите коротким: чаты, карты, соцвиджеты.
Предзагрузка всего подряд. Десяток preload шрифтов и скриптов — это очередь с высоким приоритетом, которая тормозит важные ресурсы. Предзагружайте один-два ключевых ресурса, остальное отдайте браузеру.
Тестирование со старым кэшем. После каждой правки очищайте кэш и проверяйте сайт в инкогнито: иначе выводы будут о прошлой версии. Если после изменений что-то пошло не так, включите отладку по инструкции WP_DEBUG и отладка WordPress и посмотрите логи — ошибки в хуках видно сразу.
Правки без бэкапа и обновления наспех. Скрипты плагинов меняются при обновлениях, поэтому держите свежие копии: как настроить резервное копирование WordPress, мы уже рассказывали. А сами обновления ставьте по правилам безопасного обновления WordPress — и тогда оптимизация не превратится в ремонт.

Частые вопросы об отложенной загрузке в WordPress
Что такое отложенная загрузка простыми словами?
Это приёмы, которые освобождают первый экран от второстепенных ресурсов. Скрипты со стратегиями defer и async не блокируют построение страницы, изображения и фреймы с атрибутом lazy загружаются по мере прокрутки, шрифты появляются в тексте без невидимой паузы. В сумме это даёт более быстрый старт и лучшие метрики, чем обычная синхронная загрузка.
В чём разница между defer и async?
Оба атрибута скачивают скрипт параллельно с разбором страницы. Разница в выполнении: defer запускает файл после построения DOM и сохраняет порядок подключения, async выполняет сразу после загрузки, порядок при этом не гарантируется. Практический вывод: defer — для скриптов темы и плагинов, которым важны DOM и последовательность, async — для независимых счётчиков и аналитики.
Можно ли включить отложенную загрузку без кода?
Да. Плагины Autoptimize, WP Rocket, Perfmatters и Clearfy умеют добавлять стратегии загрузки и откладывать выполнение JavaScript без единой строки кода. Достаточно включить нужные опции, очистить кэш и проверить меню, формы и слайдеры. Начните с базового набора настроек и добавляйте тонкие опции только после тестов.
Почему после добавления defer что-то перестало работать?
Почти всегда это порядок выполнения: зависимый скрипт обогнал основной или инлайн-код в HTML выполнился раньше отложенного файла. Уберите атрибут у проблемного дескриптора, проверьте зависимости при подключении скриптов и перенесите инлайн-инициализацию в отдельный файл. Точечная отладка через WP_DEBUG быстро покажет виновника.
Стоит ли включать ленивую загрузку для всех изображений?
Нет. Ленивая загрузка нужна изображениям ниже первого экрана, а главную картинку страницы — обложку записи, баннер, логотип — лучше грузить сразу, иначе Largest Contentful Paint ухудшится. Для главных изображений оставляйте обычную загрузку и добавляйте fetchpriority со значением high, а атрибут lazy — для всего, что появляется после прокрутки.
Как проверить, что скрипты загружаются отложенно?
Откройте вкладку Network в DevTools: у отложенных скриптов загрузка начнётся после построения страницы или после вашего действия, а не в первых строках водопада. Затем прогоните страницу в Lighthouse и сравните блокирующие ресурсы и метрики до и после. Финальная проверка — вручную пройти ключевые сценарии в режиме инкогнито.
Вывод
Отложенная загрузка — это не один приём, а порядок в ресурсах: defer и async убирают блокировку из скриптов, loading=»lazy» переносит картинки и фреймы за пределы первого экрана, font-display и preload наводят порядок в шрифтах, а паттерн delayed loading избавляет от виджетов до первого взаимодействия. Каждый шаг делается маленькими правками и проверяется инструментами.
Начните с малого: посмотрите исходный код страницы, выделите два-три самых тяжёлых скрипта и переведите их на defer, главное изображение — на fetchpriority, виджеты — на подгрузку по событию. Дальше измерьте метрики и двигайтесь по списку до конца. Если не хочется разбираться с фильтрами и тестировать сценарии вручную, доверьте это команде.
Мы настроим отложенную загрузку скриптов, изображений и шрифтов так, чтобы сайт стал быстрее без поломок интерфейса. Посмотрите услуги по разработке и поддержке сайтов, изучите портфолио выполненных проектов и почитайте блог о разработке и продвижении. Если сайт работает и нужна точечная оптимизация, можно заказать доработку сайта у программиста, а описать задачу — через форму контактов.



