Статья актуализирована для версии WP 5.6, менять её буду только в том случае, если код перестанет работать.
Нужна помощь? Не проблема, напишите мне на почту: admin@workinnet.ru
С версии WP 4.1 был добавлен отличный фильтр — script_loader_tag. Теперь нет необходимости извергать пламя из не предназначенных для того мест при добавление к скриптам атрибутов async или defer. Все делается довольно просто.
P. S. весь предложенный ниже код подключать требуется через файл functions.php, желательно, в рамках дочерней темы. Также можно вынести в собственный плагин. Прочитайте о создании собственного плагина.
Соответственно, предлагаю вам рабочий вариант кода для асинхронной загрузки. Это результат небольшой переработки нижеследующих вариантов, но главное отличие в том, что «ручками» вам придётся только исключать код, который не хочет работать асинхронно. Нижеприведённый код оптимизирован под версию 5.6 и работает, рекомендую использовать именно его. Если кто-то устанавливал ранее приведённый код, то измените, иначе будете получать следующую ошибку:
jquery-migrate.min.js?ver=3.3.2:2 Uncaught ReferenceError: jQuery is not defined
А теперь сам код для асинхронной загрузки скриптов:
<?php
if (!is_admin()) {
add_filter( 'script_loader_tag', function ( $tag, $handle ) {
if ( strpos( $tag, "jquery.js" ) || strpos( $tag, "jquery-migrate.min.js") || strpos ($tag, "jquery.min.js" ) ) {
return $tag;
}
return str_replace( ' src', 'async src', $tag );
}, 10, 2 );
}
Все исключения вносите в эту строку в таком же формате.
if ( strpos( $tag, "jquery.js" ) || strpos( $tag, "jquery-migrate.min.js") ) //Исключение указывайте в таком виде "strpos( $tag, "jquery-migrate.min.js")", не забудьте разделитель ||
Если решите использовать отложенную загрузку, то вот вам вариант для неё.
add_filter( 'script_loader_tag', function ( $tag, $handle ) {
if ( strpos( $tag, "jquery.js" ) || strpos( $tag, "jquery-migrate.min.js") || strpos ($tag, "jquery.min.js" ) ) {
return $tag;
}
return str_replace( ' src', 'defer src', $tag );
}, 10, 2 );
}
Я всего лишь заменил async на defer.
Ну а если предложенные варианты не помогли, то попробуйте то, что указал ниже.
В самом начале я старался использовать что-нибудь универсальное, чтобы не было проблем, например, это:
function wcs_defer_javascripts ( $url ) { if(is_admin()) return $url; if ( FALSE === strpos( $url, '.js' ) ) return $url; if ( strpos( $url, 'jquery.js') ) return $url; return "$url' defer='defer"; } add_filter( 'clean_url', 'wcs_defer_javascripts', 11, 1 );
Для запуска асинхронной загрузки достаточно поменять строку:
return "$url' defer='defer";
на:
return "$url' async='async";
Но, такой код не всегда давал значительный прирост, да и мог порушить структуру сайта.
Я решил задачку усложнить, чтобы более точно управлять отложенной и асинхронной загрузкой в WordPress и нашел такое решение:
function add_async_forscript($url) { if (strpos($url, '#asyncload')===false) return $url; else if (is_admin()) return str_replace('#asyncload', '', $url); else return str_replace('#asyncload', '', $url)."' async='async"; } add_filter('clean_url', 'add_async_forscript', 11, 1);
Теперь к любому скрипту можно просто добавить #asyncload, чтобы присвоить атрибут async. Пример ниже:
wp_enqueue_script('myscriptass', 'assest/js/myscriptass.js#asyncload' );
Таким образом требуется подключать скрипты в файле functions.php.
Для отложенной загрузки создавал аналогичный код с атрибутами defer. Все довольно просто. Но есть более правильное решение, о котором расскажу дальше. И появилось оно вместе с выпуском WP 4.1 и добавлением нового фильтра.
apply_filters('script_loader_tag', string $tag, string $handle, string $src); //виновник торжества
Собственно, это нужный фильтр. Просто для примера, его вставлять никуда не требуется.
Теперь переходим непосредственно к добавлению асинхронной загрузки на отдельный скрипт:
function add_async_attribute($tag, $handle) { if ( 'my-js-handle' !== $handle ) return $tag; return str_replace( ' src', ' async="async" src', $tag ); } add_filter('script_loader_tag', 'add_async_attribute', 10, 2);
Если необходимо добавить отложенную загрузку, то код будет выглядеть так:
function add_defer_attribute($tag, $handle) { if ( 'my-js-handle' !== $handle ) return $tag; return str_replace( ' src', ' defer="defer" src', $tag ); } add_filter('script_loader_tag', 'add_defer_attribute', 10, 2);
Как видите, просто заменили async на defer.
Наверное, содержание вызвало вопрос. Итак, все довольно просто. Данная функция проверяет скрипт на соответствие. Если js не соответствует параметру $handle, то возвращает атрибут по умолчанию, если же соответствует, то присваивает нужный атрибут. Наверное, возник вопрос, где найти значение $handle?
В таких строках:
wp_register_script('my-js-handle', $src, $deps, $ver, $in_footer);
или:
wp_enqueue_script('my-js-handle', $src, $deps, $ver, $in_footer);
Располагаться они могут практически в любом файле, который запускает загрузку скриптов. На скриншоте показываю наглядно, что вам нужно найти.
Ничего сложно, кроме того, что на каждый скрипт пилить такую структуру трудоемко, потому, сделаем код более массовым.
function add_defer_attribute($tag, $handle) { // добавляем дескрипторы в массив $scripts_to_defer = array('my-js-handle', 'another-handle'); //здесь размещаем те самые $handle foreach($scripts_to_defer as $defer_script) { if ($defer_script === $handle) { return str_replace(' src', ' defer="defer" src', $tag); } } return $tag; } add_filter ('script_loader_tag', 'add_defer_attribute', 10, 2);
Отличие кода только в том, что на соответствие проверяются все значения массива. И если соответствие найдено, то будет присвоен атрибут defer. Для асинхронной загрузки код отдельный.
function add_async_attribute($tag, $handle) { // добавляем дескрипторы в массив $scripts_to_async = array('my-js-handle', 'another-handle'); //здесь размещаем те самые $handle foreach($scripts_to_async as $async_script) { if ($async_script === $handle) { return str_replace(' src', ' async="async" src', $tag); } } return $tag; } add_filter ('script_loader_tag', 'add_async_attribute', 10, 2);
Чем хорош данный вариант? Можно с легкостью разбить часть скриптов на отложенные, другую на асинхронные, избежав конфликтов. Но для этого придется понимать, как и в какой последовательности работают скрипты на сайте.
Надеюсь, сумел вам помочь, задача нелегкая, но, как видите, решаемая.
Кл куда вставлять этот?
<?php
if (!is_admin()) {
add_filter( 'script_loader_tag', function ( $tag, $handle ) {
if ( strpos( $tag, "jquery.js" ) || strpos( $tag, "jquery-migrate.min.js") || strpos ($tag, "jquery.min.js" ) ) {
return $tag;
}
return str_replace( ' src', 'async src', $tag );
}, 10, 2 );
}
в файл функцион.пнп? до какого тега? до боди?
К тегу body этот код вообще не имеет никакого отношения, он работает со всеми скриптами, которые есть на сайте, кроме тех, что подгружаются с внешних источников (например, коды счётчиков), вообще, если у вас в functions.php есть теги разметки шаблонов, то это не очень хорошо, этот файл предназначен для другого. В общем, этот код можно добавить в functions.php, желательно создать дочернюю тему, иначе при обновлении темы весь код слетит, если вы не используете дочернюю тему, то можно сделать собственный плагин и вынести код туда. Разницы никакой. Но плагин будет удобнее.