WordPress Debloat ohne unnötigen Ballast

WordPress Debloat ohne unnötigen Ballast

Zuletzt überprüft: 12. Oktober 2026
25 Min. Lesezeit
Leitfaden
500+ WP-Projekte

WordPress ist ein Kraftpaket, aber die Standardeinstellungen nach dem Prinzip “eine Lösung für alle” bedeuten, dass es oft mit Ballast ausgeliefert wird, den die meisten modernen Projekte nicht brauchen. Über die Jahre habe ich ein spezifisches Set an Snippets verfeinert, um das System zu entschlacken, ohne das Kernerlebnis zu beeinträchtigen.

Dieser Guide ist mehr als nur eine Liste von Dingen, die man löschen kann; es ist ein strategischer Ansatz für Performance. Inspiriert von Terence Edens exzellenter Liste, ergänzt um meine eigenen, im Produktivbetrieb erprobten Lösungen. Jeder Hook-Name unten wurde gegen den Quellcode von WordPress 7.1.3 geprüft (laut Versionsabfrage bei api.wordpress.org die aktuelle Version am 12. Oktober 2026), und Snippets, die sich als veraltet, falsch oder schädlich erwiesen haben, sind entsprechend markiert. Wenn Sie die Arbeit lieber abgeben möchten, finden Sie hier unsere WordPress-Entwicklung als Dienstleistung.

#Warum WordPress entschlacken

Warum sollte man sich über ein paar kleine Skripte Gedanken machen? Weil sie sich summieren. Jede unnötige Zeile ist ein potenzieller Konflikt, eine winzige Rendering-Verzögerung oder ein verschwendetes Byte.

Unsere Ziele:

  • DOM-Größe, Entfernen nicht genutzter Inline-Styles.
  • HTTP-Overhead, Dequeuing von Skripten, die nicht geladen werden sollten.
  • Sicherheitsfläche, Deaktivierung veralteter Protokolle wie XML-RPC.
  • Core Web Vitals, Direkter Einfluss auf LCP und CLS durch Entfernen renderblockierender Elemente.

[!IMPORTANT] Vorsicht geboten: Nicht jeder “Ballast” ist nutzlos. Wenn Sie auf das spezifische Styling des Classic Editors angewiesen sind oder die eingebauten Emojis für ältere Browser brauchen, sind manche dieser Fixes eventuell nicht für Sie geeignet. Testen Sie Änderungen zuerst in einer Staging-Umgebung.

#Wie man ein komplettes Debloat-Skript für WordPress einsetzt

Fügen Sie Folgendes zur functions.php-Datei Ihres Themes hinzu, oder besser in ein MU-Plugin (siehe letzter Abschnitt), damit der Code einen Theme-Wechsel übersteht. Jeder Abschnitt ist mit Erklärungen und Quelllinks kommentiert.

#1. Classic Theme Styles entfernen

WordPress fügt “classic-theme-styles” bei Themes ohne theme.json-Datei hinzu. Der Core lädt das Stylesheet nur, wenn wp_theme_has_theme_json() false zurückgibt; ein Block-Theme oder ein klassisches Theme mit theme.json lädt es also nie. Wenn Ihres es lädt, entfernen Sie es:

//  Obligatorisches Classic Theme entfernen.
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. Emoji-Unterstützung entfernen

WordPress gibt ein kleines Erkennungsskript aus. Nur wenn der Browser aktuelle Emojis nicht darstellen kann, lädt es ein größeres Skript nach, das Emoji-Zeichen durch SVG-Bilder ersetzt. Wenn Ihr Publikum aktuelle Browser nutzt, ist das unnötig:

//  WP Emoji entfernen.
//  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"              );
//  Die SVG-Basis-URL in den Emoji-Einstellungen leeren.
add_filter( "emoji_svg_url", "__return_false" );

//  Emoji-Ersetzung mit Bildern in RSS / Atom Feeds stoppen
//  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. Automatische Textformatierung deaktivieren

WordPress “texturisiert” Ihren Inhalt: gerade Anführungszeichen werden typografisch, ASCII -- / --- werden zu Halbgeviert- bzw. Geviertstrich (U+2013 / U+2014). Das zerlegt Code-Beispiele und widerspricht einer ASCII-Bindestrich-Policy (- oder --, keine Langstrich-Glyphen in der Quelle). Auf technischem Content abschalten:

//  Automatische Formatierung entfernen.
//  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" );

//  Weitere Formatierungsfilter.
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 );
    //  NUR für Classic-Editor-Seiten: Diese Zeile stoppt jedes Block-Rendering.
    remove_filter( "the_content",  "do_blocks", 9 );
}, 11);

Hinweis: Der Filter capital_P_dangit ist die Art, wie WordPress Wordpress (mit kleinem p) automatisch in WordPress korrigiert. Er ist aggressiv und manchmal unerwünscht.

[!WARNING] Wenn Sie do_blocks aus the_content entfernen, wird Block-Markup nicht mehr geparst. Dynamische Blöcke (Query Loop, neueste Beiträge, Navigation) geben nichts mehr aus. Behalten Sie diese Zeile nur auf einer Seite, deren Beiträge ausnahmslos im Classic Editor geschrieben wurden.

#4. Gutenberg-Styles und -Skripte entfernen

