Kompleksowy przewodnik optymalizacji WooCommerce (edycja 2026)

Kompleksowy przewodnik optymalizacji WooCommerce (edycja 2026)

Ostatnio zweryfikowano: 14 października 2026
12 min czytania
Przewodnik
Ekspert WooCommerce
Core Web Vitals

Domyślne WooCommerce zwalnia, zanim katalog zrobi się ciekawy. Czysta instalacja z kilkuset produktami działa szybko na stagingu, a ten sam szablon z dziesiątkami tysięcy produktów i zamówień zaczyna mieć długi TTFB, cart fragments kolejkują się na archiwum sklepu, a tabela wp_options po cichu puchnie.

Problemem nie jest platforma, tylko konfiguracja i lata dokładania wtyczek. Jako programista WooCommerce na co dzień optymalizuję sklepy pod wydajność, a ten tekst to notatki z takich audytów.

To przewodnik terenowy po utwardzaniu WooCommerce pod realny ruch. Zakłada dostęp do shella, WP-CLI i gotowość do czytania slow query logu.

#Na czym polega migracja WooCommerce do HPOS

Przez dekadę WooCommerce przechowywało zamówienia jako wpisy typu shop_order w wp_posts (ta sama tabela co artykuły na blogu), a każdą pozycję, adres i pole metadanych rozbijało na wiersze w wp_postmeta. Zapytanie “zamówienia z maja” oznaczało skanowanie tabeli wymieszanej z rewizjami, autozapisami i szkicami stron, a potem trzy lub cztery JOIN-y z postmeta, żeby odtworzyć każde zamówienie.

High Performance Order Storage przenosi zamówienia do tabel wc_orders, wc_order_addresses, wc_order_operational_data i wc_orders_meta. Listy zamówień trafiają bezpośrednio w indeksowane kolumny, zamiast składać każdy wiersz z postmeta.

HPOS jest domyślny dla nowych instalacji od WooCommerce 8.2, wydanego w październiku 2023, według dokumentacji HPOS. Sklepy uruchomione przed tą wersją często nadal działają na przechowywaniu w postach, dlatego migracja wciąż jest pierwszym punktem większości audytów.

Czego HPOS sam nie naprawi:

  • Własne wtyczki, które zapisują dane w kluczach postmeta zamiast przez API zamówień, po wyłączeniu trybu zgodności po cichu się rozjadą
  • Wtyczki, które czytają zamówienia przez get_post_meta($order_id, ...) zamiast $order->get_meta(), zaczną zwracać puste wartości, gdy stara tabela przestanie być źródłem prawdy
  • Raporty zbudowane na WP_Query po typie shop_order trzeba przepisać

Przebieg:

  1. WooCommerce -> Ustawienia -> Zaawansowane -> Funkcje, włącz High Performance Order Storage z włączonym trybem zgodności
  2. Puść synchronizację poza godzinami szczytu; w dużym sklepie może trwać kilka godzin
  3. Sprawdź dane poleceniem wp wc hpos verify_data
  4. Przez tydzień testuj wszystkie wtyczki dotykające zamówień, z trybem zgodności nadal zapisującym do postmeta
  5. Wyłącz tryb zgodności dopiero, gdy potwierdzisz, że każda taka wtyczka czyta z HPOS
wp wc hpos status
wp wc hpos sync --batch-size=500
wp wc hpos verify_data

#Polecenia WP-CLI dla HPOS od WooCommerce 8.9

Starsze poradniki używają przestrzeni wp wc cot. WooCommerce 8.9.0 oznaczyło ją jako przestarzałą: stare polecenia nadal działają, ale każde wypisuje ostrzeżenie z nazwą następcy w wp wc hpos, a verify_cot_data zmieniło nazwę na verify_data (CLIRunner.php). Dokumentacja narzędzi CLI dla HPOS i opisy samych poleceń podają obecny zestaw:

  • wp wc hpos status pokazuje ustawienia HPOS i stan synchronizacji
  • wp wc hpos count_unmigrated liczy zamówienia, które czekają na synchronizację
  • wp wc hpos sync migruje zamówienia partiami, a --batch-size domyślnie wynosi 500
  • wp wc hpos verify_data porównuje oba magazyny danych; flaga --re-migrate ponownie synchronizuje zamówienia z różnicami i może nadpisać zamówienie, więc najpierw użyj jej na stagingu
  • wp wc hpos diff 123 pokazuje różnice dla jednego zamówienia
  • wp wc hpos compatibility-mode enable i disable przełączają synchronizację bez wchodzenia do panelu
  • wp wc hpos cleanup usuwa stare dane z tabel postów dla zmigrowanych zamówień. Dokumentacja nazywa to operacją destrukcyjną i bez argumentów polecenie nic nie robi; wp wc hpos cleanup all przetwarza wszystkie zamówienia

