Skip to content

Все для WordPress, веб-розробки — і не тільки

🛠 Правильне підключення JavaScript у темах WordPress

🛠 Правильне підключення JavaScript у темах WordPress

Оновили WordPress, і галерея перестала працювати. Знайомо?

Майже завжди причина в тому, що JavaScript підключено напряму в header.php, без хуків, без залежностей, без урахування того, що плагін кешування може перетасувати порядок завантаження. Один плагін тягне jQuery, другий, свою версію jQuery, а ваш скрипт опиняється між ними й падає з $ is not defined.

На практиці вистачає одного виклику wp_enqueue_script у потрібному місці, щоб забути про конфлікти назавжди. Нижче, повний розбір: від помилок новачків до стратегій defer/async і тонких налаштувань, які з’явилися у WordPress 6.6.

💡 Швидкий огляд:

  • Не вставляйте тег script напряму в header.php або footer.php: це створює конфлікти з плагінами й ламає дочірні теми
  • Підключайте JavaScript через wp_enqueue_script у functions.php із хуком wp_enqueue_scripts: WordPress сам розставить теги в head або перед /body
  • Для коротких вставок використовуйте wp_add_inline_script, а не голий script-тег: зберігає порядок виконання й дає плагінам шанс перехопити код
  • На WordPress 6.3+ вказуйте стратегію defer або async прямо в параметрах виклику, а з 6.6, ще й fetchpriority
  • Вивантажуйте чужі скрипти через wp_dequeue_script, якщо плагін гальмує сайт: пріоритет хука вирішує

Як неправильно додають JavaScript у WordPress

Типовий сценарій: потрібно підключити свій custom.js, і розробник вставляє в header.php рядок:

1<script src="<?php echo get_template_directory_uri(); ?>/js/custom.js"></script>

На перший погляд працює. Але такий підхід створює три проблеми.

Конфлікти з плагінами. Плагін кешування об’єднує скрипти в іншому порядку, плагін мініфікації перейменовує файл і ламає шлях. Якщо інший плагін уже завантажив jQuery, а ви завантажуєте його повторно, подвійне завантаження й помилки в консолі.

Не можна перевизначити через дочірню тему. Коли використовується дочірня тема, header.php копіюють рідко. Якщо скрипт вшито в батьківський header.php, дочірня тема не може його вивантажити або замінити без повного копіювання файлу, а це означає, що під час оновлення батьківської теми правки загубляться.

Немає залежностей. Браузер завантажує ваш скрипт до jQuery й отримує $ is not defined. Скрипт завантажується на всіх сторінках, навіть там, де він не потрібен, і зайві запити сповільнюють сайт.

Правильний спосіб: wp_enqueue_script

WordPress надає систему черг для скриптів і стилів. Ви не вставляєте <script> вручну, а реєструєте скрипт через PHP, вказуєте залежності й місце завантаження. WordPress сам розставляє теги в <head> або перед </body>.

Мінімальний робочий приклад для functions.php вашої теми:

1/**
2 * Подключаем основной скрипт темы.
3 */
4function mytheme_enqueue_scripts() {
5 wp_enqueue_script(
6 'mytheme-main', // $handle — уникальное имя
7 get_template_directory_uri() . '/js/main.js', // $src — путь к файлу
8 array( 'jquery' ), // $deps — зависимости
9 '1.0.0', // $ver — версия для сброса кеша
10 true // $in_footer — грузить в подвале
11 );
12}
13add_action( 'wp_enqueue_scripts', 'mytheme_enqueue_scripts' );

Функція wp_enqueue_script приймає п’ять параметрів. $handle, унікальний ідентифікатор: якщо інший плагін уже зареєстрував скрипт із таким самим handle, повторного завантаження не буде. $deps, масив handle-залежностей: WordPress сам підвантажить потрібні скрипти перед вашим. $in_footer зі значенням true розміщує тег <script> перед </body>, це пришвидшує відтворення сторінки.

Зверніть увагу: get_template_directory_uri() вказує на папку батьківської теми. У дочірній темі використовуйте get_stylesheet_directory_uri(), URL вестиме в папку дочірньої, і ваш скрипт не загубиться під час оновлення батьківської теми.

Стратегії завантаження: defer, async і fetchpriority

З WordPress 6.3 параметр $args приймає масив із додатковими налаштуваннями:

1wp_enqueue_script(
2 'mytheme-main',
3 get_template_directory_uri() . '/js/main.js',
4 array( 'jquery' ),
5 '1.0.0',
6 array(
7 'in_footer' => true,
8 'strategy' => 'defer',
9 )
10);