Wenn Sie ein benutzerdefiniertes Theme verwenden und nicht auf die Frontend-Styles von Gutenberg angewiesen sind, entfernen Sie sie. Auf einem Block-Theme lassen Sie das bleiben: Die globalen Styles tragen das gesamte Design aus theme.json.

//  Gutenberg Styles entfernen.
//  https://wordpress.org/support/topic/how-to-disable-inline-styling-style-idglobal-styles-inline-css/
remove_action( "wp_enqueue_scripts", "wp_enqueue_global_styles" );
//  Bei klassischen Themes hängt der Core es zusätzlich mit Priorität 1 an wp_footer.
remove_action( "wp_footer", "wp_enqueue_global_styles", 1 );

//  Gutenberg Editing Widgets entfernen.
//  Von https://wordpress.org/plugins/classic-widgets/
//  Verhindert, dass der Block-Editor im Gutenberg-Plugin die Widgets verwaltet.
add_filter( "gutenberg_use_widgets_block_editor", "__return_false" );
//  Verhindert, dass der Block-Editor die Widgets verwaltet.
add_filter( "use_widgets_block_editor", "__return_false" );

//  Gutenberg Block Library CSS vom Frontend-Laden entfernen.
//  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. Header-Meta-Tags entfernen

Bereinigen Sie Ihren <head>-Abschnitt, indem Sie unnötige Meta-Tags entfernen:

//  Shortlink entfernen.
//  https://stackoverflow.com/questions/42444063/disable-wordpress-short-links
remove_action( "wp_head", "wp_shortlink_wp_head" );

//  RSD entfernen.
//  https://wpengineer.com/1438/wordpress-header/
remove_action( "wp_head", "rsd_link" );

//  Extra Feed-Links entfernen.
//  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" );

//  api.w.org Link entfernen.
//  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. Bildverbesserungen entfernen

WordPress fügt Bildern die Attribute srcset, sizes, loading, decoding und fetchpriority hinzu. Wenn Sie diese selbst handhaben, entfernen Sie sie, aber lesen Sie vorher den Bildabschnitt weiter unten, denn diese Attribute schützen LCP und CLS:

//  WordPress erzwungene Bildgröße entfernen
//  https://core.trac.wordpress.org/ticket/62413#comment:40
add_filter( "wp_img_tag_add_auto_sizes", "__return_false" );

//  <img> Verbesserungen entfernen
//  https://developer.wordpress.org/reference/functions/wp_filter_content_tags/
remove_filter( "the_content",  "wp_filter_content_tags", 12 );

//  Umschreiben von http:// URLs für die Hauptdomain stoppen.
//  https://developer.wordpress.org/reference/hooks/wp_should_replace_insecure_home_url/
remove_filter( "the_content", "wp_replace_insecure_home_url", 10 );

//  Attachment-Stuff entfernen
//  https://developer.wordpress.org/news/2024/01/building-dynamic-block-based-attachment-templates-in-themes/
remove_filter( "the_content", "prepend_attachment" );

//  Block-Filter entfernen
remove_filter( "the_content", "apply_block_hooks_to_content_from_post_object", 8 );

#7. Browser-Check und andere Admin-Funktionen entfernen

//  Browser-Check aus dem Admin-Dashboard entfernen.
//  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" );
}

//  Hovercards auf Kommentar-Links im Admin-Bereich entfernen.
//  https://wordpress.org/support/topic/how-to-disable-mshots-service/#post-12946617
add_filter( "akismet_enable_mshots", "__return_false" );

#Was man in WordPress zusätzlich entfernen sollte

Über die obigen Techniken hinaus sind hier meine eigenen Lösungen für weitere Optimierung:

#8. XML-RPC deaktivieren

Wenn Sie keine externen Apps zum Posten auf WordPress verwenden, schalten Sie die XML-RPC-Methoden ab, die eine Anmeldung erfordern, und gleich mit ihnen die Pingback-Methoden. Der Filter xmlrpc_enabled allein schaltet den Endpunkt nicht ab (Details weiter unten):

// XML-RPC-Methoden deaktivieren, die eine Authentifizierung erfordern
add_filter( 'xmlrpc_enabled', '__return_false' );

// Pingback-Methoden entfernen, die sonst offen bleiben
add_filter( 'xmlrpc_methods', function( $methods ) {
    unset( $methods['pingback.ping'], $methods['pingback.extensions.getPingbacks'] );
    return $methods;
} );

// XML-RPC-Link aus dem Head entfernen
remove_action( 'wp_head', 'rsd_link' );

#9. jQuery Migrate entfernen

Moderne WordPress-Themes und -Plugins benötigen selten jQuery Migrate. Wenn Ihre Website ohne es funktioniert, entfernen Sie es:

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. oEmbed deaktivieren

Wenn keine andere Website Ihre Beiträge einbetten muss, schalten Sie die Anbieterseite von oEmbed ab. Einbettungen von YouTube und anderen registrierten Anbietern in Ihren eigenen Beiträgen funktionieren weiter, weil WordPress die automatische Erkennung nur für URLs ausführt, die nicht auf seiner eingebauten Anbieterliste stehen:

// oEmbed-Discovery-Links entfernen
remove_action( 'wp_head', 'wp_oembed_add_discovery_links' );
remove_action( 'wp_head', 'wp_oembed_add_host_js' );

