Skip to content

Wszystko o WordPressie, tworzeniu stron — i nie tylko

🛠 Prawidłowe podłączanie JavaScript w motywach WordPress

🛠 Prawidłowe podłączanie JavaScript w motywach WordPress

Zaktualizowali Państwo WordPress i galeria przestała działać. Brzmi znajomo?

Niemal zawsze przyczyną jest to, że JavaScript jest podłączony bezpośrednio w header.php, bez haków, bez zależności, bez uwzględnienia, że wtyczka cache’ująca może przetasować kolejność ładowania. Jedna wtyczka wczytuje jQuery, druga swoją wersję jQuery, a Państwa skrypt ląduje między nimi i pada z błędem $ is not defined.

W praktyce wystarczy jedno wywołanie wp_enqueue_script w odpowiednim miejscu, aby raz na zawsze zapomnieć o konfliktach. Poniżej pełna analiza: od błędów początkujących po strategie defer/async i subtelne ustawienia, które pojawiły się w WordPress 6.6.

💡 Szybki przegląd:

  • Nie wstawiajcie Państwo znacznika script bezpośrednio w header.php ani footer.php: tworzy to konflikty z wtyczkami i psuje motywy potomne
  • Podłączajcie Państwo JavaScript przez wp_enqueue_script w functions.php z hakiem wp_enqueue_scripts: WordPress sam rozmieści znaczniki w head lub przed /body
  • Do krótkich wstawek używajcie Państwo wp_add_inline_script, a nie gołego znacznika script: zachowuje kolejność wykonania i daje wtyczkom szansę przechwycenia kodu
  • Na WordPress 6.3+ podawajcie Państwo strategię defer lub async bezpośrednio w parametrach wywołania, a od 6.6 także fetchpriority
  • Wyładowujcie Państwo cudze skrypty przez wp_dequeue_script, jeśli wtyczka spowalnia stronę: priorytet haka decyduje

Jak nieprawidłowo dodaje się JavaScript w WordPress

Typowy scenariusz: trzeba podłączyć swój custom.js i programista wstawia w header.php linię:

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

Na pierwszy rzut oka działa. Ale takie podejście stwarza trzy problemy.

Konflikty z wtyczkami. Wtyczka cache’ująca łączy skrypty w innej kolejności, wtyczka minifikacji zmienia nazwę pliku i psuje ścieżkę. Jeśli inna wtyczka już załadowała jQuery, a Państwo ładujecie je ponownie, skutkuje to podwójnym ładowaniem i błędami w konsoli.

Nie można nadpisać przez motyw potomny. Gdy używany jest motyw potomny, header.php kopiuje się rzadko. Jeśli skrypt jest wszyty w nadrzędny header.php, motyw potomny nie może go wyładować ani zastąpić bez pełnego kopiowania pliku, a to oznacza, że podczas aktualizacji motywu nadrzędnego poprawki przepadną.

Brak zależności. Przeglądarka ładuje Państwa skrypt przed jQuery i otrzymuje $ is not defined. Skrypt ładuje się na wszystkich stronach, nawet tam, gdzie nie jest potrzebny, a zbędne zapytania spowalniają witrynę.

Prawidłowy sposób: wp_enqueue_script

WordPress udostępnia system kolejek dla skryptów i stylów. Nie wstawia się <script> ręcznie, tylko rejestruje skrypt przez PHP, podaje zależności i miejsce ładowania. WordPress sam rozmieszcza znaczniki w <head> lub przed </body>.

Minimalny działający przykład dla functions.php Państwa motywu:

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' );

Funkcja wp_enqueue_script przyjmuje pięć parametrów. $handle, unikalny identyfikator: jeśli inna wtyczka już zarejestrowała skrypt z takim samym handle, nie dojdzie do ponownego ładowania. $deps, tablica handle-zależności: WordPress sam doładuje potrzebne skrypty przed Państwa skryptem. $in_footer z wartością true umieszcza znacznik <script> przed </body>, co przyspiesza renderowanie strony.

Proszę zwrócić uwagę: get_template_directory_uri() wskazuje na folder motywu nadrzędnego. W motywie potomnym należy użyć get_stylesheet_directory_uri(), URL poprowadzi do folderu motywu potomnego i Państwa skrypt nie zginie podczas aktualizacji motywu nadrzędnego.

Strategie ładowania: defer, async i fetchpriority

Od WordPress 6.3 parametr $args przyjmuje tablicę z dodatkowymi ustawieniami:

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);