Стратегія defer каже браузеру: «завантажуй скрипт паралельно, виконуй після побудови DOM». Порядок виконання гарантовано, скрипти з defer виконуються в тому порядку, в якому додані в DOM. Стратегія async, «виконуй щойно завантажився», порядок не гарантовано. Для скриптів теми, залежних від DOM, обирайте defer.

З WordPress 6.6 у масиві $args з’явилися ще два параметри. fetchpriority керує пріоритетом завантаження ('high' або 'low'), знадобиться для критичних скриптів, які мають завантажитися раніше за інші. module_dependencies приймає масив ID модулів для динамічного імпорту — це вже для просунутих сценаріїв з ES-модулями. Важливо: коли вказуєте module_dependencies, скрипт зобов’язаний завантажуватися в підвалі (in_footer => true) або зі стратегією defer, інакше карта імпорту модулів не буде готова на момент виконання скрипта.

Які скрипти вже є у WordPress

WordPress «з коробки» реєструє десятки JavaScript-бібліотек: jQuery, jQuery UI, Backbone, wp-api, MediaElement.js та інші. Повний список, в офіційній документації.

Головне правило: ніколи не підключайте jQuery з CDN на кшталт Google або cdnjs, якщо тема працює в екосистемі WordPress. WordPress сам надає jQuery із handle jquery. Щоб використати його, просто вкажіть array( 'jquery' ) у залежностях, WordPress завантажить свою версію, протестовану на сумісність з усім ядром.

Перевірити, чи зареєстрована бібліотека, можна через wp_script_is():

1if ( wp_script_is( 'jquery-ui-datepicker', 'registered' ) ) {
2 // Библиотека доступна — просто добавьте в $deps
3}

Використання хука wp_enqueue_scripts

Хук wp_enqueue_scripts спрацьовує на фронтенді. Саме в нього обгортають виклики wp_enqueue_script. Не викликайте функцію напряму в тілі functions.php без хука, скрипт може підключитися до того, як WordPress зареєструє системні бібліотеки.

Для адмінки використовуйте окремий хук:

1add_action( 'admin_enqueue_scripts', 'mytheme_admin_scripts' );
2function mytheme_admin_scripts( $hook_suffix ) {
3 // $hook_suffix содержит текущую страницу админки
4 if ( 'post.php' !== $hook_suffix ) {
5 return; // грузим скрипт только на странице редактирования записи
6 }
7 wp_enqueue_script( 'mytheme-admin', get_template_directory_uri() . '/js/admin.js', array(), '1.0', true );
8}

Умовне завантаження економить ресурси: скрипт для сторінки опцій не повинен завантажуватися на всіх сторінках адмінки. Параметр $hook_suffix передається WordPress автоматично, використовуйте його.

Якщо скрипт потрібен і на фронті, і в адмінці, повісьте одну функцію на обидва хуки:

1add_action( 'wp_enqueue_scripts', 'mytheme_global_scripts' );
2add_action( 'admin_enqueue_scripts', 'mytheme_global_scripts' );

Додавання вбудованого JavaScript: wp_add_inline_script

Не завжди код варто виносити в окремий файл. Для коротких вставок, лічильників, змінних конфігурації, швидких обробників WordPress надає wp_add_inline_script:

1function mytheme_inline_config() {
2 wp_enqueue_script( 'mytheme-main', get_template_directory_uri() . '/js/main.js', array(), '1.0', true );
3 wp_add_inline_script(
4 'mytheme-main',
5 'const MYTHEME_AJAX_URL = "' . admin_url( 'admin-ajax.php' ) . '";',
6 'before'
7 );
8}
9add_action( 'wp_enqueue_scripts', 'mytheme_inline_config' );

Третій параметр, 'before' або 'after', визначає, куди вставиться код відносно вказаного скрипта. Це зручно для прокидання PHP-змінних у JavaScript: URL AJAX-обробника, nonce-ключ безпеки, ID поточного запису.

Важливий нюанс: wp_add_inline_script працює лише із зареєстрованим скриптом. Якщо передати handle, якого немає в черзі, код не виведеться. Тому спочатку wp_enqueue_script, потім wp_add_inline_script.

Альтернатива для дочірніх тем: wp_head і wp_footer

Якщо ви працюєте в дочірній темі й не хочете створювати окремий файл, можна вивести код напряму через хуки wp_head<head>) або wp_footer (перед </body>):

1add_action( 'wp_footer', function() { ?>
2 <script>
3 ( function( $ ) {
4 'use strict';
5 $( function() {
6 // Ваш код здесь — DOM уже готов
7 } );
8 } ( jQuery ) );
9 </script>
10<?php } );

Спосіб коротший, але поступається wp_enqueue_script у гнучкості: немає залежностей, версіонування й можливості вивантажити скрипт через дочірню тему. Використовуйте його для дрібних правок, коли не хочете створювати окремий файл.