// oEmbed REST API Endpoint entfernen
remove_action( 'rest_api_init', 'wp_oembed_register_route' );

// oEmbed Auto-Discovery deaktivieren
add_filter( 'embed_oembed_discover', '__return_false' );

#11. JavaScript-Laden verzögern

Fügen Sie defer zu nicht-kritischen Skripten für bessere Performance hinzu. Der Filter unten ist der alte Weg und ignoriert die Abhängigkeitsregeln, die der Core seit WordPress 6.3 anwendet; der Abschnitt zur Ladestrategie weiter unten zeigt den unterstützten Weg:

function add_defer_attribute( $tag, $handle ) {
    // Skripte, die NICHT verzögert werden sollten
    $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 );

#Wie man die Wirkung von WordPress Debloat misst

Nachdem Sie diese Änderungen implementiert haben, testen Sie Ihre Website mit:

  1. Google PageSpeed Insights, Überprüfen Sie Ihre Core Web Vitals
  2. GTmetrix, Detaillierte Wasserfall-Analyse
  3. WebPageTest, Mehrere Teststandorte und Verbindungsgeschwindigkeiten

Sie sollten sehen:

  • Reduzierte Seitengröße (weniger CSS/JS-Bytes)
  • Weniger HTTP-Anfragen
  • Besserer Largest Contentful Paint (LCP), wenn ein entferntes Asset renderblockierend war

Die Serverantwortzeit (TTFB) bewegt sich kaum, weil keines dieser Snippets ändert, wie PHP die Seite aufbaut. Die TTFB verbessert erst eine Caching-Schicht.

#Was eine Standardinstallation von WordPress 7.1 lädt

Bevor Sie etwas entfernen, hilft es zu wissen, was jede Funktion kostet. Die Größen unten wurden an den Dateien im offiziellen wordpress-7.1.3.zip gemessen: Rohgröße auf der Festplatte und Größe nach gzip auf Stufe 9, was nahe an dem liegt, was ein Server tatsächlich überträgt.

AssetDateiRohGzipWann es lädt
Emoji-Loader (inline, Footer)wp-emoji-loader.min.js2.977 B1.290 BAuf jeder Frontend-Seite
Emoji-Ersetzungsskriptwp-emoji-release.min.js22.752 B5.310 BNur wenn der Browser den Emoji-Test nicht besteht
Classic Theme Stylesclassic-themes.min.css291 B233 BThemes ohne theme.json
Kombinierte Block Libraryblock-library/style.min.css140.829 B18.938 BNur wenn Block-Styles bei Bedarf deaktiviert sind
Theme-Styles der Block Libraryblock-library/theme.min.css2.752 B751 BThemes, die wp-block-styles deklarieren, bei deaktiviertem Laden nach Bedarf
jQueryjquery.min.js87.553 B30.356 BWenn das Theme oder ein Plugin es einreiht
jQuery Migratejquery-migrate.min.js13.577 B4.891 BZusammen mit dem Handle jquery
Dashiconsdashicons.min.css59.004 B35.693 BAdmin-Leiste für angemeldete Nutzer oder ein Plugin
Host-Skript für Beitrags-Embedswp-embed.min.js1.251 B710 BNur auf Seiten, die einen WordPress-Beitrag einbetten
Heartbeatheartbeat.min.js5.947 B2.058 BAdmin-Bildschirme, im Frontend nur auf Anforderung eines Plugins
Kommentarantwortcomment-reply.min.js2.950 B1.371 BWenn das Theme oder der Kommentar-Block es einreiht

Zwei Zahlen fallen auf. jQuery plus Migrate ist meist das Schwerste, was ein klassisches Theme ausliefert, deshalb spart der Verzicht auf jQuery im eigenen Theme-Code mehr als alle Anpassungen an Head-Tags zusammen. Und das 140 KB große Stylesheet der Block Library wird bei einer Standardinstallation nicht mehr komplett geladen: Block-Themes laden seit WordPress 5.9 nur die Styles der Blöcke, die tatsächlich auf der Seite stehen, und seit 6.9 aktiviert der Core dasselbe Laden nach Bedarf über wp_load_classic_theme_block_styles_on_demand() auch für klassische Themes, solange der Ausgabepuffer für Templates aktiv ist. Ein Theme schaltet das ab, indem es aus den Filtern should_load_separate_core_block_assets und should_load_block_assets_on_demand false zurückgibt.

Was eine bestimmte Seite wirklich lädt, zeigt der Browser. Öffnen Sie in den Chrome DevTools den Tab “Network”, laden Sie die Seite bei deaktiviertem Cache neu, filtern Sie nach Ihrer eigenen Domain und sortieren Sie nach Größe. Lighthouse im selben DevTools-Panel listet ungenutztes CSS und JavaScript pro Datei auf. WP-CLI hilft hier nicht: Ein Aufruf von wp eval rendert nie ein Template, daher sind die ausgegebenen Skript- und Style-Warteschlangen leer. Ein protokollierender Footer-Hook funktioniert dagegen:

// Jedes eingereihte Handle bei Frontend-Seitenaufrufen protokollieren (nur 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 );

#Welche WordPress-Funktionen man deaktivieren kann, Funktion für Funktion