cleanup uruchamiaj dopiero wtedy, gdy tryb zgodności jest wyłączony na tyle długo, że żadna wtyczka nie czyta starej kopii, i zawsze po kopii zapasowej bazy.

#Jak dostosować własną wtyczkę do HPOS

WooCommerce ostrzega właściciela sklepu, gdy ten próbuje włączyć HPOS przy aktywnej wtyczce zadeklarowanej jako niezgodna, i pokazuje to samo ostrzeżenie na ekranie wtyczek. Przy wtyczkach, które nie są rozszerzeniami WooCommerce, ostrzeżenie pojawia się tylko wtedy, gdy nagłówek wtyczki zawiera linię WC tested up to. Własna wtyczka deklaruje swój status w głównym pliku, tak jak pokazuje zbiór przepisów HPOS:

add_action( 'before_woocommerce_init', function() {
    \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
} );

Deklaracja to obietnica, a nie poprawka. Kod za nią musi ładować zamówienia przez wc_get_order() zamiast get_post() i zapisywać metadane przez obiekt zamówienia (update_meta_data(), add_meta_data(), delete_meta_data(), a potem save()) zamiast update_post_meta(). Wtedy WooCommerce samo decyduje, do których tabel trafia zapis. Dokumentacja zaznacza, że save() jest stosunkowo kosztowne, więc pętla zapisująca zamówienie po każdej zmianie metadanych sama staje się problemem wydajności. Kod, który musi rozróżniać silnik przechowywania, może wywołać OrderUtil::custom_orders_table_usage_is_enabled().

#Jak wyłączyć cart fragments w WooCommerce

Starszy sklep WooCommerce albo taki z widżetem koszyka w nagłówku pokaże w GTmetrix lub WebPageTest żądanie ?wc-ajax=get_refreshed_fragments na każdej podstronie. To WooCommerce pyta PHP, czy ikonka koszyka w nagłówku się zmieniła: na stronie głównej, na blogu, w archiwach kategorii, na stronie “O nas”. Nawet gdy koszyk jest pusty.

Najprostsza reguła zakresu:

add_action( 'wp_enqueue_scripts', function() {
    if ( is_cart() || is_checkout() || is_product() ) {
        return;
    }
    wp_dequeue_script( 'wc-cart-fragments' );
}, 11 );

Wtyczki Perfmatters i Asset CleanUp wystawiają to jako przełącznik w panelu. Obie drogi prowadzą do tego samego celu: cart fragments mają działać tylko tam, gdzie ikonka koszyka naprawdę musi aktualizować się na żywo.

Jeśli licznik koszyka w nagłówku jest potrzebny na każdej stronie, trzymaj go w localStorage i aktualizuj z JavaScriptu przy zdarzeniach dodania do koszyka, zamiast odpytywać serwer.

#Kiedy WooCommerce ładuje cart fragments od wersji 7.8

WooCommerce 7.8 zmieniło zachowanie domyślne. Według wpisu na blogu deweloperskim WooCommerce Best practices for the use of the “cart fragments” API (16 czerwca 2023) skrypt nie jest już dołączany na każdej ścieżce sklepu. Nadal ładuje się w trzech przypadkach: na stronach, na których renderuje się widżet koszyka, gdy skrypt zewnętrzny rejestruje skrypt cart fragments jako zależność, oraz gdy kod dołącza go jawnie. Ten sam wpis zaznacza, że część motywów, w tym Storefront, ma widżet na stałe w szablonach.

W aktualnym sklepie to żądanie w wodospadzie jest więc objawem z konkretną przyczyną. Wyszukaj uchwyt wc-cart-fragments w źródle strony i sprawdź, który szablon motywu albo która wtyczka go dociąga. Wyłączenie skryptu bez tej kontroli może zepsuć koszyk w nagłówku, który motyw nadal odświeża przez fragments, a wtyczka deklarująca skrypt jako zależność i tak dołączy go ponownie.

#Object cache czy transienty w bazie danych

