WP 6.3: Атрибуты ASYNC и DEFER при регистрации скриптов

WP 6.3: Атрибуты ASYNC и DEFER при регистрации скриптов

В WordPress версии 6.3 появилась поддержка регистрации скриптов с атрибутами async и defer. Это улучшение было добавлено в рамках обновления существующего API для работы со скриптами и решает давнюю проблему, описанную в тикете #12009.

Теперь доступны следующие стратегии загрузки скриптов:

  • Блокировка — скрипт блокирует загрузку страницы. Это поведение по умолчанию.
  • Отложенная загрузка — стратегия defer.
  • Асинхронная загрузка — стратегия async.

Содержание

Зачем это нужно?

Добавление атрибутов defer или async к тегам скриптов позволяет загружать скрипты без "блокировки" загрузки остальной части страницы. Это улучшает производительность сайта, особенно по метрике Largest Contentful Paint (LCP).

Ранее разработчики использовали менее удобные альтернативы, например:

  • Прямое фильтрование тегов на этапе вывода с использованием фильтра script_loader_tag.
  • Использование фильтра clean_url, что считалось плохой практикой.
  • Обработка вывода тегов со скриптами через wp_print_script_tag.

Все эти подходы не учитывают зависимости скриптов, что может приводить к проблемам совместимости или ошибкам при работе с другими скриптами.

Кратко о различиях между defer и async:

  • Отложенные скрипты (defer): Скрипты с этим атрибутом выполняются только после полной загрузки DOM-дерева (но до события DOMContentLoaded). Скрипты, помеченные defer, выполняются в порядке их появления в HTML.

  • Асинхронные скрипты (async): Скрипты с этим атрибутом загружаются без блокировки страницы (браузер не ждет загрузки скрипта) и выполняются сразу после загрузки. Асинхронные скрипты не соблюдают порядок, в котором они появляются в коде.

Что изменилось в WordPress

Изменения можно описать так:

  • WordPress теперь позволяет указывать стратегию загрузки скриптов при вызовах функций wp_register_script() и wp_enqueue_script().

  • Эти функции получили новые сигнатуры — вместо параметра boolean $in_footer теперь используется массив $args, в котором можно указать, как и где должен з��гружаться скрипт. Обратная совместимость с типом boolean сохранена.

  • Стратегию загрузки также можно указать через wp_script_add_data(), что может быть полезно для совместимости с предыдущими версиями кода.

  • Класс WP_Scripts был доработан для поддержки новых стратегий загрузки.

Пример: отложенная загрузка скрипта в заголовке

Стратегию загрузки можно указать, передав массив с параметрами в функцию wp_register_script():

wp_register_script(
'my_script',
'https://example.com/path/to/my_script.js',
[],
'1.0',
[
'strategy' => 'defer'
]
);

Пример: асинхронная загрузка скрипта в подвале

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

wp_register_script(
'my_script',
'https://example.com/path/to/my_script.js',
[],
'1.0',
[
'in_footer' => true,
'strategy' => 'async',
]
);

Детали реализации

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

Реализация загрузки скриптов была выполнена без разрушения существующего API. Улучшения касаются всех функций API скриптов, таких как wp_register_script() и wp_enqueue_script().

О зависимостях

Для ясности давайте разъясним различие между зависимыми скриптами и зависимостями:

  • Зависимые скрипты — это скрипты, которые зависят от текущего скрипта, т.е. они автоматически включают текущий скрипт перед своей загрузкой.

  • Зависимости — это скрипты, от которых зависит текущий скрипт, т.е. их необходимо загрузить до вызова текущего скрипта.

Изменения в параметре $in_footer функций wp_register_script() и wp_enqueue_script()

Наиболее заметным изменением в функциях wp_register_script() и wp_enqueue_script() стало изменение сигнатуры, где параметр $in_footer теперь принят в виде массива $args с ключами:

  • in_footer (bool) — ведет себя так же, как и предыдущая реализация параметра $in_footer.
  • strategy (string) — указывает, какой стратегией следует использовать для загрузки скрипта. В настоящее время доступны два значения: defer и async.

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

wp_script_add_data() - Поддержание совместимости

Полная обратная совместимость сохраняется для предыдущего использования функций wp_register_script() и wp_enqueue_script() с использованием булевого параметра $in_footer. Это означает, что данное улучшение не нарушает API.

Хотя изменения не критичны, при использовании нового параметра $args в плагинах или темах, работающих на версиях WordPress < 6.3, возможно недопонимание параметра $in_footer.

Простой способ избежать таких проблем совместимости — использовать функцию wp_script_add_data():

wp_register_script(
'my_script',
'https://example.com/path/to/my_script.js',
[],
'1.0.0',
false
);

wp_script_add_data('my_script', 'strategy', 'defer');

Изменение указанной стратегии из-за зависимостей

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

Например, если разработчик зарегистрировал скрипт с атрибутом defer, но зависимые от него скрипты используют блокирующую стратегию, то скрипт с атрибутом defer и все его зависимости автоматически станут блокирующими.

Новая логика в классе WP_Scripts отвечает за выполнение логических проверок, чтобы убедиться, что итоговая стратегия для данного скрипта является оптимальной на основе описанных факторов.

Встраиваемые скрипты

Не забудьте о функции wp_add_inline_script() для добавления встроенных скриптов.

Существуют некоторые нюансы при применении стратегии загрузки для скриптов, которые зависят от встроенных скриптов. Встроенные скрипты, зарегистрированные в позиции "до", ведут себя почти неизменно, так как они включаются до применения каких-либо стратегий.

Однако встроенные скрипты, зарегистрированные в позиции "после", могут повлиять на финальную стратегию загрузки родительского скрипта, если у него установлены атрибуты async или defer. Это может изменить зависимость итогового дерева скриптов.

Для дальнейших обсуждений на эту тему и возможных изменений был открыт дополнительный тикет #58632.

Переход на новый API

Код, использующий устаревшие методы для добавления атрибутов async или defer к тегам скриптов, должен перейти на новый API. Это касается и тех скриптов, где атрибуты добавлялись с помощью фильтра script_loader_tag или фильтра clean_url.

Пример 1: Добавление атрибута DEFER через script_loader_tag

add_filter('script_loader_tag', 'old_approach', 10, 2);

function old_approach($tag, $handle) {
if ('foo' !== $handle) {
return $tag;
}
return str_replace(' src=', ' defer src=', $tag);
}

Пример 2: Добавление атрибута DEFER через clean_url

add_filter('clean_url', 'old_brittle_approach');

function old_brittle_approach($url) {
if (false === strpos($url, 'foo.js')) {
return $url;
}
return "$url' defer ";
}

Если вы используете подход, подобный описанному выше, для добавления атрибутов defer или async, перейдите на новый API, используя один из ранее описанных методов.


Таким образом, в WordPress 6.3 введены важные изменения для улучшения управления загрузкой скриптов, что непосредственно сказывается на производительности сайтов.

Leave a Reply

Ваш адрес email не будет опубликован. Обязательные поля помечены *