Как подключить основной jQuery в футере?
У меня в файле functions.php
есть следующий код, но я не могу добиться загрузки jQuery в футере. Файл includes
загружается в футере нормально. Что еще нужно сделать?
function starter_scripts() {
wp_enqueue_style( 'starter-style', get_stylesheet_uri() );
wp_enqueue_script( 'jquery', '', '', '', true );
wp_enqueue_script( 'includes', get_template_directory_uri() . '/js/min/includes.min.js', '', '', true );
}
add_action( 'wp_enqueue_scripts', 'starter_scripts' );

Вот еще один вариант, который позволяет избежать необходимости снимать и заново регистрировать скрипты:
/**
* Перемещение jQuery в подвал (футер) страницы.
*/
function wpse_173601_enqueue_scripts() {
wp_scripts()->add_data( 'jquery', 'group', 1 );
wp_scripts()->add_data( 'jquery-core', 'group', 1 );
wp_scripts()->add_data( 'jquery-migrate', 'group', 1 );
}
add_action( 'wp_enqueue_scripts', 'wpse_173601_enqueue_scripts' );
Это решение имитирует поведение ядра WordPress, устанавливая параметр group
в значение 1
, что определяет, должен ли скрипт загружаться в подвале страницы (как отметил @jgraup в комментариях, выбор значения 1
кажется несколько произвольным, точная логика этого выбора неизвестна).

Интересно. Похоже, что wp_register_script
использует add_data( $handle, 'group', 1 )
для перемещения скриптов в футер. https://core.trac.wordpress.org/browser/tags/4.5/src/wp-includes/functions.wp-scripts.php#L117 - Не могли бы вы подробнее рассказать, почему это так? На первый взгляд, параметр 'group' кажется несколько произвольным. Но в коде видно, как он используется в WP_Scripts->do_item
дальше, согласно https://core.trac.wordpress.org/browser/tags/4.5/src/wp-includes/class.wp-scripts.php#L231. В любом случае, это кажется наименее разрушительным решением.

Надеюсь, кто-то сможет прокомментировать эти три ответа с высоким рейтингом. Все они разные и требуют некоторых знаний WordPress. Поскольку Google требует, чтобы эти скрипты находились ниже сгиба страницы, это важная тема.

Лучший ответ! Примечание: работает начиная с WordPress 4.2.0, используйте его в functions.php в хуке 'wp_enqueue_scripts'.

Привет, я попробовал указанный выше подход, но он не сработал. Кто-нибудь может помочь?

@iSaumya Возможно, вам стоит добавить некоторые детали о том, почему это не сработало / что произошло. Это довольно загадочный запрос! Также ознакомьтесь с другим новым ответом и учтите, что этот ответ всё ещё нужно обернуть в функцию и вызов фильтра.

@tim Я попробовал это, но скрипт по-прежнему не перемещается в футер. Вот что произошло.

@iSaumya Я добавил для вас дополнительные детали, надеюсь, это поможет!

WordPress использует настолько старую версию jQuery, что на данном этапе лучше отменить регистрацию и зарегистрировать новейшую версию.

Это просто отлично! Большое спасибо. Однако, стоит отметить, как указывает @tehlivi — WordPress использует старую версию jQuery — подумайте об отмене регистрации и регистрации более новой версии.

@MarcoPanichi возможно, у вас конфликтующая тема или плагин? Попробуйте проверить на чистой установке WordPress без плагинов, используя стандартную тему?

@MatthewBoynes Думаю, вы правы. На другой установке всё работает.

@MatthewBoynes Я всё ещё ищу больше разработчиков, которые хотели бы помочь поддерживать проект с открытым исходным кодом, см.: https://wordpress.org/plugins/jquery-manager/ и https://github.com/Remzi1993/jquery-manager Этот плагин/проект должен помочь пользователям использовать последнюю версию jQuery простым кликом.

