WordPress to potężne narzędzie, ale jego filozofia “wszystko dla każdego” sprawia, że na start dostajemy mnóstwo dodatków, których większość nowoczesnych projektów po prostu nie potrzebuje. Przez lata wypracowałem zestaw konkretnych fragmentów kodu, które pozwalają mi pozbyć się zbędnego balastu bez wpływu na kluczowe działanie strony.
Ten przewodnik to nie tylko lista rzeczy do usunięcia, to strategiczne podejście do wydajności. Inspiracją był dla mnie doskonały artykuł Terence’a Edena, który uzupełniłem o własne rozwiązania sprawdzone w boju. Każdą nazwę hooka poniżej sprawdziłem w kodzie źródłowym WordPressa 7.1.3 (aktualne wydanie na 12 października 2026, według sprawdzenia wersji w api.wordpress.org), a fragmenty, które okazały się przestarzałe, błędne albo szkodliwe, są wyraźnie oznaczone. Jeśli wolisz zlecić to zadanie, zobacz, czym zajmuje się nasz programista WordPress.
Dlaczego warto odchudzić WordPressa
Po co zawracać sobie głowę kilkoma małymi skryptami? Bo one się sumują. Każda zbędna linia to potencjalny konflikt, milisekundy opóźnienia w renderowaniu czy po prostu niepotrzebne bajty wysyłane do użytkownika.
Nasze cele:
- Rozmiar DOM, usunięcie nieużywanych stylów inline.
- Liczba zapytań HTTP, wyłączenie skryptów, których nie powinno tam być.
- Bezpieczeństwo, wyłączenie przestarzałych protokołów jak XML-RPC.
- Core Web Vitals, bezpośredni wpływ na LCP i CLS poprzez usunięcie blokujących renderowanie elementów.
[!IMPORTANT] Zachowaj ostrożność: Nie każdy “bloat” jest bezużyteczny. Jeśli polegasz na specyficznym stylowaniu klasycznego edytora albo na wbudowanych emoji dla starszych przeglądarek, niektóre z tych poprawek mogą nie być dla Ciebie. Zawsze testuj zmiany najpierw na środowisku testowym.
Jak uruchomić kompletny skrypt debloat WordPressa
Dodaj poniższy kod do pliku functions.php Twojego motywu, a jeszcze lepiej do mu-pluginu (patrz ostatnia sekcja), żeby przetrwał zmianę motywu. Każda sekcja jest opatrzona komentarzami i linkami do źródeł.
1. Usuń style classic theme
WordPress dodaje “classic-theme-styles” w motywach, które nie mają pliku theme.json. Core kolejkuje ten arkusz tylko wtedy, gdy wp_theme_has_theme_json() zwraca false, więc motyw blokowy albo motyw klasyczny z theme.json nigdy go nie ładuje. Jeśli Twój go ładuje, usuń go:
// Usuń wymuszony classic theme.
function disable_classic_theme_styles() {
wp_deregister_style( "classic-theme-styles" );
wp_dequeue_style( "classic-theme-styles" );
}
add_action( "wp_enqueue_scripts", "disable_classic_theme_styles" );2. Usuń obsługę emoji
WordPress wstawia mały skrypt wykrywający i dopiero wtedy, gdy przeglądarka nie potrafi wyświetlić aktualnych emoji, ładuje większy skrypt, który podmienia znaki emoji na obrazy SVG. Jeśli Twoi odwiedzający korzystają z aktualnych przeglądarek, to jest zbędne:
// Usuń WP Emoji.
// https://www.denisbouquet.com/remove-wordpress-emoji-code/
remove_action( "wp_head", "print_emoji_detection_script", 7 );
remove_action( "wp_print_styles", "print_emoji_styles" );
remove_action( "admin_print_scripts", "print_emoji_detection_script" );
remove_action( "admin_print_styles", "print_emoji_styles" );
// Wyczyść bazowy URL SVG przekazywany do ustawień emoji.
add_filter( "emoji_svg_url", "__return_false" );
// Zatrzymaj zamianę emoji na obrazy w RSS / Atom Feeds
// https://danq.me/2023/09/04/wordpress-stop-emoji-images/
remove_filter( "the_content_feed", "wp_staticize_emoji" );
remove_filter( "comment_text_rss", "wp_staticize_emoji" );3. Wyłącz automatyczne formatowanie tekstu
WordPress “teksturyzuje” treść: proste cudzysłowy stają się typograficzne, a ASCII -- / --- zamienia na znaki półpauzy / pauzy (U+2013 / U+2014). To psuje przykłady kodu i koliduje z polityką ASCII (- albo --, bez glifów długich myślników w źródle). Na treści technicznej wyłącz:
// Usuń automatyczne formatowanie.
// https://css-tricks.com/snippets/wordpress/disable-automatic-formatting/
remove_filter( "the_content", "wptexturize" );
remove_filter( "the_excerpt", "wptexturize" );
remove_filter( "comment_text", "wptexturize" );
remove_filter( "the_title", "wptexturize" );
// Więcej filtrów formatowania.
add_action("init", function() {
remove_filter( "the_content", "convert_smilies", 20 );
foreach ( array( "the_content", "the_title", "wp_title", "document_title" ) as $filter ) {
remove_filter( $filter, "capital_P_dangit", 11 );
}
remove_filter( "comment_text", "capital_P_dangit", 31 );
// TYLKO strony z klasycznym edytorem: ta linia wyłącza całe renderowanie bloków.
remove_filter( "the_content", "do_blocks", 9 );
}, 11);Uwaga: Filtr
capital_P_dangitto sposób WordPressa na automatyczną poprawęWordpress(z małym p) naWordPress. Jest agresywny i bywa niepożądany.
[!WARNING] Usunięcie
do_blockszthe_contentoznacza, że znaczniki bloków nie są już przetwarzane. Bloki dynamiczne (pętla zapytania, najnowsze wpisy, nawigacja) nic nie wyświetlają. Zostaw tę linię tylko na stronie, której wszystkie wpisy powstały w klasycznym edytorze.
4. Usuń style i skrypty Gutenberga
Jeśli używasz własnego motywu i nie polegasz na frontendowych stylach Gutenberga, usuń je. Na motywie blokowym tego nie rób: style globalne niosą cały wygląd zapisany w theme.json.
// Usuń style Gutenberga.
// https://wordpress.org/support/topic/how-to-disable-inline-styling-style-idglobal-styles-inline-css/
remove_action( "wp_enqueue_scripts", "wp_enqueue_global_styles" );
// W motywach klasycznych core podpina ją też do wp_footer z priorytetem 1.
remove_action( "wp_footer", "wp_enqueue_global_styles", 1 );
// Usuń widgety edycji Gutenberga.
// Z https://wordpress.org/plugins/classic-widgets/
// Wyłącza zarządzanie widgetami przez edytor bloków we wtyczce Gutenberg.
add_filter( "gutenberg_use_widgets_block_editor", "__return_false" );
// Wyłącza zarządzanie widgetami przez edytor bloków.
add_filter( "use_widgets_block_editor", "__return_false" );
// Usuń CSS biblioteki bloków Gutenberga z frontendu.
// https://smartwp.com/remove-gutenberg-css/
function remove_wp_block_library_css() {
wp_dequeue_style( "wp-block-library" );
wp_dequeue_style( "wp-block-library-theme" );
}
add_action( "wp_enqueue_scripts", "remove_wp_block_library_css", 100 );5. Usuń meta tagi z nagłówka
Wyczyść sekcję <head> usuwając niepotrzebne meta tagi:
// Usuń shortlink.
// https://stackoverflow.com/questions/42444063/disable-wordpress-short-links
remove_action( "wp_head", "wp_shortlink_wp_head" );
// Usuń RSD.
// https://wpengineer.com/1438/wordpress-header/
remove_action( "wp_head", "rsd_link" );
// Usuń dodatkowe linki feed.
// https://developer.wordpress.org/reference/functions/feed_links/
add_filter( "feed_links_show_comments_feed", "__return_false" );
add_filter( "feed_links_show_posts_feed", "__return_false" );
// Usuń link api.w.org.
// https://wordpress.stackexchange.com/questions/211467/remove-json-api-links-in-header-html
remove_action( "wp_head", "rest_output_link_wp_head" );
// https://wordpress.stackexchange.com/questions/211817/how-to-remove-rest-api-link-in-http-headers
// https://developer.wordpress.org/reference/functions/rest_output_link_header/
remove_action( "template_redirect", "rest_output_link_header", 11, 0 );6. Usuń ulepszenia obrazów
WordPress dodaje do obrazów atrybuty srcset, sizes, loading, decoding i fetchpriority. Jeśli obsługujesz je samodzielnie, usuń je, ale najpierw przeczytaj dalszą sekcję o obrazach, bo te atrybuty chronią LCP i CLS:
// Usuń wymuszony rozmiar obrazu WordPress
// https://core.trac.wordpress.org/ticket/62413#comment:40
add_filter( "wp_img_tag_add_auto_sizes", "__return_false" );
// Usuń ulepszenia <img>
// https://developer.wordpress.org/reference/functions/wp_filter_content_tags/
remove_filter( "the_content", "wp_filter_content_tags", 12 );
// Zatrzymaj przepisywanie URL http:// dla głównej domeny.
// https://developer.wordpress.org/reference/hooks/wp_should_replace_insecure_home_url/
remove_filter( "the_content", "wp_replace_insecure_home_url", 10 );
// Usuń elementy załączników
// https://developer.wordpress.org/news/2024/01/building-dynamic-block-based-attachment-templates-in-themes/
remove_filter( "the_content", "prepend_attachment" );
// Usuń filtr bloków
remove_filter( "the_content", "apply_block_hooks_to_content_from_post_object", 8 );7. Usuń sprawdzanie przeglądarki i inne funkcje admina
// Usuń sprawdzanie przeglądarki z panelu admina.
// https://core.trac.wordpress.org/attachment/ticket/27626/disable-wp-check-browser-version.0.2.php
if ( !empty( $_SERVER["HTTP_USER_AGENT"] ) ) {
add_filter( "pre_site_transient_browser_" . md5( $_SERVER["HTTP_USER_AGENT"] ), "__return_null" );
}
// Usuń hovercards na linkach komentarzy w panelu admina.
// https://wordpress.org/support/topic/how-to-disable-mshots-service/#post-12946617
add_filter( "akismet_enable_mshots", "__return_false" );Jakie dodatkowe kroki warto zrobić po debloat WordPressa
Poza powyższymi technikami, oto moje własne rozwiązania dla dalszej optymalizacji:
8. Wyłącz XML-RPC
Jeśli nie używasz zewnętrznych aplikacji do publikowania w WordPressie, wyłącz metody XML-RPC wymagające logowania, a razem z nimi metody pingback. Sam filtr xmlrpc_enabled nie wyłącza punktu końcowego (szczegóły niżej):
// Wyłącz metody XML-RPC wymagające uwierzytelnienia
add_filter( 'xmlrpc_enabled', '__return_false' );
// Usuń metody pingback, które inaczej zostają otwarte
add_filter( 'xmlrpc_methods', function( $methods ) {
unset( $methods['pingback.ping'], $methods['pingback.extensions.getPingbacks'] );
return $methods;
} );
// Usuń link XML-RPC z nagłówka
remove_action( 'wp_head', 'rsd_link' );9. Usuń jQuery Migrate
Nowoczesne motywy i wtyczki WordPress rzadko potrzebują jQuery Migrate. Jeśli Twoja strona działa bez niego, usuń go:
function remove_jquery_migrate( $scripts ) {
if ( ! is_admin() && isset( $scripts->registered['jquery'] ) ) {
$script = $scripts->registered['jquery'];
if ( $script->deps ) {
$script->deps = array_diff( $script->deps, array( 'jquery-migrate' ) );
}
}
}
add_action( 'wp_default_scripts', 'remove_jquery_migrate' );10. Wyłącz oEmbed
Jeśli żadna inna strona nie musi osadzać Twoich wpisów, wyłącz oEmbed po stronie dostawcy. Osadzenia YouTube i innych zarejestrowanych dostawców w Twoich własnych wpisach nadal działają, bo WordPress uruchamia wykrywanie tylko dla adresów spoza wbudowanej listy dostawców:
// Usuń linki wykrywania oEmbed
remove_action( 'wp_head', 'wp_oembed_add_discovery_links' );
remove_action( 'wp_head', 'wp_oembed_add_host_js' );
// Usuń endpoint REST API oEmbed
remove_action( 'rest_api_init', 'wp_oembed_register_route' );
// Wyłącz auto wykrywanie oEmbed
add_filter( 'embed_oembed_discover', '__return_false' );11. Odrocz ładowanie JavaScriptu
Dodaj defer do niekrytycznych skryptów dla lepszej wydajności. Poniższy filtr to stare podejście, które pomija reguły zależności stosowane przez core od WordPressa 6.3; dalsza sekcja o strategii ładowania pokazuje sposób wspierany oficjalnie:
function add_defer_attribute( $tag, $handle ) {
// Skrypty, które NIE powinny być odroczone
$scripts_to_not_defer = array( 'jquery-core' );
if ( in_array( $handle, $scripts_to_not_defer ) || str_contains( $tag, ' defer' ) ) {
return $tag;
}
return str_replace( ' src', ' defer src', $tag );
}
add_filter( 'script_loader_tag', 'add_defer_attribute', 10, 2 );Jak mierzyć efekty wyłączenia zbędnych funkcji WordPressa
Po wdrożeniu tych zmian, przetestuj swoją stronę używając:
- Google PageSpeed Insights, sprawdź Core Web Vitals
- GTmetrix, szczegółowa analiza waterfall
- WebPageTest, wiele lokalizacji testowych i prędkości połączenia
Powinieneś zobaczyć:
- Zmniejszony rozmiar strony (mniej bajtów CSS/JS)
- Mniej zapytań HTTP
- Lepszy Largest Contentful Paint (LCP), jeśli usunięty zasób blokował renderowanie
Czas odpowiedzi serwera (TTFB) prawie się nie zmienia, bo żaden z tych fragmentów nie zmienia sposobu, w jaki PHP buduje stronę. TTFB poprawia dopiero warstwa cache.
Co ładuje domyślna instalacja WordPressa 7.1
Zanim cokolwiek usuniesz, warto wiedzieć, ile kosztuje każda funkcja. Rozmiary poniżej zmierzyłem na plikach z oficjalnego archiwum wordpress-7.1.3.zip: surowe bajty na dysku oraz rozmiar po kompresji gzip na poziomie 9, zbliżony do tego, co serwer faktycznie wysyła.
| Zasób | Plik | Surowy | Gzip | Kiedy się ładuje |
|---|---|---|---|---|
| Loader emoji (inline, stopka) | wp-emoji-loader.min.js | 2977 B | 1290 B | Na każdej stronie frontendu |
| Skrypt zamiany emoji | wp-emoji-release.min.js | 22 752 B | 5310 B | Tylko gdy przeglądarka nie przejdzie testu emoji |
| Style classic theme | classic-themes.min.css | 291 B | 233 B | Motywy bez theme.json |
| Pełna biblioteka bloków | block-library/style.min.css | 140 829 B | 18 938 B | Tylko przy wyłączonym ładowaniu stylów bloków na żądanie |
| Style motywu biblioteki bloków | block-library/theme.min.css | 2752 B | 751 B | Motywy deklarujące wp-block-styles, przy wyłączonym ładowaniu na żądanie |
| jQuery | jquery.min.js | 87 553 B | 30 356 B | Gdy motyw albo wtyczka go kolejkuje |
| jQuery Migrate | jquery-migrate.min.js | 13 577 B | 4891 B | Razem z uchwytem jquery |
| Dashicons | dashicons.min.css | 59 004 B | 35 693 B | Pasek admina dla zalogowanych albo wtyczka |
| Skrypt hosta osadzeń wpisów | wp-embed.min.js | 1251 B | 710 B | Tylko na stronach z osadzonym wpisem WordPressa |
| Heartbeat | heartbeat.min.js | 5947 B | 2058 B | Ekrany admina, na frontendzie tylko na żądanie wtyczki |
| Odpowiedzi na komentarze | comment-reply.min.js | 2950 B | 1371 B | Gdy kolejkuje go motyw albo blok Komentarze |
Dwie liczby się wyróżniają. jQuery z Migrate to zwykle najcięższa rzecz, jaką wysyła motyw klasyczny, więc rezygnacja z jQuery we własnym kodzie motywu oszczędza więcej niż wszystkie poprawki w tagach head razem. A arkusz biblioteki bloków o rozmiarze 140 KB nie ładuje się już w całości na domyślnej instalacji: motywy blokowe ładują tylko style bloków obecnych na stronie od WordPressa 5.9, a od wersji 6.9 core włącza to samo ładowanie na żądanie dla motywów klasycznych przez wp_load_classic_theme_block_styles_on_demand(), o ile działa bufor wyjścia szablonu. Motyw może z tego zrezygnować, zwracając false z filtrów should_load_separate_core_block_assets i should_load_block_assets_on_demand.
Żeby zobaczyć, co naprawdę ładuje konkretna strona, użyj przeglądarki. W Chrome DevTools otwórz zakładkę Network, odśwież stronę z wyłączonym cache, przefiltruj po własnej domenie i posortuj po rozmiarze. Lighthouse w tym samym panelu DevTools pokazuje nieużywany CSS i JavaScript dla każdego pliku. WP-CLI tu nie pomoże: wywołanie wp eval nigdy nie renderuje szablonu, więc kolejki skryptów i stylów, które wypisuje, są puste. Działa za to hook w stopce, który zapisuje dane do logu:
// Zapisz w logu każdy zakolejkowany uchwyt przy wyświetleniu frontendu (tylko staging).
add_action( 'wp_footer', function () {
if ( is_admin() ) {
return;
}
foreach ( wp_scripts()->queue as $handle ) {
error_log( 'script: ' . $handle . ' ' . wp_scripts()->registered[ $handle ]->src );
}
foreach ( wp_styles()->queue as $handle ) {
error_log( 'style: ' . $handle . ' ' . wp_styles()->registered[ $handle ]->src );
}
}, 999 );Jakie funkcje WordPressa wyłączać funkcja po funkcji
Powyższy skrypt to wersja szybka. Niżej każda funkcja dostaje kontekst potrzebny do decyzji, czy powinna zostać na Twojej stronie.
Czym są classic theme styles i ile kosztują
WordPress 6.1 dodał mały arkusz stylów, który daje motywom klasycznym rozsądne domyślne wartości dla znaczników bloków, na przykład odstępy w blokach przycisku i pliku. Waży 291 bajtów i kolejkuje go wp_enqueue_classic_theme_styles() tylko wtedy, gdy aktywny motyw nie ma theme.json. Usuń go w motywie klasycznym z własnym CSS dla bloków. Zostaw w motywach klasycznych, które liczą na to, że znaczniki bloków z core wyglądają poprawnie bez dodatkowej pracy, a w motywach blokowych w ogóle się nim nie przejmuj, bo tam nigdy się nie ładuje.
Po co WordPress ładuje skrypt emoji
Funkcja emoji robi dwie rzeczy: sprawdza, czy przeglądarka potrafi narysować najnowsze emoji, a jeśli nie, ładuje wp-emoji-release.min.js, który zamienia znaki na obrazy z s.w.org. W WordPressie 7.1.3 test jest wbudowanym skryptem type="module" wypisywanym w stopce, więc nie blokuje już renderowania, a wyniki trafiają do sessionStorage. Razem z nim przychodzi mały wbudowany arkusz stylów dla img.emoji. Usunięcie akcji z wp_print_styles nadal działa: wp_enqueue_emoji_styles() sprawdza tę akcję i pomija wbudowany CSS, gdy jej nie ma.
Filtr emoji_svg_url ustawia dziś tylko bazowy URL SVG w ustawieniach emoji. Starsze poradniki używały go, żeby pozbyć się DNS prefetch do s.w.org; wp_resource_hints() w wersji 7.1.3 już tej wskazówki nie dodaje, więc ta linia jest nieszkodliwa, ale nie oszczędza już żadnego zapytania DNS. Zostaw obsługę emoji, jeśli odwiedzający piszą w komentarzach albo na forach ze starych urządzeń, których czcionki nie mają najnowszych emoji. Pełna wersja obejmuje też e-maile i klasyczny edytor:
function disable_emojis_completely() {
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
remove_action( 'wp_print_styles', 'print_emoji_styles' );
remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
remove_action( 'admin_print_styles', 'print_emoji_styles' );
remove_action( 'embed_head', 'print_emoji_detection_script' );
remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
add_filter( 'tiny_mce_plugins', function ( $plugins ) {
return array_diff( $plugins, array( 'wpemoji' ) );
} );
}
add_action( 'init', 'disable_emojis_completely' );Co zmienia wptexturize w treści
wptexturize() zamienia proste cudzysłowy na typograficzne, -- i --- na półpauzę i pauzę, a trzy kropki na znak wielokropka. Na stronach technicznych psuje shortcode’y, HTML i fragmenty PHP, które czytelnicy kopiują. Całą funkcję można wyłączyć jednym filtrem zamiast usuwać ją z każdego hooka osobno:
add_filter( 'run_wptexturize', '__return_false' );Zostaw ją tylko na stronach redakcyjnych, które chcą typograficznych cudzysłowów i nigdy nie publikują kodu.
Co robi filtr capital_P_dangit
capital_P_dangit() zamienia Wordpress na WordPress. W tytułach zamienia każde wystąpienie, w treści i komentarzach tylko po spacji, cudzysłowie, > albo (. Nie rusza adresów URL, bo ukośnik przed słowem nie pasuje do wzorca. Prawdziwe ryzyko dotyczy kodu: przykład zawierający Wordpress po spacji zostaje po cichu zmieniony.
Jakie style i skrypty ładuje Gutenberg
Na frontendzie edytor bloków dokłada wp-block-library (CSS bloków), wp-block-library-theme (style motywu z własnym wyglądem) oraz wbudowane global-styles generowane z theme.json. wp-components należy do ekranów edytora, więc usuwanie go z kolejki na frontendzie nic nie daje. Starsze fragmenty kodu usuwają też wp_global_styles_render_svg_filters z wp_body_open; ta funkcja jest przestarzała od wersji 6.3.0 i nie jest już podpięta. Usuwaj CSS bloków tylko na stronach, które nie renderują bloków na frontendzie. Na motywie blokowym usunięcie stylów globalnych zdejmuje cały wygląd motywu.
Jakie meta tagi WordPress dodaje do nagłówka
Domyślne wp_head w wersji 7.1.3 wypisuje między innymi:
<meta name="generator" content="WordPress 7.1.3" />
<link rel="shortlink" href="https://example.com/?p=123" />
<link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://example.com/xmlrpc.php?rsd" />
<link rel="https://api.w.org/" href="https://example.com/wp-json/" />
<link rel="alternate" type="application/json" href="https://example.com/wp-json/wp/v2/posts/123" />| Tag | Ryzyko | Rekomendacja |
|---|---|---|
| generator | Niskie, wersja i tak widnieje jako ?ver= przy zasobach core | Usuń, jeśli chcesz, niewiele ukrywa |
| shortlink | Brak | Usuń |
| RSD (EditURI) | Kieruje klientów do xmlrpc.php | Usuń razem z XML-RPC |
| Linki REST API | Niskie | Zostaw, jeśli coś wykrywa Twoje API |
Dwa usunięcia, które wciąż pojawiają się w wielu poradnikach, w aktualnych wersjach nic nie robią: wlwmanifest_link jest przestarzały od wersji 6.3.0 i nie jest już wypisywany, a adjacent_posts_rel_link_wp_head nie jest używany przez core od wersji 5.6.0. Aktualne czyszczenie jest krótsze:
add_action( 'init', function () {
remove_action( 'wp_head', 'wp_generator' );
remove_action( 'wp_head', 'wp_shortlink_wp_head' );
remove_action( 'template_redirect', 'wp_shortlink_header', 11 );
remove_action( 'wp_head', 'rsd_link' );
} );Co WordPress dodaje do obrazów
wp_filter_content_tags() dodaje srcset i sizes, brakujące width i height, loading="lazy" na obrazach poniżej pierwszego ekranu, decoding="async" oraz fetchpriority="high" na prawdopodobnym obrazie LCP. Filtr wp_img_tag_add_auto_sizes pojawił się w wersji 6.7.0, nie wcześniej. Wyłączenie tych funkcji zwykle pogarsza CLS i LCP, czyli działa odwrotnie do zamierzonego celu, więc rób to tylko wtedy, gdy CDN albo Twoje własne znaczniki ustawiają wszystkie te atrybuty. Żeby wyłączyć samo leniwe ładowanie:
add_filter( 'wp_lazy_loading_enabled', '__return_false' );Jak działa sprawdzanie przeglądarki w kokpicie
wp_check_browser_version() pyta api.wordpress.org, czy przeglądarka administratora jest przestarzała, i zapisuje odpowiedź jako transient witryny na tydzień, z kluczem opartym na MD5 user agenta. To jedno zdalne zapytanie na przeglądarkę na tydzień, a nie na każde wyświetlenie strony panelu. Sprawdzanie wersji PHP działa tak samo, ale kluczem transientu jest php_check_ plus MD5 z PHP_VERSION, a nie z user agenta, więc fragmenty kodu filtrujące pre_site_transient_phpcompat_ nic nie robią:
add_filter( 'pre_site_transient_php_check_' . md5( PHP_VERSION ), '__return_null' );Zostaw to sprawdzanie, chyba że wersję PHP monitoruje ktoś inny, bo to właśnie ono ostrzega właścicieli stron, że ich PHP straciło wsparcie.
Co naprawdę wyłącza filtr xmlrpc_enabled
XML-RPC to protokół zdalnego publikowania, z którego korzystają starsze aplikacje mobilne, edytory desktopowe i pingbacki. Nazwa filtra sugeruje główny wyłącznik, ale kod źródłowy WordPressa 7.1.3 mówi co innego:
“Wbrew swojej nazwie ten filtr nie decyduje o tym, czy XML-RPC jest włączony w całości, a jedynie o tym, czy włączone są metody XML-RPC wymagające uwierzytelnienia, na przykład te służące do publikowania.”
Źródło: komentarz dokumentujący metodę wp_xmlrpc_server::set_is_enabled() w kodzie WordPressa 7.1.3 (tłumaczenie własne).
Po add_filter( 'xmlrpc_enabled', '__return_false' ) plik xmlrpc.php nadal odpowiada, a pingback.ping nadal działa. Pingbacki to część nadużywana do odbijania ruchu, a system.multicall pozwala zmieścić w jednym żądaniu wiele prób logowania, co filtr akurat zatrzymuje, bo te metody wymagają uwierzytelnienia. Fragment z sekcji 8 usuwa dodatkowo metody pingback przez xmlrpc_methods. Nagłówek HTTP X-Pingback jest wysyłany tylko na pojedynczych wpisach, które przyjmują pingi, więc zamknięcie pingów (kolejne sekcje) usuwa i jego. Żeby całkowicie wyłączyć punkt końcowy, zablokuj xmlrpc.php na serwerze WWW; potem sprawdź każdą wtyczkę i aplikację publikującą zdalnie, bo przestanie działać.
Do czego służy jQuery Migrate
jQuery Migrate przywraca API jQuery usunięte w późniejszych wersjach i zapisuje ostrzeżenia, gdy stary kod je wywołuje. WordPress rejestruje uchwyt jquery jako alias dla jquery-core i jquery-migrate, dlatego fragment z sekcji 9 zmienia listę zależności zamiast usuwać plik z kolejki. Zanim usuniesz go na produkcji, uruchom stronę na stagingu z define( 'SCRIPT_DEBUG', true );. Wtedy WordPress serwuje niezminifikowany jquery-migrate.js, który core trzyma do debugowania, a w konsoli zobaczysz ostrzeżenia JQMIGRATE o przestarzałych wywołaniach. Nie wywołuj wp_deregister_script( 'jquery-migrate' ) na frontendzie; każda wtyczka, która deklaruje jquery-migrate jako zależność, straciłaby wtedy własny skrypt, bo WordPress nie wypisuje skryptu, któremu brakuje zależności.
Jak działa oEmbed w WordPressie
oEmbed ma dwie strony. Jako odbiorca WordPress zamienia wklejony link do YouTube albo Vimeo na odtwarzacz, korzystając z wbudowanej listy dostawców; to działa nadal po zastosowaniu fragmentu z sekcji 10. Jako dostawca Twoja strona wypisuje linki wykrywania i obsługuje /wp-json/oembed/1.0/embed, żeby inne strony na WordPressie mogły osadzać Twoje wpisy. Skrypt wp-embed (710 bajtów po gzip) jest kolejkowany tylko na stronach, które zawierają takie osadzenie wpisu. Dwóch linii ze starszego kodu do wyłączania osadzeń nie kopiuj: usunięcie wp_filter_oembed_result z oembed_dataparse wyłącza oczyszczanie, które core stosuje do HTML od dostawców spoza zaufanej listy, a wtyczka TinyMCE wpembed już nie istnieje, więc odfiltrowanie jej z tiny_mce_plugins nic nie daje.
Jak ograniczyć REST API bez psucia edytora bloków
REST API odpowiada pod /wp-json/ i korzystają z niego edytor bloków, edytor witryny i wiele wtyczek. Oficjalny podręcznik REST API stawia sprawę jasno:
“Nie należy wyłączać REST API; spowoduje to awarię funkcji panelu administracyjnego WordPressa, które wymagają aktywnego API.”
Źródło: najczęściej zadawane pytania w podręczniku REST API na developer.wordpress.org (tłumaczenie własne).
Zamiast tego podręcznik proponuje wymaganie uwierzytelnienia przez filtr rest_authentication_errors. Zalogowani redaktorzy pracują dalej, a anonimowe żądania dostają 401:
add_filter( 'rest_authentication_errors', function( $result ) {
// Jeśli wcześniejsze sprawdzenie uwierzytelnienia już zadziałało,
// przekaż jego wynik bez zmian.
if ( true === $result || is_wp_error( $result ) ) {
return $result;
}
// Uwierzytelnienie jeszcze się nie odbyło.
// Zwróć błąd, jeśli użytkownik nie jest zalogowany.
if ( ! is_user_logged_in() ) {
return new WP_Error(
'rest_not_logged_in',
__( 'You are not currently logged in.' ),
array( 'status' => 401 )
);
}
// Nasze własne sprawdzenie nie powinno wpływać
// na żądania zalogowanych użytkowników
return $result;
});To psuje każdą funkcję frontendu, która dla anonimowych odwiedzających wywołuje /wp-json/: formularze wysyłane przez REST, widżety wyszukiwania albo filtrowania pobierające JSON, frontend headless oraz osadzanie Twoich wpisów na innych stronach przez endpoint oEmbed. Węższa opcja to ukrycie pojedynczych tras filtrem rest_endpoints, na przykład endpointu użytkowników, który wypisuje slugi autorów. Po zmianie przetestuj każdy formularz i każdy interaktywny blok po wylogowaniu.
Jak dostroić Heartbeat API w WordPressie
Heartbeat to pętla odpytywania w heartbeat.js, która w stałych odstępach wysyła żądanie do admin-ajax.php. Obsługuje blokowanie wpisów (komunikat, że ktoś inny edytuje ten wpis), dane autozapisu w klasycznym edytorze oraz sprawdzanie wygaśnięcia sesji, które pokazuje okno ponownego logowania. W WordPressie 7.1.3 domyślny mainInterval to 60 sekund, dopuszczalny zakres to od 1 do 3600 sekund, pętla może tymczasowo przyspieszyć do 5 sekund, a gdy karta jest ukryta, zwalnia do 120 sekund. Ustawienie interwału na 60 niczego więc nie zmienia; przydaje się wolniejszy interwał, przy dużych zespołach w panelu albo słabym hostingu:
add_filter( 'heartbeat_settings', function ( $settings ) {
$settings['interval'] = 120;
return $settings;
} );Na frontendzie core nie ładuje Heartbeat dla odwiedzających; pojawia się tylko wtedy, gdy kolejkuje go wtyczka. Wyrejestrowanie go tam jest bezpieczne, jeśli potem sprawdzisz funkcję tej wtyczki. Nigdy nie wyrejestrowuj go w panelu admina: blokady wpisów i ostrzeżenia o wygasającej sesji od niego zależą.
Jak ograniczyć rewizje wpisów przez WP_POST_REVISIONS
Rewizje nie spowalniają frontendu, bo strony publiczne nigdy ich nie pobierają. Powiększają za to tabelę wp_posts i wydłużają kopie zapasowe oraz eksporty. Steruje nimi stała w wp-config.php, którą odczytuje wp_revisions_to_keep():
define( 'WP_POST_REVISIONS', 10 ); // zachowaj 10 najnowszych rewizji na wpis
// define( 'WP_POST_REVISIONS', false ); // bez rewizjiDomyślna wartość to true, czyli brak limitu. false albo 0 wyłącza rewizje, a liczba dodatnia zachowuje tyle rewizji. Filtr wp_revisions_to_keep nadpisuje stałą, a od WordPressa 5.8 filtr wp_{$post_type}_revisions_to_keep ustawia limit dla konkretnego typu wpisu. Limit zaczyna działać przy następnym zapisie wpisu, więc nadmiarowe rewizje zostają do tego czasu. Wyłączenie rewizji zabiera redaktorom siatkę bezpieczeństwa, dlatego mała liczba zwykle jest lepszym kompromisem.
Autozapis ma własną stałą. W core nie ma filtra autosave_interval, więc kod, który go dodaje, nic nie robi; ustaw interwał w sekundach w wp-config.php:
define( 'AUTOSAVE_INTERVAL', 120 ); // domyślnie 60Jak wyłączyć komentarze w całej witrynie
Strona bez komentarzy nadal wyświetla formularze komentarzy tam, gdzie motyw o nie prosi, zostawia link do kanału komentarzy w head i utrzymuje mechanizm pingbacków. Zamknięcie komentarzy i pingów filtrami obejmuje każdy typ wpisu bez edycji wpisów w bazie danych:
add_filter( 'comments_open', '__return_false', 20, 2 );
add_filter( 'pings_open', '__return_false', 20, 2 );
add_filter( 'feed_links_show_comments_feed', '__return_false' );
add_action( 'admin_menu', function () {
remove_menu_page( 'edit-comments.php' );
} );
add_action( 'init', function () {
remove_post_type_support( 'post', 'comments' );
remove_post_type_support( 'page', 'comments' );
} );Zamknięcie pingów usuwa też nagłówek X-Pingback, bo core wysyła go tylko wtedy, gdy pings_open() zwraca true. Istniejące komentarze zostają w bazie i mogą się nadal wyświetlać, jeśli motyw wypisuje je niezależnie od comments_open(). Skrypt comment-reply nie jest wart osobnej pracy: core rejestruje go ze strategią async i niskim priorytetem pobierania, a po gzip waży 1371 bajtów.
Jak odroczyć skrypty przez strategię ładowania skryptów
Od WordPressa 6.3 funkcje wp_register_script() i wp_enqueue_script() przyjmują argument strategy z wartością defer albo async. Core sprawdza wtedy drzewo zależności przed wypisaniem atrybutu: skrypt z dołączonym skryptem inline w pozycji after nigdy nie jest opóźniany, a skrypt defer wraca do trybu blokującego, gdy zależny skrypt potrzebuje go wcześniej. Ta logika siedzi w WP_Scripts::get_eligible_loading_strategy(). Filtr script_loader_tag z sekcji 11 pomija ją całkowicie i właśnie dlatego odroczone skrypty potrafią uruchomić się po kodzie inline, który je wywołuje.
// Twój własny skrypt.
wp_enqueue_script( 'site-main', get_theme_file_uri( 'js/main.js' ), array(), '1.4.0', array(
'in_footer' => true,
'strategy' => 'defer',
) );
// Skrypt zarejestrowany przez wtyczkę.
add_action( 'wp_enqueue_scripts', function () {
wp_script_add_data( 'some-plugin-handle', 'strategy', 'defer' );
}, 20 );Potem obejrzyj źródło strony: jeśli core uznał, że danego uchwytu nie da się odroczyć, atrybutu po prostu nie będzie.
Jak testować wydajność WordPressa przed i po odchudzeniu
Jeden przebieg PageSpeed Insights to nie pomiar, bo wyniki laboratoryjne zmieniają się między uruchomieniami. Procedura, która daje porównywalne liczby:
- Przygotowanie: wyczyść cache strony, użyj tego samego hostingu i tego samego zestawu adresów URL w obu przebiegach, zapisz wersje WordPressa, motywu i wtyczek.
- Punkt odniesienia: uruchom PageSpeed Insights albo Lighthouse trzy razy dla każdego adresu i zapisz medianę, a potem zanotuj przesłane bajty i liczbę żądań z zakładki Network w DevTools przy wyłączonym cache.
- Wdróż kod debloat na staging i ponownie wyczyść cache.
- Powtórz te same testy na tych samych adresach.
- Porównaj przesłane bajty, liczbę żądań, LCP i CLS. Dane terenowe w sekcji Chrome UX Report w PageSpeed Insights aktualizują się w oknie 28 dni, więc sprawdź je ponownie po miesiącu.
Tabela rozmiarów powyżej wyznacza górną granicę. Na motywie klasycznym, który już ładuje style bloków na żądanie, usunięcie emoji, stylów classic theme i tagów w head oszczędza kilka kilobajtów i kilka linii HTML; duże liczby kryją się w jQuery i zasobach wtyczek.
Jak sprawdzić kompatybilność po odchudzeniu WordPressa
Po każdej zmianie sprawdź trzy obszary:
- Frontend: układ, menu, slidery i formularze, a w konsoli przeglądarki błędy JavaScript.
- Panel admina: edytor wpisów, bibliotekę mediów, ekran widżetów i każdą stronę ustawień wtyczek, z której korzystasz.
- Po wylogowaniu: formularze kontaktowe, komentarze (jeśli je zostawiasz), wyszukiwanie i wszystko, co pobiera dane bez przeładowania strony.
Na czas testów włącz logowanie, a wyświetlanie błędów zostaw wyłączone, żeby odwiedzający nie widzieli komunikatów:
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );| Problem | Prawdopodobna przyczyna | Rozwiązanie |
|---|---|---|
| Błędy jQuery w konsoli | Usunięty jQuery Migrate | Przywróć Migrate albo zaktualizuj wtyczkę, która wywołuje przestarzałe API |
| Bloki wyglądają na nieostylowane | Usunięta biblioteka bloków albo style globalne | Przywróć style na stronach z treścią blokową |
| Pętla zapytania albo nawigacja nic nie wyświetla | do_blocks usunięte z the_content | Usuń tę linię |
| Formularze nie wysyłają się po wylogowaniu | REST API ograniczone do zalogowanych | Dopuść trasę wtyczki albo zrezygnuj z ograniczenia |
| Aplikacja mobilna albo zdalne publikowanie nie działa | Zablokowany XML-RPC | Włącz go ponownie albo przestaw klienta na hasła aplikacji i REST |
| Osadzenia Twoich wpisów na innych stronach przestają działać | Usunięta strona dostawcy oEmbed | To oczekiwany efekt; przywróć, jeśli potrzebują tego partnerzy |
Jak spakować kod debloat jako mu-plugin
Kod w functions.php znika przy zmianie motywu. Wtyczka must-use w wp-content/mu-plugins/ ładuje się przy każdym żądaniu, nie da się jej dezaktywować z panelu admina i uniezależnia ustawienia debloat od motywu. WordPress ładuje pliki PHP umieszczone bezpośrednio w tym folderze, a nie pliki z podfolderów, więc trzymaj jeden plik albo dodaj mały loader:
wp-content/
mu-plugins/
debloat-loader.php
debloat/
emoji.php
head-cleanup.php
xmlrpc.php
heartbeat.php<?php
/**
* Plugin Name: Debloat
* Description: Usuwa funkcje frontendu, których ta strona nie używa.
*/
defined( 'ABSPATH' ) || exit;
foreach ( array( 'emoji', 'head-cleanup', 'xmlrpc', 'heartbeat' ) as $module ) {
$file = __DIR__ . '/debloat/' . $module . '.php';
if ( is_readable( $file ) ) {
require_once $file;
}
}Każdy moduł zawiera fragmenty kodu z powyższych sekcji. Dwie rzeczy trzymaj poza wtyczką debloat. Wyłączenie automatycznych aktualizacji wtyczek i motywów przez auto_update_plugin i auto_update_theme to polityka utrzymania, a nie ustawienie wydajności, i razem z aktualizacjami funkcji wyłącza też poprawki bezpieczeństwa. A limity rewizji i autozapisu to stałe, więc ich miejsce jest w wp-config.php, a nie we wtyczce ładowanej po tym, jak te stałe zostały już odczytane.
Podsumowanie
Podejście WordPressa “wszystko w zestawie” jest świetne dla początkujących, ale deweloperzy szukający maksymalnej wydajności muszą przyciąć zbędny kod. Techniki w tym przewodniku, zainspirowane doskonałym skryptem optymalizacji Terence’a Edena, pomogą Ci osiągnąć lżejszą, szybszą instalację WordPressa.
Kilka klasycznych fragmentów kodu nic już nie robi w WordPressie 7.1 (manifest WLW, linki do sąsiednich wpisów, filtry SVG, filtr autosave_interval), a niektóre szkodzą (usunięcie do_blocks, usunięcie oczyszczania oEmbed, całkowita blokada REST API). Każda linia kodu, którą usuniesz, to o jeden potencjalny punkt awarii mniej, więc sprawdź każdy fragment pod kątem wersji, której używasz, zanim trafi na produkcję. Jeśli chcesz poprawić Core Web Vitals i realną szybkość strony, zobacz nasze usługi optymalizacji szybkości WordPress.







