PluginProbe
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN / 1.3.4
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN v1.3.4
1.3.4 1.3.3 1.3.2 1.3.1 1.3.0 1.2.4 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 All 30 releases
← All changes | includes/modules/Bloat/BloatModule.php +59 -0 1.3.11.3.4 View file →
@@ -72,8 +72,14 @@
72 72 'default' => false,
73 73 'label' => __( 'Strip jQuery Migrate on Frontend', 'xspeed' ),
74 74 'description' => __( 'Remove the jquery-migrate compatibility shim from non-admin pages. Saves ~10 KB; safe on modern themes / plugins.', 'xspeed' ),
75 75 ),
76 + 'strip_editor_styles' => array(
77 + 'type' => 'bool',
78 + 'default' => false,
79 + 'label' => __( 'Strip Block-Editor Styles on Frontend', 'xspeed' ),
80 + 'description' => __( 'Drop editor-only stylesheets (wp-editor, wp-components, and friends) from anonymous pages. A plugin that enqueues them on the frontend usually does so by accident — they can add hundreds of KB of render-blocking CSS. Frontend block styles (wp-block-library) are never touched.', 'xspeed' ),
81 + ),
76 82 'restrict_rest_to_authed' => array(
77 83 'type' => 'bool',
78 84 'default' => false,
79 85 'label' => __( 'Restrict REST API to Logged-In Users', 'xspeed' ),
@@ -131,8 +137,13 @@
131 137 if ( ! empty( $opts['strip_jquery_migrate'] ) ) {
132 138 add_action( 'wp_default_scripts', array( __CLASS__, 'strip_jquery_migrate' ) );
133 139 }
134 140
141 + if ( ! empty( $opts['strip_editor_styles'] ) ) {
142 + // Late, so anything enqueued at normal priority is already queued.
143 + add_action( 'wp_enqueue_scripts', array( __CLASS__, 'dequeue_editor_styles' ), PHP_INT_MAX );
144 + }
145 +
135 146 if ( ! empty( $opts['restrict_rest_to_authed'] ) ) {
136 147 add_filter( 'rest_authentication_errors', array( __CLASS__, 'restrict_rest' ) );
137 148 }
138 149 }
@@ -172,8 +183,56 @@
172 183 }
173 184 return $rules;
174 185 }
175 186 );
187 + }
188 +
189 + /**
190 + * Editor-only style handles that have no business on an anonymous
191 + * frontend page. Deliberately NOT wp-block-library /
192 + * wp-block-library-theme / global-styles — those style the blocks
193 + * visitors actually see. Observed live: a plugin pulled wp-editor +
194 + * wp-components (and their deps) onto a marketing homepage, several
195 + * hundred KB of render-blocking CSS nothing on the page used.
196 + */
197 + private const EDITOR_STYLE_HANDLES = array(
198 + 'wp-editor',
199 + 'wp-block-editor',
200 + 'wp-block-directory',
201 + 'wp-components',
202 + 'wp-preferences',
203 + 'wp-media-utils',
204 + 'wp-reusable-blocks',
205 + 'wp-patterns',
206 + 'wp-edit-blocks',
207 + 'wp-edit-post',
208 + 'wp-edit-site',
209 + 'wp-edit-widgets',
210 + 'wp-format-library',
211 + 'wp-list-reusable-blocks',
212 + 'wp-nux',
213 + );
214 +
215 + public static function dequeue_editor_styles(): void {
216 + // Logged-in views legitimately reach editor surfaces (front-end
217 + // editing, admin bar flows), and a builder editing screen is a
218 + // front-end URL — same guard set as the other frontend strips.
219 + if ( is_user_logged_in() || is_admin() || \XSpeed\Builder_Editor::is_active() ) {
220 + return;
221 + }
222 + $styles = wp_styles();
223 + foreach ( self::EDITOR_STYLE_HANDLES as $handle ) {
224 + wp_dequeue_style( $handle );
225 + }
226 + // Dequeue alone is not enough: dependencies are resolved again at
227 + // print time, so any queued sheet that lists one of these as a dep
228 + // pulls it straight back. Strip the handles from every registered
229 + // sheet's deps too — same technique strip_jquery_migrate() uses.
230 + foreach ( $styles->registered as $dependency ) {
231 + if ( is_array( $dependency->deps ?? null ) && array_intersect( $dependency->deps, self::EDITOR_STYLE_HANDLES ) ) {
232 + $dependency->deps = array_values( array_diff( $dependency->deps, self::EDITOR_STYLE_HANDLES ) );
233 + }
234 + }
176 235 }
177 236
178 237 public static function block_feed(): void {
179 238 wp_die(