Otwarte na nowe projekty +48 887 255 528 · kontakt[at]kosari.pl

28 mu-pluginów na jednej stronie – jak zrobiliśmy jedną wtyczkę

Customowy kod w mu-plugins WordPress urósł do 28 plików? Jak złożyliśmy go w jedną wtyczkę z modułami, wdrożyliśmy bez przerwy i sprawdziliśmy efekt.

9 min czytania WordPress
28 mu-pluginów na jednej stronie - jak zrobiliśmy jedną wtyczkę

Wchodzimy na serwer klientki, żeby zaktualizować jedną wtyczkę. Zaglądamy do katalogu wp-content/mu-plugins/ i widzimy dwadzieścia osiem plików PHP. Każdy dopisany kiedyś w reakcji na konkretną prośbę: licznik w koszyku, kupon z linku, pasek postępu przewijania, poprawka w formularzu, drobiazg w regulaminie.

Żadnego z nich nie da się wyłączyć z panelu WordPressa. Żaden nie ma wersji. Żaden nie mówi, po co powstał. To typowy los, jaki spotyka customowy kod w mu-plugins WordPress: na początku to najszybsza droga, po kilku latach – katalog, którego nikt już nie rozumie. W tym wpisie pokazujemy, jak zamieniliśmy go w jedną wtyczkę z modułami i panelem, i jak sprawdziliśmy, że po drodze nic nie wypadło.

Strona po latach dopisywania

Klientka prowadzi sklep na WooCommerce z subskrypcjami i platformę kursową. Strona rozwijała się po kawałku: każda prośba o drobną zmianę kończyła się nowym plikiem w mu-plugins, bo tak było najszybciej. Nikt nie popełnił tu błędu w jednym konkretnym momencie. Problem narastał po cichu.

Stawka nie była abstrakcyjna. Sklep sprzedaje codziennie, a każda diagnoza „dlaczego koszyk zachowuje się dziwnie” zaczynała się od zgadywania, który z dwudziestu ośmiu plików może za to odpowiadać.

Dlaczego mu-plugins to wygodna pułapka

mu-plugins, czyli must-use plugins, to katalog, z którego WordPress ładuje każdy plik PHP automatycznie, przed zwykłymi wtyczkami. Nie trzeba nic aktywować, nie da się tego przypadkiem wyłączyć, kod działa od razu. Dla programisty to najkrótsza droga do celu i właśnie dlatego tak łatwo się tam osiedlić na stałe.

Cena pojawia się później:

  • Zero kontroli z panelu. Klientka nie może niczego wyłączyć samodzielnie, nawet na próbę.
  • Zero wersjonowania. Nie wiadomo, co jest aktualne, a co jest osadem sprzed dwóch lat.
  • Diagnoza przez zgadywanie. Standardowy test „wyłącz wtyczki po kolei” w ogóle nie obejmuje tego katalogu.
  • Duplikaty. Dwa pliki robiły to samo – dodawały kupon do koszyka z linku – tylko na dwóch różnych parametrach w adresie.
  • Sieroty. Znaleźliśmy plik HTML z treścią maila, którego nie czytał już żaden kod. Leżał i czekał.
  • Kod po nieaktywnych wtyczkach. Kilka plików poprawiało zachowanie kreatora stron i wtyczki formularzy, których na stronie od dawna nie było włączonych.

Drugie znalezisko: wtyczka-fork z poprawką, której nie ma w repozytorium

Przy okazji trafiliśmy na problem tej samej rodziny. Wtyczka narzędziowa na stronie klientki różniła się od oficjalnego wydania w tej samej wersji. Ktoś kiedyś dopisał w niej lokalną poprawkę bezpieczeństwa: escapowanie etykiet w podglądzie zgłoszeń z formularza. Poprawki nie było w repozytorium.