Як вивантажити скрипт, доданий плагіном або темою

Буває, що плагін підключає непотрібний скрипт на всіх сторінках і гальмує сайт. Прибрати його можна через wp_dequeue_script:

1function mytheme_dequeue_plugin_scripts() {
2 if ( ! is_page( 'contacts' ) ) {
3 wp_dequeue_script( 'plugin-handle' );
4 }
5}
6add_action( 'wp_enqueue_scripts', 'mytheme_dequeue_plugin_scripts', 20 );

Пріоритет 20 (третій аргумент add_action) ставить вашу функцію пізніше за реєстрацію плагіна, інакше handle ще не буде в черзі. Дізнатися handle конкретного скрипта можна через консоль браузера: відкрийте вихідний код сторінки й знайдіть атрибут id у тега <script>, handle зазвичай збігається з id без суфікса -js.

Якщо потрібно повністю замінити скрипт, спочатку зніміть старий через wp_deregister_script, потім зареєструйте новий:

1function mytheme_replace_script() {
2 wp_deregister_script( 'old-handle' );
3 wp_enqueue_script( 'old-handle', get_template_directory_uri() . '/js/replacement.js', array(), '2.0', true );
4}
5add_action( 'wp_enqueue_scripts', 'mytheme_replace_script', 20 );

Перед такими операціями зробіть повний бекап сайту. Заміна скриптів плагінів, прямий шлях до поломки функціоналу, якщо не протестувати на staging-оточенні.

На відео вище, покроковий розбір підключення CSS і JavaScript у темі WordPress через wp_enqueue_script і wp_enqueue_style. Якщо ви новачок у темі хуків, почніть із нього, а потім повертайтеся до текстового посібника за деталями.

⁉️🤔 Часті питання

Чи обов’язково використовувати wp_enqueue_script для кожного js-файлу?

На практиці, так, для всіх скриптів, які підключаються глобально. Для скрипта, що працює на одній-єдиній сторінці й генерується динамічно, допустимо вставити <script> прямо в шаблон. Але щойно скриптів стає два й більше, черга через wp_enqueue_script економить години налагодження.

Чим wp_register_script відрізняється від wp_enqueue_script?

wp_register_script лише реєструє скрипт у системі (задає handle, шлях, залежності), але не виводить тег на сторінку. wp_enqueue_script реєструє І одразу ставить у чергу на виведення. Розділення корисне, коли скрипт потрібен не завжди: реєструєте один раз у functions.php, а викликаєте wp_enqueue_script('my-handle') лише на потрібних сторінках.

Чи можна завантажувати скрипти із зовнішнього CDN?

Технічно, так, передайте повний URL другим параметром. Але для jQuery та інших бібліотек із ядра WordPress це погана практика: WordPress уже містить їх і тестує сумісність. Зовнішній CDN виправданий для сторонніх сервісів, Google Analytics, reCAPTCHA, віджети чатів. Там URL вказуйте як є.

Як перевірити, що скрипт справді завантажився?

Відкрийте інструменти розробника (F12), вкладка Network, відфільтруйте за JS й оновіть сторінку. Ваш файл має бути в списку з кодом 200. Якщо скрипта немає, перевірте, чи спрацьовує хук wp_enqueue_scripts на цій сторінці та чи коректний шлях до файлу. Для налагодження виведіть get_template_directory_uri() окремо й звірте URL.

Що робити, якщо після оновлення теми скрипти перестали працювати?

Найімовірніше, оновлення затерло ваш functions.php. Рішення, дочірня тема: створіть її, перенесіть туди свої функції й активуйте. Після цього оновлення батьківської теми ваш код залишиться на місці.

Що означає помилка «$ is not defined» під час використання jQuery?

WordPress завантажує jQuery у режимі noConflict, змінна $ не зайнята jQuery, щоб уникнути конфліктів з іншими бібліотеками. Використовуйте повне ім’я jQuery замість $ або обгорніть код у самовикличну функцію: (function($) { ... })(jQuery);.

Чи варто морочитися з wp_enqueue_script для пари скриптів?

Якщо на сайті більше одного плагіна, варто. Черга скриптів у WordPress влаштована так, що один плагін, який підключив jQuery напряму, ламає пів сайту при першому ж встановленні плагіна кешування. wp_enqueue_script прибирає цей клас проблем повністю.

Для теми з п’яти файлів, беріть wp_enqueue_script. Для однієї короткої вставки на конкретну сторінку, згодиться wp_add_inline_script або хук wp_footer. Але щойно скриптів стає два й більше, повертайтеся до черги. Година, витрачена на правильне підключення зараз, економить вечір налагодження після чергового оновлення WordPress.