Strategia defer mówi przeglądarce: „ładuj skrypt równolegle, wykonaj po zbudowaniu DOM". Kolejność wykonania jest gwarantowana, skrypty z defer wykonują się w kolejności dodania do DOM. Strategia async, „wykonaj, gdy tylko się załaduje", nie gwarantuje kolejności. Dla skryptów motywu zależnych od DOM należy wybierać defer.

Od WordPress 6.6 w tablicy $args pojawiły się dwa kolejne parametry. fetchpriority steruje priorytetem ładowania ('high' lub 'low'), przyda się dla krytycznych skryptów, które muszą załadować się przed innymi. module_dependencies przyjmuje tablicę ID modułów dla dynamicznego importu, to już dla zaawansowanych scenariuszy z modułami ES. Ważne: gdy podają Państwo module_dependencies, skrypt musi ładować się w stopce (in_footer => true) lub ze strategią defer, w przeciwnym razie mapa importu modułów nie będzie gotowa w momencie wykonania skryptu.

Jakie skrypty są już w WordPress

WordPress „od razu po instalacji" rejestruje dziesiątki bibliotek JavaScript: jQuery, jQuery UI, Backbone, wp-api, MediaElement.js i inne. Pełna lista w oficjalnej dokumentacji.

Główna zasada: nigdy nie podłączajcie Państwo jQuery z CDN pokroju Google ani cdnjs, jeśli motyw działa w ekosystemie WordPress. WordPress sam dostarcza jQuery z handle jquery. Aby go użyć, wystarczy podać array( 'jquery' ) w zależnościach, WordPress załaduje swoją wersję, przetestowaną pod kątem zgodności z całym rdzeniem.

Sprawdzić, czy biblioteka jest zarejestrowana, można przez wp_script_is():

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

Użycie haka wp_enqueue_scripts

Hak wp_enqueue_scripts odpala się na frontendzie. To w niego opakowuje się wywołania wp_enqueue_script. Nie wywołujcie Państwo funkcji bezpośrednio w ciele functions.php bez haka, skrypt może podłączyć się, zanim WordPress zarejestruje biblioteki systemowe.

Dla panelu administracyjnego należy użyć osobnego haka:

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}

Warunkowe ładowanie oszczędza zasoby: skrypt dla strony opcji nie powinien ładować się na wszystkich stronach panelu. Parametr $hook_suffix jest przekazywany przez WordPress automatycznie, proszę go używać.

Jeśli skrypt jest potrzebny i na froncie, i w panelu, proszę podpiąć jedną funkcję pod oba haki:

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

Dodawanie osadzonego JavaScript: wp_add_inline_script

Nie zawsze kod warto wynosić do osobnego pliku. Dla krótkich wstawek, liczników, zmiennych konfiguracyjnych, szybkich handlerów WordPress udostępnia 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' );

Trzeci parametr, 'before' lub 'after', określa, gdzie wstawi się kod względem wskazanego skryptu. Jest to wygodne do przekazywania zmiennych PHP do JavaScript: URL handlera AJAX, klucz bezpieczeństwa nonce, ID bieżącego wpisu.

Ważny niuans: wp_add_inline_script działa tylko z zarejestrowanym skryptem. Jeśli przekażą Państwo handle, którego nie ma w kolejce, kod się nie wyświetli. Dlatego najpierw wp_enqueue_script, potem wp_add_inline_script.

Alternatywa dla motywów potomnych: wp_head i wp_footer

Jeśli pracują Państwo w motywie potomnym i nie chcą tworzyć osobnego pliku, można wyprowadzić kod bezpośrednio przez haki wp_head (w <head>) lub wp_footer (przed </body>):

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

Sposób jest krótszy, ale ustępuje wp_enqueue_script pod względem elastyczności: nie ma zależności, wersjonowania ani możliwości wyładowania skryptu przez motyw potomny. Proszę go używać do drobnych poprawek, gdy nie chcą Państwo tworzyć osobnego pliku.

Jak wyładować skrypt dodany przez wtyczkę lub motyw

Zdarza się, że wtyczka podłącza niepotrzebny skrypt na wszystkich stronach i spowalnia witrynę. Usunąć go można przez 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 );

Priorytet 20 (trzeci argument add_action) stawia Państwa funkcję później niż rejestracja wtyczki, w przeciwnym razie handle nie będzie jeszcze w kolejce. Poznać handle konkretnego skryptu można przez konsolę przeglądarki: proszę otworzyć kod źródłowy strony i znaleźć atrybut id w znacznikach <script>, handle zazwyczaj pokrywa się z id bez sufiksu -js.