WooCommerce intensywnie korzysta z transientów: zakresy cen wariantów, wyszukiwanie terminów atrybutów, obliczenia kosztów wysyłki. Bez object cache transienty trafiają do wp_options. To, czy ładują się przy każdym żądaniu, zależy od czasu wygaśnięcia: set_transient() zapisuje transient bez wygaśnięcia z autoload, a transient z wygaśnięciem bez autoload, plus osobny wiersz _transient_timeout_. WooCommerce zapisuje transienty cen wariantów i listy wariantów potomnych z 30-dniowym wygaśnięciem (magazyn danych produktów zmiennych), więc głównie zwiększają liczbę wierszy w wp_options. Ciężar autoload biorą na siebie opcje, które wtyczki zapisują bez wygaśnięcia.

Wybierz jeden backend cache i trzymaj się go. Albo Redis lub Memcached jako prawdziwy object cache, albo transienty w bazie. Mieszanie obu daje błędy unieważniania, które trudno zdiagnozować.

# Rozmiar autoload w wp_options
wp db query "SELECT SUM(LENGTH(option_value)) AS bytes, COUNT(*) AS rows FROM wp_options WHERE autoload IN ('yes', 'on', 'auto-on', 'auto');"

# Największe opcje z autoload
wp db query "SELECT option_name, LENGTH(option_value) AS bytes FROM wp_options WHERE autoload IN ('yes', 'on', 'auto-on', 'auto') ORDER BY bytes DESC LIMIT 20;"

WordPress wykonuje wiele zapytań, żeby zbudować pojedynczą kartę produktu: warianty, ceny, stany magazynowe. Redis trzyma w RAM wyniki tych zapytań. Gdy Redis jest skonfigurowany na serwerze, u hostingu z zarządzanym Redisem albo na własnej instancji redis-server, a object-cache.php leży na miejscu, set_transient() zapisuje do object cache zamiast do wp_options, transienty przenoszą się do RAM i spada presja na autoload.

#Wartości autoload w WordPress 6.6 i próg 800 KB

WordPress 6.6 zmienił sposób zapisu autoload. Notatka deweloperska rdzenia Options API: disabling autoload for large options wprowadza wartości on, off, auto, auto-on i auto-off; on i off to jawne decyzje, a auto-on i auto-off ustawia sam WordPress. Funkcja wp_autoload_values_to_autoload() zwraca yes, on, auto-on i auto, dlatego zapytania audytowe powyżej filtrują po tej liście. Zapytanie sprawdzające tylko autoload = 'yes' pomija każdą opcję zapisaną po aktualizacji i pokazuje sklep czystszym, niż jest.

Razem ze zmianą przyszły dwa progi. Opcja większa niż 150 000 bajtów nie jest ładowana automatycznie, chyba że kod jawnie o to poprosi, a filtr wp_max_autoloaded_option_size przesuwa ten limit. Kondycja witryny zgłasza problem, gdy łączny rozmiar opcji z autoload przekracza 800 KB. To najtańszy pierwszy test w nieznanym sklepie, bo nie wymaga dostępu do shella i nazywa problem, zanim ktokolwiek otworzy klienta bazy danych.

#Czego nie wolno cache’ować w sklepie WooCommerce

Cache statyczny pomaga archiwom, kartom produktów i wpisom na blogu. Psuje wszystko, co zależy od sesji użytkownika, bo każdy klient ma własny koszyk.

Obowiązkowe wyjątki dla każdego cache stron i każdej reguły Cloudflare:

  • /koszyk/ lub /cart/
  • /zamowienie/ lub /checkout/
  • /moje-konto/ lub /my-account/
  • Każdy URL z ?wc-ajax=
  • Każde żądanie z cookie woocommerce_items_in_cart
  • Endpointy REST pod /wp-json/wc/

Statyczne zasoby (zdjęcia, CSS, JS) cache’uj na krawędzi sieci. Cloudflare APO for WordPress potrafi cache’ować także HTML dla niezalogowanych i respektuje cookies sesji WooCommerce, jeśli jest dobrze skonfigurowane, ale sprawdź curl -I na koszyku i zamówieniu, czy dostajesz cf-cache-status: BYPASS. Źle ustawiony cache, który pokazuje koszyk innego klienta, to incydent z zakresu RODO, a nie zysk wydajności.

#Zapytania o produkty zmienne i filtr woocommerce_variable_children_args