Das Skript oben ist die Kurzfassung. Im Folgenden bekommt jede Funktion den Kontext, den Sie für die Entscheidung brauchen, ob sie auf Ihre Seite gehört.

#Was Classic Theme Styles sind und was sie kosten

WordPress 6.1 hat ein kleines Stylesheet eingeführt, das klassischen Themes sinnvolle Standards für Block-Markup gibt, etwa Abstände bei Button- und Datei-Blöcken. Es wiegt 291 Bytes und wird von wp_enqueue_classic_theme_styles() nur eingereiht, wenn das aktive Theme keine theme.json hat. Entfernen Sie es bei einem klassischen Theme mit eigenem Block-CSS. Behalten Sie es bei klassischen Themes, die darauf angewiesen sind, dass Core-Block-Markup ohne Zusatzaufwand richtig aussieht, und kümmern Sie sich bei Block-Themes gar nicht darum, denn dort lädt es nie.

#Warum WordPress ein Emoji-Skript lädt

Die Emoji-Funktion erledigt zwei Aufgaben: Sie prüft, ob der Browser aktuelle Emojis zeichnen kann, und falls nicht, lädt sie wp-emoji-release.min.js, das die Zeichen durch Bilder von s.w.org ersetzt. In WordPress 7.1.3 ist dieser Test ein Inline-Skript mit type="module" im Footer, blockiert das Rendering also nicht mehr, und die Ergebnisse werden in sessionStorage zwischengespeichert. Dazu kommt ein kleines Inline-Stylesheet für img.emoji. Das Entfernen der Aktion wp_print_styles funktioniert weiterhin: wp_enqueue_emoji_styles() prüft, ob diese Aktion vorhanden ist, und lässt das Inline-CSS weg, wenn sie fehlt.

Der Filter emoji_svg_url setzt inzwischen nur noch die SVG-Basis-URL in den Emoji-Einstellungen. Ältere Anleitungen nutzten ihn, um einen DNS-Prefetch zu s.w.org zu entfernen; wp_resource_hints() fügt diesen Hinweis in 7.1.3 nicht mehr hinzu, die Zeile schadet also nicht, spart aber auch keine DNS-Abfrage mehr. Behalten Sie die Emoji-Unterstützung, wenn Besucher in Kommentaren oder Foren von alten Geräten aus schreiben, deren Schriften keine aktuellen Emojis enthalten. Die vollständige Variante deckt auch E-Mails und den Classic Editor ab:

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

#Was wptexturize an Ihren Inhalten ändert

wptexturize() macht aus geraden Anführungszeichen typografische, aus -- und --- Halbgeviert- und Geviertstriche und aus drei Punkten ein Auslassungszeichen. Bei technischen Inhalten beschädigt das Shortcodes sowie HTML- und PHP-Fragmente, die Leser kopieren. Die ganze Funktion lässt sich mit einem einzigen Filter abschalten, statt sie aus jedem Hook einzeln zu entfernen:

add_filter( 'run_wptexturize', '__return_false' );

Behalten Sie sie nur auf redaktionellen Seiten, die typografische Anführungszeichen wollen und nie Code veröffentlichen.

#Was der Filter capital_P_dangit macht