To najgroźniejszy scenariusz w utrzymaniu stron: aktualizacja, która cofa poprawkę. Nie wywala błędu, nie psuje wyglądu, nie ma jej w żadnym logu. Po prostu wraca stare zachowanie – w tym przypadku luka, którą ktoś kiedyś załatał – a nikt nie wie dlaczego.

Najbliższa zwykła aktualizacja przez nadpisanie plików skasowałaby tę poprawkę bez śladu. Dlatego zanim cokolwiek przenieśliśmy, poprawkę wydaliśmy oficjalnie w nowej wersji wtyczki. Od tej pory aktualizacja jej nie cofa, bo po prostu jest w kodzie źródłowym.

Co zrobiliśmy: jedna wtyczka z modułami zamiast 28 plików

Zamiast czyścić katalog po kawałku, złożyliśmy cały customowy kod strony w jedną dedykowaną wtyczkę. Struktura jest banalna i o to chodzi:

kwt-custom-klient/
  kwt-custom-klient.php   # loader + panel w wp-admin
  modules/
    sklep-kupon-z-linku.php
    koszyk-licznik.php
    scroll-progress.php
    ...

Każdy dawny mu-plugin stał się modułem: osobnym plikiem, który loader włącza albo pomija na podstawie jednej opcji w bazie. W wp-admin pojawił się prosty panel z listą checkboxów – jeden moduł, jedna linijka opisu, jeden przełącznik.

Przed i po konsolidacji customowego koduPRZED - mu-plugins28 plików bez nazwy i wersjiduplikat, sierota, kod martwych wtyczekwyłączenie = sesja na serwerzePO - jedna wtyczkaPanel w wp-admin: 25 modułówsklep - kupon z linkukoszyk - licznikpasek postępu przewijania... i kolejne moduływersja, repozytorium, opiswyłączenie = jeden checkbox
Ten sam kod, ale zamiast zgadywania przy awarii jest lista nazwanych modułów, z których każdy wyłącza się jednym kliknięciem.

Trzy zasady, których trzymaliśmy się przy przenoszeniu:

  1. Kod przenosimy jeden do jednego. Zero „przy okazji poprawię”. Refaktor i przeprowadzka nigdy w jednym kroku, bo potem nie wiadomo, co zepsuło stronę.
  2. Duplikaty scalamy dopiero po przeniesieniu, jako osobną, testowaną zmianę. Dwa mechanizmy kuponu z linku zostały jednym modułem obsługującym oba parametry.
  3. W mu-plugins zostaje tylko to, co musi przeżyć awarię wtyczek – u nas strażnik, który ponownie włącza wtyczkę narzędziową, gdyby ta została wyłączona, i kilka plików wymaganych przez hosting. Reszta wyprowadzona.

Kod nowej wtyczki trafił do prywatnego repozytorium z oznaczonymi wersjami. Świadomie nie wrzuciliśmy go do kanału aktualizacji, z którego korzystają inne strony: kod jednej konkretnej strony nie ma czego szukać w dystrybucji dla wszystkich.

Wdrożenie bez migającej strony

Podmiana katalogu wtyczki na żywym sklepie to moment, w którym strona może przez chwilę nie mieć kodu. Robimy to atomowym przeniesieniem, nie kopiowaniem po pliku:

# nowa wersja wgrana obok, potem podmiana jednym ruchem
mv wp-content/plugins/kwt-custom-klient wp-content/plugins/kwt-custom-klient.old
mv /tmp/kwt-custom-klient wp-content/plugins/kwt-custom-klient

Przed czymkolwiek: pełna kopia katalogu mu-plugins na serwerze i lokalnie. W kopii wylądowało 31 pozycji. Backup ma ustalony termin skasowania zapisany w zadaniu – inaczej zostaje na serwerze na zawsze i za rok nikt nie wie, czy jest jeszcze potrzebny.

Weryfikacja: skąd wiadomo, że nic nie wypadło