Produkty zmienne z kilkudziesięcioma wariantami każdy mnożą JOIN-y. Archiwum sklepu odzieżowego z 200 produktami zmiennymi po 30 wariantów to przy każdym wczytaniu JOIN z wp_posts po 6000 produktów potomnych.

Dwie praktyczne poprawki:

  • Ogranicz warianty ładowane do listy rozwijanej do tych, które są na stanie i widoczne
  • Użyj woocommerce_variable_children_args, aby na archiwach wykluczyć z pierwszego ładowania warianty prywatne i niedostępne
add_filter( 'woocommerce_variable_children_args', function( $args ) {
    if ( is_shop() || is_product_category() ) {
        $args['post_status'] = 'publish';
        $args['meta_query'][] = array(
            'key'     => '_stock_status',
            'value'   => 'instock',
        );
    }
    return $args;
} );

#Jak ograniczyć rozrost tabel Action Scheduler

Każde rozszerzenie WooCommerce, które pracuje w tle, korzysta z Action Scheduler. Subskrypcje, maile przypominające, odzyskiwanie porzuconych koszyków, synchronizacja stanów, integracje z ERP: wszystko ląduje w wp_actionscheduler_actions i wp_actionscheduler_logs.

W sklepie z aktywnymi subskrypcjami i odzyskiwaniem koszyków te tabele potrafią w ciągu roku zebrać ogromną liczbę zakończonych i nieudanych akcji, a panel odpytuje je przy każdym wczytaniu, żeby pokazać licznik kolejki.

Skrypt konserwacyjny:

# Usuń zakończone i anulowane akcje starsze niż 31 dni
wp action-scheduler clean --before="31 days ago" --pause=1

# Sprawdź rozmiar kolejki
wp db query "SELECT status, COUNT(*) FROM wp_actionscheduler_actions GROUP BY status;"

# Sprawdź indeksy na status i scheduled_date_gmt
wp db query "SHOW INDEX FROM wp_actionscheduler_actions;"

#Jak długo Action Scheduler przechowuje zakończone i nieudane akcje

Action Scheduler sprząta po sobie podczas przebiegu kolejki. Jego mechanizm czyszczenia kolejki usuwa zakończone i anulowane akcje starsze niż 31 dni, a filtr action_scheduler_retention_period zmienia to okno. Od Action Scheduler 4.0 usuwane są także akcje nieudane, domyślnie po trzech miesiącach (action_scheduler_retention_period_for_failed); komentarz w kodzie wiąże ten okres z kwartalnym cyklem księgowym.

Czyszczenie działa wewnątrz procesu kolejki. W sklepie, który wyłącza WP-Cron i nie ma systemowego crona wywołującego wp-cron.php albo wp action-scheduler run, kolejka staje, a razem z nią czyszczenie, bez żadnego błędu na ekranie. Zaległości po takiej przerwie usuniesz ręcznie przez wp action-scheduler clean, które według dokumentacji WP-CLI Action Scheduler przyjmuje --status (domyślnie canceled,complete), --before (domyślnie 31 dni), --batch-size (domyślnie 20) i --pause, czyli przerwę między partiami na obciążonej bazie.

#Jak zoptymalizować zdjęcia produktów w WooCommerce

Zdjęcia produktów to zwykle najcięższa część każdego sklepu. Trzy zasady:

  1. AVIF dla zdjęć głównych i galerii, z WebP jako zapasem dla starszych wersji Safari, które wciąż pojawiają się w ruchu
  2. Nie wgrywaj surowych zdjęć po 4000 px. Ogranicz proces wgrywania do 2000 px na dłuższym boku
  3. Natywne loading="lazy" wystarcza; usuń stare skrypty JS do leniwego ładowania, które z nim kolidują

Zmniejszaj zdjęcia przed wgraniem, zamiast liczyć, że WordPress wygeneruje miniatury w locie, bo to zapisuje dane w wp_postmeta i powiększa bazę.

#Jak wyczyścić bazę danych WooCommerce przez WP-CLI

Uruchamiaj to co miesiąc, częściej w sklepach z dużą liczbą porzuconych koszyków:

# Usuń wygasłe sesje (potrzebne tylko, gdy zaplanowane czyszczenie stanęło)
wp db query "DELETE FROM wp_woocommerce_sessions WHERE session_expiry < UNIX_TIMESTAMP();"

# Wyczyść transienty WooCommerce
wp wc tool run clear_transients --user=1

# Zoptymalizuj tabele
wp db optimize

# Sprawdź głębokość kolejki Action Scheduler
wp action-scheduler status