Это работает, но 1
— это "магическое число". Если оно изменится, этот код сломается. И, к сожалению, мы не знаем, что оно означает, поэтому не можем заменить его константой. Кто-нибудь на самом деле знает, на что оно ссылается?

Параметр 1 отвечает на вопрос "Должны ли мы переместить скрипт в футер?" в функции — я думаю, он означает "true".

Для этого вам сначала нужно отменить регистрацию вашего jQuery-скрипта, а затем зарегистрировать его снова. Если вы используете jQuery, поставляемый с WordPress, то вам подойдет следующая функция.
function starter_scripts() {
wp_deregister_script( 'jquery' );
wp_register_script( 'jquery', includes_url( '/js/jquery/jquery.js' ), false, NULL, true );
wp_enqueue_script( 'jquery' );
wp_enqueue_style( 'starter-style', get_stylesheet_uri() );
wp_enqueue_script( 'includes', get_template_directory_uri() . '/js/min/includes.min.js', '', '', true );
}
add_action( 'wp_enqueue_scripts', 'starter_scripts' );
Если вы используете версию jQuery, размещенную на Google CDN, дайте мне знать - я изменю этот код для URL Google CDN.

Я попробовал это, но скрипт всё ещё в подвале, есть идеи почему?

Что ты имеешь в виду? Решение как раз про перемещение jQuery в подвал.

Возможно, также стоит проверить is_admin(), чтобы избежать изменений в jQuery бэкенда - в конце концов, нам нужно оптимизировать только фронтенд наших сайтов :)

@TimMalone - на самом деле, нет - wp_enqueue_scripts
используется только для фронтенда, тогда как admin_enqueue_scripts
предназначен для бэкенда

Иногда это не работает, потому что плагин добавляет свой скрипт с параметром "in_footer" равным false. Это приводит к перемещению jquery-скрипта в head.

Я считаю, что это решение на самом деле ужасно. Удаляются ли теги версий этим способом? Что это за starter-style и что это за includes.min.js, и какое отношение это имеет к jQuery.

@redanimalwar starter-style и включаемые файлы взяты непосредственно из вопроса.

@Roberthue Я всё ещё ищу больше разработчиков, которые хотели бы помочь в поддержке open source проекта, см.: https://wordpress.org/plugins/jquery-manager/ и https://github.com/Remzi1993/jquery-manager этот плагин / проект должен помочь пользователям использовать последнюю версию jQuery простым кликом.

Лучшее решение:
add_action( 'wp_default_scripts', 'move_jquery_into_footer' );
function move_jquery_into_footer( $wp_scripts ) {
if( is_admin() ) {
return;
}
$wp_scripts->add_data( 'jquery', 'group', 1 );
$wp_scripts->add_data( 'jquery-core', 'group', 1 );
$wp_scripts->add_data( 'jquery-migrate', 'group', 1 );
}
Почему это решение лучше принятого ответа (по моему мнению)
- Изменения происходят на самом глубоком уровне, а не на позднем этапе, когда другие процессы могли уже повлиять на скрипты.
- Строка версии сохраняется и не удаляется!
- Вместо удаления и повторной регистрации скрипта просто устанавливается значение группы, что по сути эквивалентно регистрации скрипта с параметром
$footer = true
.
О том, почему не стоит делать это для админки
Если плагины добавляют inline jQuery в wp_head, это вызовет ошибку, когда jQuery не загружен в этот момент. Я рекомендую избегать этого, пока у вас не будут миллионы правок на сайте и вы не начнёте оптимизировать производительность админки. Это актуально и для фронтенда — следите за плохо написанными темами или плагинами, которые предполагают загрузку jQuery в head через inline-код. WP и плагины регистрируют другие скрипты в админке с jQuery в зависимостях, так что это всё равно не сработает.
Если решение не работает
Важно понимать: если любой другой скрипт загружается в head и зависит от jQuery, это приведёт к загрузке jQuery в head прямо перед ним. Это нормально и ожидаемо — так работает система wp_enqueue. Это означает, что при использовании нескольких плагинов вы быстро узнаете, если один из них потребует jQuery в head. К сожалению, это поведение по умолчанию для подключаемых скриптов.
Радикальное решение
Думаю, это сломает любой inline JS, который полагается на jQuery, но такое встречается редко. Этот код принудительно переместит все скрипты в футер, независимо от того, как они были подключены.
add_action( 'wp_enqueue_scripts', 'js_to_footer' );
function js_to_footer() {
remove_action( 'wp_head', 'wp_print_scripts' );
remove_action( 'wp_head', 'wp_print_head_scripts', 9 );
remove_action( 'wp_head', 'wp_enqueue_scripts', 1 );
}