To jest część, którą najłatwiej pominąć i najdrożej się za to płaci. Brak białego ekranu nie jest dowodem, że wszystkie funkcje dalej działają. Kod może się załadować i po cichu nic nie robić.

Pięć warstw sprawdzenia po przeniesieniu koduHTTP 2004 kluczowe adresyZnacznikiw HTML odpowiedziHooki13 kluczowychPanelzapis i wyłączenieScenariusze5 testów kuponuDopiero komplet = zmiana weszła
Każda warstwa łapie inny rodzaj błędu. Sam kod 200 przepuściłby moduł, który się załadował, ale niczego nie robi.
  1. Kluczowe podstrony zwracają 200 bez błędu krytycznego: strona główna, sklep, koszyk, moje konto.
  2. Znaczniki modułów są w HTML. Jeśli moduł dodaje klasę, atrybut albo element, sprawdzamy jego obecność w odpowiedzi serwera, a nie w kodzie źródłowym wtyczki.
  3. Hooki są zarejestrowane. Przeglądamy globalną tablicę filtrów WordPressa i potwierdzamy, że przeniesione moduły faktycznie wpięły swoje akcje – u nas 13 kluczowych hooków.
  4. Panel działa w obie strony – checkbox się zapisuje i realnie wyłącza funkcję.
  5. Scalony duplikat testujemy na scenariuszach. Kupon z linku przeszedł pięć scenariuszy na żywym sklepie, a testowy kupon skasowaliśmy po teście.

Przykład sprawdzenia hooka z poziomu WP-CLI, gdy wiesz, na jaką akcję moduł się wpina:

wp eval 'global $wp_filter; echo isset($wp_filter["woocommerce_before_cart"]) ? "jest" : "BRAK";'

Dopiero komplet tych punktów pozwala powiedzieć klientce, że zmiana weszła. Jeśli zlecasz komuś opiekę nad stroną WordPress, to jest dokładnie ten poziom weryfikacji, którego masz prawo oczekiwać po każdej większej zmianie.

Efekt

Zamiast dwudziestu ośmiu anonimowych plików jest jedna wtyczka z 25 nazwanymi modułami i panelem, w którym widać, co strona ma dodatkowo włączone. Moduły obsługujące nieaktywne wtyczki usunęliśmy, duplikat kuponu scaliliśmy w jeden moduł, a sierotę bez kodu przenieśliśmy do backupu. Z opcji wtyczki wyczyściliśmy też wpisy po usuniętych modułach.

Najważniejsza zmiana nie jest jednak techniczna. Diagnostyka przestała być zgadywanką. Gdy coś zacznie się dziwnie zachowywać, wyłącza się moduł checkboxem i w kilkanaście sekund wiadomo, czy to on. Wcześniej oznaczało to sesję na serwerze i przenoszenie plików po jednym.

Sprawdziło się to szybciej, niż się spodziewaliśmy. Kilka dni później w lekcjach kursu przestały wyświetlać się filmy. Winowajcą okazał się jeden z naszych modułów wydajności, który dodawał atrybut defer do wszystkich skryptów i rozjeżdżał start odtwarzacza lekcji. Poprawka dotyczyła jednego nazwanego pliku z wersją, a nie poszukiwań w katalogu pełnym anonimowych dopisków.

Sprawdź to u siebie w trzy minuty

  1. Zajrzyj do wp-content/mu-plugins/. Ile jest plików i czy potrafisz powiedzieć, co robi każdy?
  2. Czy któryś nie ma nagłówka z nazwą i opisem? Taki plik jest niewidzialny w każdym raporcie.
  3. Czy któryś plik dotyczy wtyczki, której już nie używasz? To kandydat do usunięcia, po backupie.
  4. Czy w katalogu wtyczek jest coś, co różni się od oficjalnego wydania w tej samej wersji? To kandydat na fork z lokalną poprawką.
  5. Czy przy ostatniej aktualizacji ktoś sprawdził, że dostosowania przeżyły?
  6. Czy potrafisz wyłączyć pojedynczą customową funkcję bez wchodzenia na serwer?