Planuj to przez systemowy cron, a nie wp-cron.php, który odpala się tylko przy ruchu. Flaga --user przy wp wc tool run pochodzi z przykładów WooCommerce CLI; podaj ID konta administratora w swojej instalacji. Kto woli panel, może użyć WP-Optimize.

#Jak WooCommerce czyści sesje klientów

WooCommerce samo przycina tabelę sesji. Rejestruje cykliczną akcję Action Scheduler woocommerce_cleanup_sessions, uruchamianą co 12 godzin (class-woocommerce.php), a obsługa sesji usuwa wygasłe wiersze partiami po 100, z krótką przerwą między partiami. Sesja gościa wygasa po dwóch dniach, a zalogowanego klienta po siedmiu; filtry wc_session_expiration i wc_session_expiring zmieniają oba okresy. Czas życia dłuższy niż 30 dni zostawia ostrzeżenie w logu WooCommerce, bo dłuższe sesje powiększają tabelę.

Wynikają z tego dwie rzeczy. Tabela sesji licząca gigabajty zwykle oznacza, że kolejka Action Scheduler nie działa albo wtyczka wydłużyła czas życia sesji, więc przed kasowaniem czegokolwiek sprawdź wp action-scheduler status i te filtry. I nigdy nie uruchamiaj TRUNCATE na wp_woocommerce_sessions w działającym sklepie: opróżnia to wszystkie aktywne koszyki, a DELETE ... WHERE session_expiry < UNIX_TIMESTAMP() powyżej usuwa tylko wiersze, które już wygasły.

#Jakie metryki wydajności WooCommerce śledzić

Optymalizacja na ślepo kończy się optymalizowaniem nie tego, co trzeba. Wybierz kilka sygnałów i sprawdzaj je co tydzień:

  • TTFB przy zimnym cache na archiwum sklepu i jednej karcie produktu
  • Czas do pierwszego bajtu na koszyku i zamówieniu z jednym i czterema produktami w koszyku
  • Liczba wierszy i łączny rozmiar opcji z autoload w wp_options
  • Głębokość kolejki Action Scheduler i najstarsza oczekująca akcja

Query Monitor na stagingu pokazuje, które zapytania dominują. New Relic albo Datadog APM na produkcji pokazują rzeczywisty rozkład. PageSpeed Insights to test dymny, a nie diagnoza.

#Ostatnia aktualizacja

2026-10-14. Jeśli twój sklep nie pasuje do tych wzorców, to nie wzorce są problemem. Zacznij od slow query logu. Konfigurację HPOS, Redisa i porządków w bazie najszybciej domknie programista WooCommerce, który zna te wąskie gardła z produkcji.

Potrzebujesz wsparcia? Sprawdź cennik stron i sklepów WordPress, aby zlecić nam optymalizację sklepu.

Następny krok

Przekuj artykuł w realne wdrożenie

Pod tym wpisem dokładam linki, które domykają intencję użytkownika i prowadzą dalej w strukturze serwisu.

Chcesz wdrożyć ten temat na swojej stronie?

Jeśli problemem są Core Web Vitals, wolny frontend albo ciężki WordPress, rozpiszę i wdrożę konkretny plan optymalizacji.

Powiązany klaster

Sprawdź inne usługi WordPress i bazę wiedzy

Wzmocnij swój biznes dzięki profesjonalnemu wsparciu technicznemu w kluczowych obszarach ekosystemu WordPress.

FAQ do artykułu

Często zadawane pytania

Najważniejsze odpowiedzi, które pomagają wdrożyć temat w praktyce.

SEO-readyGEO-readyAEO-ready2 Q&A
Czym jest HPOS w WooCommerce?#
High Performance Order Storage przenosi zamówienia ze wspólnych tabel wp_posts i wp_postmeta do dedykowanych tabel wc_orders. Znikają JOIN-y w listach zamówień, a kolumny, które wcześniej siedziały w postmeta, można indeksować.
Dlaczego sklep WooCommerce jest wolny mimo cache?#
Cache stron nie pomaga koszykowi, zamówieniu ani kontu klienta, a cart fragments potrafią odpalać się także na zcache'owanych archiwach. Dodaj object cache, ogranicz fragments do stron sklepu i sprawdź opcje z autoload.

Potrzebujesz FAQ dopasowanego do branży i rynku? Przygotujemy wersję pod Twoje cele biznesowe.

Porozmawiajmy

Polecane artykuły