Jeśli trzeba całkowicie zastąpić skrypt, najpierw proszę zdjąć stary przez wp_deregister_script, a następnie zarejestrować nowy:

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 );

Przed takimi operacjami proszę zrobić pełny backup witryny. Zastępowanie skryptów wtyczek to prosta droga do zepsucia funkcjonalności, jeśli nie przetestuje się tego na środowisku stagingowym.

Na filmie powyżej, krok po kroku omówione jest podłączanie CSS i JavaScript w motywie WordPress przez wp_enqueue_script i wp_enqueue_style. Jeśli są Państwo początkujący w temacie haków, proszę zacząć od niego, a potem wrócić do tekstowego poradnika po szczegóły.

⁉️🤔 Częste pytania

Czy trzeba koniecznie używać wp_enqueue_script dla każdego pliku js?

W praktyce tak, dla wszystkich skryptów podłączanych globalnie. Dla skryptu, który działa na jednej jedynej stronie i jest generowany dynamicznie, dopuszczalne jest wstawienie <script> bezpośrednio w szablonie. Ale gdy tylko skryptów robi się dwa lub więcej, kolejka przez wp_enqueue_script oszczędza godziny debugowania.

Czym wp_register_script różni się od wp_enqueue_script?

wp_register_script jedynie rejestruje skrypt w systemie (ustala handle, ścieżkę, zależności), ale nie wyprowadza znacznika na stronę. wp_enqueue_script rejestruje I od razu stawia w kolejce do wyprowadzenia. Rozdzielenie jest przydatne, gdy skrypt nie zawsze jest potrzebny: rejestruje się raz w functions.php, a wywołuje wp_enqueue_script('my-handle') tylko na potrzebnych stronach.

Czy można ładować skrypty z zewnętrznego CDN?

Technicznie tak, proszę przekazać pełny URL jako drugi parametr. Ale dla jQuery i innych bibliotek z rdzenia WordPress to zła praktyka: WordPress już je zawiera i testuje zgodność. Zewnętrzny CDN jest uzasadniony dla usług zewnętrznych, Google Analytics, reCAPTCHA, widżetów czatu. Tam proszę podawać URL jak jest.

Jak sprawdzić, czy skrypt naprawdę się załadował?

Proszę otworzyć narzędzia deweloperskie (F12), zakładkę Network, odfiltrować po JS i odświeżyć stronę. Państwa plik powinien być na liście z kodem 200. Jeśli skryptu nie ma, proszę sprawdzić, czy hak wp_enqueue_scripts odpala się na tej stronie i czy ścieżka do pliku jest poprawna. Do debugowania proszę wyprowadzić get_template_directory_uri() osobno i zweryfikować URL.

Co robić, jeśli po aktualizacji motywu skrypty przestały działać?

Najprawdopodobniej aktualizacja nadpisała Państwa functions.php. Rozwiązanie to motyw potomny: proszę go utworzyć, przenieść tam swoje funkcje i aktywować. Po tym aktualizacje motywu nadrzędnego pozostawią Państwa kod na miejscu.

Co oznacza błąd „$ is not defined" przy użyciu jQuery?

WordPress ładuje jQuery w trybie noConflict, zmienna $ nie jest zajęta przez jQuery, aby uniknąć konfliktów z innymi bibliotekami. Proszę używać pełnej nazwy jQuery zamiast $ lub opakować kod w samowywołującą się funkcję: (function($) { ... })(jQuery);.

Czy warto zawracać sobie głowę wp_enqueue_script dla pary skryptów?

Jeśli na stronie jest więcej niż jedna wtyczka, warto. Kolejka skryptów w WordPress jest tak skonstruowana, że jedna wtyczka, która podłączyła jQuery bezpośrednio, psuje pół witryny przy pierwszej instalacji wtyczki cache’ującej. wp_enqueue_script całkowicie eliminuje tę klasę problemów.

Dla motywu z pięciu plików proszę brać wp_enqueue_script. Dla jednej krótkiej wstawki na konkretną stronę nada się wp_add_inline_script lub hak wp_footer. Ale gdy tylko skryptów robi się dwa lub więcej, proszę wracać do kolejki. Godzina poświęcona na prawidłowe podłączenie teraz oszczędza wieczór debugowania po kolejnej aktualizacji WordPress.