Как мне отложить или асинхронизировать этот фрагмент javascript WordPress для окончательной загрузки для ускорения загрузки страницы?
У меня есть различные javascripts, которые являются необходимыми плагинами в одном из моих доменов WordPress, и я знаю, откуда в файле php он вызывается.
Я принимаю все возможные меры, чтобы ускорить загрузку страниц, и каждый тестер скорости в Интернете говорит, что по возможности следует отложить javascripts.
Я читал о defer='отложить' и асинхронных функциях в javascript, и я думаю, что одна из них выполнит то, что я пытаюсь выполнить. Но я не понимая, как бы я сделал это в php-файле.
Например, вот фрагмент из php-файла одного конкретного плагина, в котором вызывается файл javascript:
function add_dcsnt_scripts() {
wp_enqueue_script( 'jquery' );
wp_enqueue_script( 'dcsnt', dc_jqsocialtabs::get_plugin_directory() . '/js/jquery.social.media.tabs.1.7.1.min.js' );
}
Я читал, что лучше всего сделать что-то подобное для ускорения загрузки страницы:
<script defer async src="..."></script>
Но я не знаю, как это сделать в php-файле. Я хочу сделать это со всеми моими файлами javascript.
Как бы я мог выполнить перенос или синхронизацию этого фрагмента javascript для загрузки последний и ускоряет загрузку страницы? Каков был бы идеальный способ увеличить время загрузки страниц во всех браузерах? Спасибо за любое руководство, которое кто-либо может предложить!
11 answers
Это сообщение в блоге ссылается на два интересных плагина:
Асинхронный Javascript
Улучшите производительность загрузки страниц за счет асинхронной загрузки javascript с помощью head.js
WP Отложенные Javascripts
Отложите загрузку всех javascripts, добавленных с помощью wp_enqueue_scripts, используя LABJS (асинхронную библиотеку javascript).
Не тестировал их, но проверил код, и они делайте довольно причудливые вещи с помощью процесса постановки скриптов WordPress в очередь.
Но затем WPSE приходит на помощь:
// Adapted from https://gist.github.com/toscho/1584783
add_filter( 'clean_url', function( $url )
{
if ( FALSE === strpos( $url, '.js' ) )
{ // not our file
return $url;
}
// Must be a ', not "!
return "$url' defer='defer";
}, 11, 1 );
Или более универсальный способ:
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 в URL-адрес скрипта как:
wp_enqueue_script('dcsnt', '/js/jquery.social.media.tabs.1.7.1.min.js#asyncload' )
Пытаясь сохранить все в некоторой степени модульным и всеобъемлющим, следующий подход динамически выбирает способ встраивания тега с атрибутами async или defer, просто добавляя небольшой идентификатор к имени дескриптора $:
/**
* Add async or defer attributes to script enqueues
* @author Mike Kormendy
* @param String $tag The original enqueued <script src="...> tag
* @param String $handle The registered unique name of the script
* @return String $tag The modified <script async|defer src="...> tag
*/
// only on the front-end
if(!is_admin()) {
function add_asyncdefer_attribute($tag, $handle) {
// if the unique handle/name of the registered script has 'async' in it
if (strpos($handle, 'async') !== false) {
// return the tag with the async attribute
return str_replace( '<script ', '<script async ', $tag );
}
// if the unique handle/name of the registered script has 'defer' in it
else if (strpos($handle, 'defer') !== false) {
// return the tag with the defer attribute
return str_replace( '<script ', '<script defer ', $tag );
}
// otherwise skip
else {
return $tag;
}
}
add_filter('script_loader_tag', 'add_asyncdefer_attribute', 10, 2);
}
Пример использования:
function enqueue_my_scripts() {
// script to load asynchronously
wp_register_script('firstscript-async', '//www.domain.com/somescript.js', '', 2, false);
wp_enqueue_script('firstscript-async');
// script to be deferred
wp_register_script('secondscript-defer', '//www.domain.com/otherscript.js', '', 2, false);
wp_enqueue_script('secondscript-defer');
// standard script embed
wp_register_script('thirdscript', '//www.domain.com/anotherscript.js', '', 2, false);
wp_enqueue_script('thirdscript');
}
add_action('wp_enqueue_scripts', 'enqueue_my_scripts', 9999);
Выходные данные:
<script async type='text/javascript' src='//www.domain.com/somescript.js'></script>
<script defer type='text/javascript' src='//www.domain.com/otherscript.js'></script>
<script type='text/javascript' src='//www.domain.com/anothercript.js'></script>
Спасибо @Mattkeys @crissoca за вдохновляющий мой ответ здесь.
Другое решение, использующее другой фильтр, который можно использовать для нацеливания на определенный дескриптор скрипта:
function frontend_scripts()
{
wp_enqueue_script( 'my-unique-script-handle', 'path/to/my/script.js' );
}
add_action( 'wp_enqueue_scripts', 'frontend_script' );
function make_script_async( $tag, $handle, $src )
{
if ( 'my-unique-script-handle' != $handle ) {
return $tag;
}
return str_replace( '<script', '<script async', $tag );
}
add_filter( 'script_loader_tag', 'make_script_async', 10, 3 );
Упрощенный метод. Добавьте в свой functions.php файл, чтобы сделать JavaScript асинхронным в Wordpress
// Make JavaScript Asynchronous in Wordpress
add_filter( 'script_loader_tag', function ( $tag, $handle ) {
if( is_admin() ) {
return $tag;
}
return str_replace( ' src', ' async src', $tag );
}, 10, 2 );
Чтобы получить контроль над тем, какие файлы js следует отложить, и избежать конфликтов, вы можете добавить переменную к URL-адресу в функции wp_register_script, как показано ниже.
wp_register_script( 'menu', get_template_directory_uri() . '/js/script.js?defer', array('jquery'), '1.0', true );
Затем измените строку:
if ( FALSE === strpos( $url, '.js' ))
Кому:
if ( FALSE === strpos( $url, '.js?defer' ))
Новый фильтр выглядит следующим образом.
add_filter( 'clean_url', function( $url )
{
if ( FALSE === strpos( $url, '.js?defer' ) )
{ // not our file
return $url;
}
// Must be a ', not "!
return "$url' defer='defer";
}, 11, 1 );
Включите атрибут async
в сценарии, чтобы они загружались только после загрузки всей страницы
<script type="text/javascript">
function ngfbJavascript( d, s, id, url ) {
var js, ngfb_js = d.getElementsByTagName( s )[0];
if ( d.getElementById( id ) ) return;
js = d.createElement( s );
js.id = id;
js.async = true;
js.src = url;
ngfb_js.parentNode.insertBefore( js, ngfb_js );
};
</script>
Источник: Здесь
Что-то, чтобы добавить решение фильтра clean_url
, убедитесь, что оно используется только в конце шрифта, возможно, использование if( ! is_admin() ){}
популярных плагинов, таких как ACF, может вызвать у вас головную боль.
Обновление
Вот моя измененная версия решения:
if( ! is_admin() ){
add_filter( 'clean_url', 'so_18944027_front_end_defer', 11, 1 );
function so_18944027_front_end_defer( $url ) {
if ( FALSE === strpos( $url, '.js' ) )
{ // not our file
return $url;
}
// Must be a ', not "!
return "$url' defer='defer";
}
}
Я считаю, что откладывать/синхронизировать jQuery WordPress - плохая практика. Лучшим решением было бы исключить jQuery из фильтра:
if (!is_admin()) {
add_filter( 'script_loader_tag', function ( $tag, $handle ) {
if ( strpos( $tag, "jquery.js" ) || strpos( $tag, "jquery-migrate.min.js") ) {
return $tag;
}
return str_replace( ' src', ' async src', $tag );
}, 10, 2 );
}
Вы можете использовать defer
вместо async
Очень маленький код модификации Майк Корменди, который позволяет добавлять сразу 2 атрибута:
// Async load
function add_asyncdefer_attribute($tag, $handle)
{
$param = '';
if ( strpos($handle, 'async') !== false ) $param = 'async ';
if ( strpos($handle, 'defer') !== false ) $param .= 'defer ';
if ( $param )
return str_replace('<script ', '<script ' . $param, $tag);
else
return $tag;
}
Результат:
<script async defer type='text/javascript' src='#URL'></script>
Правильный способ сделать это
wp_script_add_data( 'script-handle', 'async/defer' , true );