Добавление  defer  к вашим скриптам — один из самых простых и «дешёвых» способов ускорить сайт на WordPress. Но это же изменение чаще всего ломает меню, слайдеры или поля оформления заказа. В этой статье мы на небольшом примере разберём, почему так происходит, и рассмотрим безопасный способ внедрения.

Раскрытие информации: я вхожу в команду разработчиков NodeThemes Cache AI — бесплатного плагина кэширования для WordPress, который тестирует подобные изменения. Описанная ниже методика работает независимо от того, используете вы его или нет.

Что на самом деле меняет  defer 

Классический  <script src>  в  <head>  блокирует парсинг: браузер скачивает и выполняет его до того, как построит остальную часть страницы. С атрибутом  defer  браузер продолжает парсинг и выполняет скрипт позже. Согласно документации MDN, отложенные скрипты:

  • выполняются после завершения парсинга документа, но перед  DOMContentLoaded 
  • выполняются в порядке их появления в коде
  • применяются только к внешним скриптам ( defer  во встроенном (inline) скрипте ни на что не влияет)
Атрибут Блокирует парсинг? Когда выполняется Сохраняется ли порядок?
отсутствует Да Сразу же Да
 defer  Нет После парсинга Да
 async  Нет Сразу после загрузки Нет

Специфическая проблема WordPress: встроенные скрипты

Темы и плагины WordPress очень любят выводить небольшой inline-скрипт сразу после файла. Функция  wp_add_inline_script()  делает именно это, да и многие темы выводят собственный код через echo:

 <script src="/wp-includes/js/jquery/jquery.min.js"></script>
<script>
  jQuery(function ($) { $('.hero-slider').slick(); });
</script>
 

Теперь добавим defer к файлу:

 <script src="/wp-includes/js/jquery/jquery.min.js" defer></script>
<script>
  jQuery(function ($) { $('.hero-slider').slick(); }); // runs NOW
</script>
 

Встроенный блок кода не откладывается, поэтому он выполняется в момент, когда jQuery ещё не загрузился:

 Uncaught ReferenceError: jQuery is not defined
 

Слайдер остаётся пустым, и пока кто-нибудь не откроет консоль, никто не поймёт, в чём причина. То же самое происходит с  … is not a function , когда скрипт плагина откладывается, а другой скрипт вызывает его раньше времени.

Пошаговое безопасное внедрение

  1.  Отложите всё, кроме jQuery. Оставьте  jquery.min.js  и  jquery-migrate  загружаться в обычном режиме; они являются самой частой зависимостью для inline-кода.
  2.  Протестируйте ключевые страницы: главную, запись, страницу, магазин и карточку товара. Открывайте меню, вкладки и слайдеры, а не только первый экран.
  3.  Изучите консоль. Ошибка укажет файл и строку. Добавьте этот файл в список исключений («не откладывать»).
  4.  Повторяйте до тех пор, пока не исчезнут новые ошибки, после чего выкатывайте в продакшен.
  5.  Повторно тестируйте после обновлений тем и плагинов. Обновление может добавить новый inline-код.

Быстрый способ обнаружить новые ошибки — сравнить состояние консоли до и после изменений. Ошибки, которые возникали и без  defer , сегодня не ваша проблема; внимание нужно обратить только на новые.

Автоматизация сравнения

Делать всё это вручную — значит постоянно перезагружать страницы с открытым DevTools, поэтому мы автоматизировали этот процесс в бесплатном плагине NodeThemes Cache AI. Он открывает каждую тестовую страницу в скрытых фреймах прямо в браузере администратора: дважды без новых настроек и один раз с ними. Затем он сравнивает:

  • ошибки JavaScript (только новые, чтобы уже существующие ошибки на сайте не приводили к сбою теста)
  • файлы и изображения, которые не удалось загрузить
  • размер основных частей страницы и высоту страницы

Настройки, не прошедшие проверку, не применяются, а любое изменение можно отменить в один клик. Pro-версия идет ещё дальше в случае неудачи: она делит отложенные скрипты пополам и повторно тестирует их, пока не найдет те несколько файлов, которые нельзя откладывать, оставляя все остальные с атрибутом defer.

Помогает ли это Core Web Vitals?

Часто да, в основном показателю LCP, так как страница может отрисоваться до выполнения скриптов. Проводите измерения на мобильных устройствах, сравнивайте корректные сопоставимые данные и подтверждайте результаты метриками реальных пользователей в течение следующих дней.

Полное руководство с ответами на частые вопросы и подробной спецификой WordPress доступно здесь: Defer JavaScript in WordPress without breaking your site.