Хотя этот ответ отвечает на вопрос и содержит несколько полезных моментов для размышления, в нём слишком много лишнего (воды?) и он очень похож на ранее опубликованные ответы с незначительными улучшениями кода. Ответ был бы воспринят лучше, если бы его отредактировали и сократили до более информативной версии. Также нет реальной необходимости указывать конкретных пользователей или ответы (так как они могут по каким-то причинам исчезнуть в будущем).

Вы называете совершенно не упомянутые и, вероятно, лучшие, чем что-либо указанное в других ответах, "незначительными улучшениями кода". Это просто неправда. Кроме того, я никого не "вызывал", я просто упомянул факты, которые знаю, чтобы улучшить стиль кодирования и обучить читателей, чтобы они писали лучший код. Серьёзно, я потратил немало времени, чтобы написать лучший на данный момент ответ, и вот что я получаю за это.

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

Этот код (как и код в ответе выше) возвращает мне ошибку 500. У меня WordPress 4.9.9

Сложно поверить, что этот код вызывает 500 ошибку, скорее всего вы допустили ошибку при реализации этого в своем коде. Это не совсем правильное место для такого вопроса, и ваша устаревшая версия WP — это слишком мало информации.

@NextGenThemes Я всё ещё ищу разработчиков, которые хотели бы помочь в поддержке open source проекта, см.: https://wordpress.org/plugins/jquery-manager/ и https://github.com/Remzi1993/jquery-manager этот плагин / проект должен помочь пользователям использовать последнюю версию jQuery простым кликом.