Czego nauczyła nas ta historia

Customowy kod strony klienta ma mieszkać w jednej, nazwanej wtyczce z modułami i panelem – nawet jeśli na start to tylko dwie funkcje. Katalog mu-plugins zostawiamy wyłącznie na rzeczy, które muszą działać, gdy zwykłe wtyczki padną. A jeśli musimy dopisać poprawkę do wtyczki, jej miejsce jest w wydaniu tej wtyczki, nie w lokalnej kopii na jednym serwerze. Inaczej najbliższa aktualizacja cicho ją cofnie.

FAQ

Czym różnią się mu-plugins od zwykłych wtyczek?

WordPress ładuje każdy plik PHP z katalogu mu-plugins automatycznie, przed zwykłymi wtyczkami. Nie da się ich aktywować ani wyłączyć z panelu i nie pojawiają się na standardowej liście wtyczek, tylko w osobnej zakładce dla wtyczek obowiązkowych (Must-Use).

Czy mu-plugins są złe?

Nie, mają swoje zastosowanie: kod, który musi zadziałać niezależnie od stanu zwykłych wtyczek – strażnicy, ustawienia hostingowe, awaryjne poprawki. Problem zaczyna się, gdy trafia tam zwykła funkcjonalność sklepu, bo tak było szybciej.

Czy przeniesienie kodu z mu-plugins do wtyczki jest ryzykowne?

Ryzyko jest kontrolowane, pod warunkiem że kod przenosi się bez zmian, robi backup całego katalogu i weryfikuje obecność hooków po wdrożeniu. Ryzykowna jest wersja, w której przy okazji przeprowadzki „poprawia się” kod.

Jak sprawdzić, czy moja wtyczka jest forkiem?

Porównaj pliki ze świeżo pobranym oficjalnym wydaniem w tej samej wersji. Różnice oznaczają lokalne zmiany, które znikną przy najbliższej aktualizacji. Takie poprawki trzeba przenieść do wydania albo do osobnej wtyczki.

Co z customowym kodem w functions.php motywu?

To ten sam problem w innym miejscu – zmiana motywu albo jego aktualizacja zabiera kod ze sobą. Docelowo trafia on do tej samej dedykowanej wtyczki z modułami.

Ile trwa taka konsolidacja?

U nas przeniesienie, sprzątanie i weryfikacja zmieściły się w jednym dniu pracy. Najwięcej czasu zajmuje nie samo przenoszenie, tylko ustalenie, co każdy plik robi i czy jest jeszcze potrzebny.

Masz stronę, która przez lata obrosła dopiskami, i nikt już nie wie, co robi połowa z nich? To nie powód do wstydu, tylko normalny efekt kilku lat rozwoju.

Robimy inwentaryzację customowego kodu, składamy go w jedną wtyczkę z panelem i sprawdzamy po wdrożeniu, że wszystko działa jak wcześniej – z backupem i listą tego, co usunęliśmy jako martwe. Napisz do nas przez formularz – wystarczy adres strony i zdanie o tym, co Cię na niej niepokoi. Jeśli prowadzisz kursy online, zajrzyj też na platformykursowe.pl.

Grzegorz Rówiński · Kosari

Buduję strony, sklepy i platformy kursowe, automatyzuję procesy i wdrażam AI w firmach. Ten wpis powstał z realnego wdrożenia, nie z teorii.

Napisz do mnie →

Przeczytaj też

Masz podobny problem i nie chcesz go debugować sam?

Napisz krótko co się dzieje. Odpowiadamy konkretnie, bez zobowiązań - powiemy z czego to najpewniej wynika i ile kosztuje naprawa.

Napisz do nas

Wolisz porozmawiać? Zadzwoń: +48 887 255 528

Zadzwoń +48 887 255 528