capital_P_dangit() ersetzt Wordpress durch WordPress. In Titeln ersetzt er jedes Vorkommen, in Inhalten und Kommentaren nur nach einem Leerzeichen, einem Anführungszeichen, > oder (. URLs fasst er nicht an, weil ein Schrägstrich vor dem Wort nicht passt. Das eigentliche Risiko ist Code: Ein Beispiel, das Wordpress nach einem Leerzeichen enthält, wird stillschweigend verändert.

#Welche Styles und Skripte der Block-Editor hinzufügt

Im Frontend steuert der Block-Editor wp-block-library (das Block-CSS), wp-block-library-theme (meinungsstarke Theme-Styles) und die aus theme.json erzeugten Inline-global-styles bei. wp-components gehört zu den Editor-Bildschirmen, daher bewirkt ein Dequeue im Frontend nichts. Ältere Snippets entfernen außerdem wp_global_styles_render_svg_filters aus wp_body_open; diese Funktion wurde in 6.3.0 als veraltet markiert und hängt an keinem Hook mehr. Entfernen Sie Block-CSS nur auf Seiten, die im Frontend keine Blöcke rendern. Auf einem Block-Theme nimmt das Entfernen der globalen Styles dem Theme sein Design.

#Welche Head-Tags WordPress hinzufügt und welche man entfernen sollte

Ein standardmäßiges wp_head gibt in 7.1.3 unter anderem Folgendes aus:

<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" />
TagRisikoEmpfehlung
generatorGering, die Version steht ohnehin als ?ver= an Core-AssetsNach Belieben entfernen, es verbirgt wenig
shortlinkKeinesEntfernen
RSD (EditURI)Verweist Clients auf xmlrpc.phpZusammen mit XML-RPC entfernen
REST-API-LinksGeringBehalten, wenn etwas Ihre API automatisch erkennt

Zwei Entfernungen, die in vielen Anleitungen noch auftauchen, bewirken in aktuellen Versionen nichts: wlwmanifest_link wurde in 6.3.0 als veraltet markiert und wird nicht mehr ausgegeben, und adjacent_posts_rel_link_wp_head nutzt der Core seit 5.6.0 nicht mehr. Eine aktuelle Bereinigung ist kürzer:

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

#Was WordPress zu Bildern hinzufügt

wp_filter_content_tags() ergänzt srcset und sizes, width und height, wo sie fehlen, loading="lazy" bei Bildern unterhalb des sichtbaren Bereichs sowie decoding="async" und fetchpriority="high" beim voraussichtlichen LCP-Bild. Der Filter wp_img_tag_add_auto_sizes kam mit 6.7.0, nicht früher. Das Entfernen dieser Funktionen verschlechtert meist CLS und LCP, also das Gegenteil des Ziels; tun Sie es nur, wenn ein CDN oder Ihr eigenes Markup alle diese Attribute setzt. Um nur das Lazy Loading abzuschalten:

add_filter( 'wp_lazy_loading_enabled', '__return_false' );

#Wie der Browser-Check im Dashboard funktioniert

wp_check_browser_version() fragt bei api.wordpress.org nach, ob der Browser des Admins veraltet ist, und speichert die Antwort eine Woche lang als Site-Transient, dessen Schlüssel ein MD5 des User-Agents ist. Das ist eine externe Anfrage pro Browser und Woche, nicht pro Aufruf einer Admin-Seite. Die PHP-Versionsprüfung arbeitet genauso, aber der Transient-Schlüssel ist php_check_ plus ein MD5 von PHP_VERSION, nicht des User-Agents; Snippets, die pre_site_transient_phpcompat_ filtern, bewirken deshalb nichts:

add_filter( 'pre_site_transient_php_check_' . md5( PHP_VERSION ), '__return_null' );

Behalten Sie diese Prüfung, solange niemand sonst die PHP-Version überwacht, denn sie ist die Warnung, die Seitenbetreibern sagt, dass ihre PHP-Version nicht mehr unterstützt wird.

#Was der Filter xmlrpc_enabled wirklich abschaltet

XML-RPC ist das Protokoll für entferntes Veröffentlichen hinter älteren mobilen Clients, Desktop-Editoren und Pingbacks. Der Filtername klingt nach einem Hauptschalter, doch der Quellcode von WordPress 7.1.3 sagt im Docblock der Methode wp_xmlrpc_server::set_is_enabled() etwas anderes:

“Entgegen seinem Namen steuert dieser Filter nicht, ob XML-RPC vollständig aktiviert ist, sondern nur, ob XML-RPC-Methoden aktiviert sind, die eine Authentifizierung erfordern, etwa zum Veröffentlichen.”

Quelle: Docblock von wp_xmlrpc_server::set_is_enabled() (eigene Übersetzung).

Nach add_filter( 'xmlrpc_enabled', '__return_false' ) antwortet xmlrpc.php also weiterhin, und pingback.ping funktioniert nach wie vor. Pingbacks sind der Teil, der für reflektierten Traffic missbraucht wird, und mit system.multicall kann eine einzige Anfrage viele Anmeldeversuche transportieren; das stoppt der Filter tatsächlich, weil diese Methoden eine Authentifizierung brauchen. Das Snippet in Abschnitt 8 entfernt zusätzlich die Pingback-Methoden über xmlrpc_methods. Der HTTP-Header X-Pingback wird nur bei einzelnen Beiträgen gesendet, die Pings erlauben, daher entfernt das Schließen der Pings (siehe folgende Abschnitte) auch ihn. Um den Endpunkt vollständig abzuschalten, sperren Sie xmlrpc.php auf Webserver-Ebene; prüfen Sie danach jedes Plugin und jede App, die aus der Ferne veröffentlicht, denn sie funktioniert dann nicht mehr.

#Wofür jQuery Migrate da ist

jQuery Migrate stellt jQuery-APIs wieder her, die in späteren jQuery-Versionen entfernt wurden, und protokolliert Warnungen, wenn alter Code sie aufruft. WordPress registriert das Handle jquery als Alias für jquery-core plus jquery-migrate; deshalb bearbeitet das Snippet in Abschnitt 9 die Abhängigkeitsliste, statt eine Datei aus der Warteschlange zu nehmen. Bevor Sie es auf der Produktivseite entfernen, laden Sie die Seite auf Staging mit define( 'SCRIPT_DEBUG', true );. Damit liefert WordPress das nicht minifizierte jquery-migrate.js aus, das der Core zum Debuggen bereithält, und Sie können in der Konsole nach JQMIGRATE-Warnungen zu veralteten Aufrufen suchen. Rufen Sie im Frontend nicht wp_deregister_script( 'jquery-migrate' ) auf; jedes Plugin, das jquery-migrate als Abhängigkeit deklariert, verlöre dann sein eigenes Skript, weil WordPress ein Skript mit fehlender Abhängigkeit nicht ausgibt.

#Wie oEmbed in WordPress funktioniert

oEmbed hat zwei Seiten. Als Konsument macht WordPress aus einem eingefügten YouTube- oder Vimeo-Link einen Player, gestützt auf seine eingebaute Anbieterliste; das funktioniert auch nach dem Snippet in Abschnitt 10 weiter. Als Anbieter gibt Ihre Seite Discovery-Links aus und stellt /wp-json/oembed/1.0/embed bereit, damit andere WordPress-Seiten Ihre Beiträge einbetten können. Das Skript wp-embed (710 Bytes gzip-komprimiert) wird nur auf Seiten eingereiht, die eine solche Beitragseinbettung enthalten. Zwei Zeilen aus älterem Code zum Abschalten von Embeds sollten Sie nicht übernehmen: Das Entfernen von wp_filter_oembed_result aus oembed_dataparse schaltet die Bereinigung ab, die der Core auf HTML von Anbietern außerhalb der vertrauenswürdigen Liste anwendet, und das TinyMCE-Plugin wpembed gibt es nicht mehr, daher bewirkt das Herausfiltern aus tiny_mce_plugins nichts.

#Wie man die REST API einschränkt, ohne den Block-Editor zu beschädigen

Die REST API antwortet unter /wp-json/ und wird vom Block-Editor, vom Site-Editor und von vielen Plugins genutzt. Das offizielle REST API Handbook ist in seinen häufig gestellten Fragen eindeutig:

“Sie sollten die REST API nicht deaktivieren; damit legen Sie Funktionen im WordPress-Admin lahm, die darauf angewiesen sind, dass die API aktiv ist.”

Quelle: Häufig gestellte Fragen im REST API Handbook (eigene Übersetzung).

Stattdessen empfiehlt das Handbook, über den Filter rest_authentication_errors eine Authentifizierung zu verlangen. Angemeldete Redakteure arbeiten weiter, anonyme Anfragen erhalten einen 401:

add_filter( 'rest_authentication_errors', function( $result ) {
    // Wenn bereits eine vorherige Authentifizierungsprüfung lief,
    // dieses Ergebnis unverändert weitergeben.
    if ( true === $result || is_wp_error( $result ) ) {
        return $result;
    }

    // Bisher wurde keine Authentifizierung durchgeführt.
    // Fehler zurückgeben, wenn der Nutzer nicht angemeldet ist.
    if ( ! is_user_logged_in() ) {
        return new WP_Error(
            'rest_not_logged_in',
            __( 'You are not currently logged in.' ),
            array( 'status' => 401 )
        );
    }

    // Unsere eigene Authentifizierungsprüfung soll keinen Einfluss
    // auf angemeldete Anfragen haben
    return $result;
});

Das legt für anonyme Besucher jede Frontend-Funktion lahm, die /wp-json/ aufruft: Formulare, die über REST absenden, Such- oder Filter-Widgets, die JSON abrufen, ein Headless-Frontend sowie andere Seiten, die Ihre Beiträge über den oEmbed-Endpunkt einbetten. Eine engere Variante ist das Ausblenden einzelner Routen mit dem Filter rest_endpoints, zum Beispiel des Users-Endpunkts, der die Slugs der Autoren auflistet. Testen Sie nach der Änderung jedes Formular und jeden interaktiven Block im abgemeldeten Zustand.

#Wie man die WordPress Heartbeat API anpasst

Heartbeat ist eine Abfrageschleife in heartbeat.js, die in einem festen Intervall eine Anfrage an admin-ajax.php sendet. Sie trägt die Beitragssperre (den Hinweis, dass gerade jemand anderes bearbeitet), Autosave-Daten im Classic Editor und die Prüfung auf abgelaufene Anmeldungen, die den Dialog zur erneuten Anmeldung anzeigt. In WordPress 7.1.3 beträgt das Standard-mainInterval 60 Sekunden, der erlaubte Bereich liegt bei 1 bis 3.600 Sekunden, die Schleife kann vorübergehend auf 5 Sekunden beschleunigen und verlangsamt sich auf 120 Sekunden, wenn der Tab im Hintergrund ist. Das Intervall auf 60 zu setzen ändert daher nichts; ein langsameres Intervall ist der sinnvolle Hebel bei großen Admin-Teams oder schwachem Hosting:

add_filter( 'heartbeat_settings', function ( $settings ) {
    $settings['interval'] = 120;
    return $settings;
} );

Im Frontend lädt der Core Heartbeat für Besucher nicht; es erscheint nur, wenn ein Plugin es einreiht. Dort können Sie es gefahrlos abmelden, sofern Sie danach die Funktion dieses Plugins prüfen. Melden Sie es im Admin nie ab: Beitragssperren und Warnungen zum Sitzungsablauf hängen davon ab.

#Wie man Beitragsrevisionen mit WP_POST_REVISIONS begrenzt

Revisionen bremsen das Frontend nicht, weil sie auf öffentlichen Seiten nie abgefragt werden. Sie vergrößern die Tabelle wp_posts und verlangsamen Backups und Exporte. Gesteuert wird das über eine Konstante in wp-config.php, die wp_revisions_to_keep() ausliest:

define( 'WP_POST_REVISIONS', 10 );   // die 10 neuesten Revisionen pro Beitrag behalten
// define( 'WP_POST_REVISIONS', false ); // gar keine Revisionen

Der Standardwert ist true, also unbegrenzt. false oder 0 schaltet Revisionen ab; eine positive Zahl behält entsprechend viele. Der Filter wp_revisions_to_keep überschreibt die Konstante, und seit WordPress 5.8 setzt der Filter wp_{$post_type}_revisions_to_keep ein Limit pro Beitragstyp. Das Limit greift beim nächsten Speichern eines Beitrags, überzählige Revisionen bleiben bis dahin bestehen. Wer Revisionen abschaltet, nimmt Redakteuren das Sicherheitsnetz, daher ist eine kleine Zahl meist der bessere Kompromiss.

Autosave hat eine eigene Konstante. Einen Filter autosave_interval gibt es im Core nicht, Code, der einen solchen hinzufügt, bewirkt also nichts; setzen Sie das Intervall stattdessen in Sekunden in wp-config.php:

define( 'AUTOSAVE_INTERVAL', 120 ); // Standard ist 60

#Wie man Kommentare auf der ganzen Website deaktiviert

Eine Website ohne Kommentare rendert trotzdem Kommentarformulare, wo das Theme sie anfordert, behält den Link zum Kommentar-Feed im Head und behält die Pingback-Mechanik. Kommentare und Pings über Filter zu schließen deckt jeden Beitragstyp ab, ohne Beiträge in der Datenbank zu bearbeiten:

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

Das Schließen der Pings entfernt auch den Header X-Pingback, weil der Core ihn nur sendet, wenn pings_open() true ist. Bestehende Kommentare bleiben in der Datenbank und können weiterhin erscheinen, wenn das Theme sie unabhängig von comments_open() ausgibt. Das Skript comment-reply lohnt keinen eigenen Aufwand: Der Core registriert es mit der Strategie async und niedriger Abrufpriorität, und es hat gzip-komprimiert 1.371 Bytes.

#Wie man Skripte mit der Loading Strategy API verzögert

Seit WordPress 6.3 akzeptieren wp_register_script() und wp_enqueue_script() ein Argument strategy mit den Werten defer oder async. Der Core prüft dann den Abhängigkeitsbaum, bevor er das Attribut ausgibt: Ein Skript, an das in der Position after ein Inline-Skript angehängt ist, wird nie verzögert, und ein defer-Skript fällt auf blockierendes Laden zurück, wenn ein abhängiges Skript es vorher ausgeführt braucht. Diese Logik steckt in WP_Scripts::get_eligible_loading_strategy(). Der Filter script_loader_tag aus Abschnitt 11 übergeht all das, und genau so landen verzögerte Skripte hinter Inline-Code, der sie aufruft.

// Ihr eigenes Skript.
wp_enqueue_script( 'site-main', get_theme_file_uri( 'js/main.js' ), array(), '1.4.0', array(
    'in_footer' => true,
    'strategy'  => 'defer',
) );

// Ein von einem Plugin registriertes Skript.
add_action( 'wp_enqueue_scripts', function () {
    wp_script_add_data( 'some-plugin-handle', 'strategy', 'defer' );
}, 20 );

Sehen Sie sich danach den Seitenquelltext an: Hat der Core entschieden, dass ein Handle nicht verzögert werden kann, fehlt das Attribut einfach.

#Wie man die WordPress-Performance vor und nach dem Entschlacken testet

Ein einzelner Lauf von PageSpeed Insights ist keine Messung, weil Laborwerte zwischen den Läufen schwanken. Ein Ablauf, der vergleichbare Zahlen liefert:

  1. Vorbereiten: Seiten-Cache leeren, für beide Durchgänge dasselbe Hosting und dieselben URLs verwenden und die Versionen von WordPress, Theme und Plugins notieren.
  2. Ausgangswert: PageSpeed Insights oder Lighthouse dreimal pro URL laufen lassen und den Median behalten, dann übertragene Bytes und Anzahl der Anfragen aus dem Network-Tab der DevTools bei deaktiviertem Cache notieren.
  3. Den Debloat-Code auf Staging einspielen und den Cache erneut leeren.
  4. Dieselben Läufe auf denselben URLs wiederholen.
  5. Übertragene Bytes, Anzahl der Anfragen, LCP und CLS vergleichen. Die Felddaten im Bereich Chrome UX Report von PageSpeed Insights aktualisieren sich über 28 Tage, prüfen Sie sie daher einen Monat später noch einmal.

Die Größentabelle oben nennt die Obergrenze. Bei einem klassischen Theme, das Block-Styles bereits nach Bedarf lädt, sparen Emoji, Classic Theme Styles und die Head-Tags zusammen ein paar Kilobyte und einige Zeilen HTML; die großen Zahlen stecken in jQuery und in Plugin-Assets.

#Wie man nach dem Entschlacken die Kompatibilität prüft

Prüfen Sie nach jeder Änderung drei Bereiche:

  1. Frontend: Layout, Menüs, Slider und Formulare sowie die Browserkonsole auf JavaScript-Fehler.
  2. Admin: den Beitragseditor, die Mediathek, den Widget-Bildschirm und jede Plugin-Einstellungsseite, die Sie nutzen.
  3. Abgemeldet: Kontaktformulare, Kommentare (falls Sie sie behalten), die Suche und alles, was Daten ohne Neuladen der Seite holt.

Schalten Sie während der Tests die Protokollierung ein und die Anzeige aus, damit Besucher keine Hinweise sehen:

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
ProblemWahrscheinliche UrsacheLösung
jQuery-Fehler in der KonsolejQuery Migrate entferntMigrate wiederherstellen oder das Plugin aktualisieren, das veraltete APIs aufruft
Blöcke wirken ungestyltBlock Library oder globale Styles entferntDie Styles auf Seiten mit Block-Inhalten wiederherstellen
Query Loop oder Navigation zeigt nichts ando_blocks aus the_content entferntDiese Zeile entfernen
Formulare scheitern im abgemeldeten ZustandREST API auf angemeldete Nutzer beschränktDie Route des Plugins freigeben oder die Einschränkung aufheben
Mobile App oder Remote-Publishing scheitertXML-RPC blockiertWieder aktivieren oder den Client auf Anwendungspasswörter und REST umstellen
Einbettungen Ihrer Beiträge auf anderen Seiten brechenoEmbed-Anbieterseite entferntErwartet; wiederherstellen, wenn Partner es brauchen

#Wie man den Debloat-Code als MU-Plugin verpackt

Code in functions.php verschwindet, wenn das Theme wechselt. Ein Must-Use-Plugin in wp-content/mu-plugins/ lädt bei jeder Anfrage, lässt sich im Admin nicht deaktivieren und hält die Debloat-Einstellungen unabhängig vom Theme. WordPress lädt PHP-Dateien, die direkt in diesem Ordner liegen, aber keine Dateien in Unterordnern; behalten Sie also entweder eine einzige Datei oder ergänzen Sie einen kleinen Loader:

wp-content/
  mu-plugins/
    debloat-loader.php
    debloat/
      emoji.php
      head-cleanup.php
      xmlrpc.php
      heartbeat.php
<?php
/**
 * Plugin Name: Debloat
 * Description: Removes front-end features this site does not use.
 */

defined( 'ABSPATH' ) || exit;

foreach ( array( 'emoji', 'head-cleanup', 'xmlrpc', 'heartbeat' ) as $module ) {
    $file = __DIR__ . '/debloat/' . $module . '.php';
    if ( is_readable( $file ) ) {
        require_once $file;
    }
}

Jedes Modul enthält die Snippets aus den Abschnitten oben. Zwei Dinge gehören nicht in ein Debloat-Plugin. Automatische Plugin- und Theme-Updates mit auto_update_plugin und auto_update_theme abzuschalten ist eine Frage der Wartungsstrategie, keine Performance-Einstellung, und schaltet Sicherheitsupdates zusammen mit Funktionsupdates ab. Und Limits für Revisionen und Autosave sind Konstanten; sie gehören in wp-config.php, nicht in ein Plugin, das erst lädt, nachdem diese Konstanten ausgelesen wurden.

#Zusammenfassung

Der “Batteries included”-Ansatz von WordPress ist großartig für Anfänger, aber Entwickler, die maximale Performance suchen, müssen das Fett trimmen. Die Techniken in diesem Leitfaden, inspiriert von Terence Edens ausgezeichnetem Debloat-Skript, helfen Ihnen zu einer schlankeren, schnelleren WordPress-Installation.

Mehrere klassische Snippets bewirken unter WordPress 7.1 nichts mehr (WLW-Manifest, Links zu benachbarten Beiträgen, SVG-Filter, der Filter autosave_interval), und einige richten Schaden an (Entfernen von do_blocks, Entfernen der oEmbed-Bereinigung, komplettes Sperren der REST API). Jede Codezeile, die Sie entfernen, ist ein potenzieller Fehlerpunkt weniger; prüfen Sie deshalb jedes Snippet gegen die Version, die Sie betreiben, bevor es in die Produktion geht.

Nächster Schritt

Machen Sie aus dem Artikel eine echte Umsetzung

Dieser Block stärkt die interne Verlinkung und führt Nutzer gezielt zum nächsten sinnvollen Schritt im Service- und Content-System.

Soll das Thema auf Ihrer Website umgesetzt werden?

Wenn Sie aus dem Artikel konkrete Maßnahmen für Website, Relaunch oder Weiterentwicklung ableiten wollen, definiere ich den Scope und setze ihn um.

Relevanter Cluster

Weitere WordPress-Dienste und Wissensbasis entdecken

Stärken Sie Ihr Unternehmen mit professionellem technischen Support in den Kernbereichen des WordPress-Ökosystems.

Artikel-FAQ

Häufig gestellte Fragen

Praktische Antworten zur Umsetzung des Themas.

SEO-readyGEO-readyAEO-ready3 Q&A
Was bringt WordPress Debloat in der Praxis?#
Es reduziert unnötige Skripte, Styles und Meta-Tags. Das hilft bei Ladezeit, Wartbarkeit und teilweise auch bei der Sicherheitsoberfläche.
Sollte ich Emojis, XML-RPC und Gutenberg-Styles immer deaktivieren?#
Nicht blind. Manche Projekte brauchen genau diese Funktionen. Sinnvoll ist Debloat nur dann, wenn Sie die Auswirkungen im konkreten Stack geprüft haben.
Wo sollte ich Debloat-Code ablegen?#
Am saubersten in einem MU-Plugin oder in klar versioniertem Projektcode. So bleiben die Optimierungen unabhängig vom aktiven Theme erhalten.

Sie brauchen ein FAQ für Branche und Zielmarkt? Wir erstellen eine Version passend zu Ihren Business-Zielen.

Kontakt aufnehmen

Ähnliche Artikel