Я разработал плагин для решения этой конкретной проблемы. Этот плагин не вмешивается в jQuery WordPress, так как загружается только во фронтенде. Смотрите: jQuery Manager for WordPress
Зачем еще один инструмент для обновления / управления / разработки / отладки jQuery?
Потому что ни один из существующих инструментов не позволяет выбрать конкретную версию jQuery и/или jQuery Migrate, предоставляя как сжатую (production), так и несжатую (development) версии. Смотрите возможности ниже!
✅ Выполняется только во фронтенде, не влияет на админку WordPress и кастомайзер (для совместимости). Смотрите: https://core.trac.wordpress.org/ticket/45130 и https://core.trac.wordpress.org/ticket/37110
✅ Включает/выключает jQuery и/или jQuery Migrate
✅ Активирует конкретную версию jQuery и/или jQuery Migrate
И многое другое! Код открыт, так что вы можете изучать его, учиться и вносить свой вклад.
Почти все используют неверный хэндл
WordPress на самом деле использует хэндл jquery-core, а не jquery:
// jQuery $scripts->add( 'jquery', false, array( 'jquery-core', 'jquery-migrate' ), '1.12.4-wp' ); $scripts->add( 'jquery-core', '/wp-includes/js/jquery/jquery.js', array(), '1.12.4-wp' ); $scripts->add( 'jquery-migrate', "/wp-includes/js/jquery/jquery-migrate$suffix.js", array(), '1.4.1' );
Хэндл jquery — это просто алиас для загрузки jquery-core вместе с jquery-migrate
Подробнее об алиасах: wp_register_script multiple identifiers?
Правильный способ сделать это
В моем примере ниже я использую официальный CDN jQuery на https://code.jquery.com. Также я применяю script_loader_tag, чтобы добавить атрибуты CDN.
Вы можете использовать следующий код:
// Фронтенд — не выполняется в админке и кастомайзере WordPress (для совместимости)
// Смотрите: https://core.trac.wordpress.org/ticket/45130 и https://core.trac.wordpress.org/ticket/37110
function wp_jquery_manager_plugin_front_end_scripts() {
$wp_admin = is_admin();
$wp_customizer = is_customize_preview();
// jQuery
if ( $wp_admin || $wp_customizer ) {
// echo 'Мы в админке WordPress или в кастомайзере';
return;
}
else {
// Удаляем стандартный jQuery WordPress (см. https://github.com/Remzi1993/wp-jquery-manager/issues/2 и https://github.com/WordPress/WordPress/blob/91da29d9afaa664eb84e1261ebb916b18a362aa9/wp-includes/script-loader.php#L226)
wp_deregister_script( 'jquery' ); // хэндл jquery — это алиас для загрузки jquery-core и jquery-migrate
// Удаляем стандартный jQuery WordPress
wp_deregister_script( 'jquery-core' );
// Удаляем стандартный jQuery Migrate WordPress
wp_deregister_script( 'jquery-migrate' );
// Регистрируем jQuery в head
wp_register_script( 'jquery-core', 'https://code.jquery.com/jquery-3.3.1.min.js', array(), null, false );
/**
* Регистрируем jquery с зависимостью от jquery-core, чтобы другие скрипты могли использовать хэндл jquery
* см. https://wordpress.stackexchange.com/questions/283828/wp-register-script-multiple-identifiers
* Сначала регистрируем скрипт, а затем подключаем его. Почему? Смотрите:
* https://wordpress.stackexchange.com/questions/82490/when-should-i-use-wp-register-script-with-wp-enqueue-script-vs-just-wp-enque
* https://stackoverflow.com/questions/39653993/what-is-diffrence-between-wp-enqueue-script-and-wp-register-script
*/
wp_register_script( 'jquery', false, array( 'jquery-core' ), null, false );
wp_enqueue_script( 'jquery' );
}
}
add_action( 'wp_enqueue_scripts', 'wp_jquery_manager_plugin_front_end_scripts' );
function add_jquery_attributes( $tag, $handle ) {
if ( 'jquery-core' === $handle ) {
return str_replace( "type='text/javascript'", "type='text/javascript' integrity='sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=' crossorigin='anonymous'", $tag );
}
return $tag;
}
add_filter( 'script_loader_tag', 'add_jquery_attributes', 10, 2 );

Попробуйте изменить ваш код следующим образом:
function starter_scripts() {
wp_enqueue_style( 'starter-style', get_stylesheet_uri() );
wp_enqueue_script('jquery');
wp_enqueue_script( 'includes', get_template_directory_uri() . '/js/min/includes.min.js', array( 'jquery' ) );
}
add_action( 'wp_enqueue_scripts', 'starter_scripts' );
Думаю, это должно работать правильно
Добавьте эти строки в ваш файл functions.php
remove_action('wp_head', 'wp_enqueue_scripts', 1);
add_action('wp_footer', 'wp_enqueue_scripts', 5);
Это перенесет подключение скриптов в подвал сайта (footer)

Это помещает jQuery в head. Мне нужно, чтобы он был в подвале сайта (футере).

Привет, Деси, пожалуйста, проверь отредактированный ответ, думаю, он тебе поможет

Я почти уверен, что это ужасная идея — ты фактически предотвратил загрузку любых скриптов в заголовке, а не только jQuery, и, возможно, дублируешь их подключение (не вдавался в подробности). На самом деле, если уж делать таким способом, тебе, вероятно, нужна только часть с remove_action
/ add_action
.
