PluginProbe
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN / 1.3.3
xSpeed Cache: AI-Powered Performance Hub with MCP, Caching & CDN v1.3.3
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 1.1.8 All 29 releases
← All changes | includes/modules/ResourceHints/ResourceHintsModule.php +53 -15 1.0.81.3.3 View file →
@@ -56,11 +56,17 @@
56 56 private static $buffering = false;
57 57
58 58 public function ui_metadata(): array {
59 59 return array(
60 - 'label' => 'Resource Hints',
61 - 'icon' => 'Zap',
62 - 'description' => 'Preload the LCP hero image and preconnect to font hosts so the largest element paints sooner.',
60 + 'label' => __( 'Resource Hints', 'xspeed' ),
61 + 'tab_label' => __( 'Hints', 'xspeed' ), // its own tab on the Resource Hints page
62 + 'icon' => 'Zap',
63 + 'description' => __( 'Preload the LCP hero image and preconnect to font hosts so the largest element paints sooner.', 'xspeed' ),
64 + // Host page: Hints (this module) + a Speculation Rules section
65 + // (SmartPredict, Pro). SmartPredict prefetches the next page in
66 + // the visitor's browser — same family as preload/preconnect, so
67 + // it belongs here, not under AI (FBS-83633).
68 + 'custom_panel' => 'ResourceHintsPanel',
63 69 );
64 70 }
65 71
66 72 public function settings_schema(): array {
@@ -67,16 +73,16 @@
67 73 return array(
68 74 'enabled' => array(
69 75 'type' => 'bool',
70 76 'default' => true,
71 - 'label' => 'Enable Resource Hints',
72 - 'description' => 'Master switch for the LCP-image preload + preconnect resource hints. On by default — these are safe, no-config optimizations that help every theme.',
77 + 'label' => __( 'Enable Resource Hints', 'xspeed' ),
78 + 'description' => __( 'Master switch for the LCP-image preload + preconnect resource hints. On by default — these are safe, no-config optimizations that help every theme.', 'xspeed' ),
73 79 ),
74 80 'lcp_preload' => array(
75 81 'type' => 'bool',
76 82 'default' => true,
77 - 'label' => 'Preload LCP Image',
78 - 'description' => 'Detect the largest above-the-fold image and emit a <link rel="preload" as="image" fetchpriority="high"> in the head, plus fetchpriority="high" on the image. This is the highest-impact fix for Largest Contentful Paint — it beats any lazy-load the theme applied.',
83 + 'label' => __( 'Preload LCP Image', 'xspeed' ),
84 + 'description' => __( 'Detect the largest above-the-fold image and emit a <link rel="preload" as="image" fetchpriority="high"> in the head, plus fetchpriority="high" on the image. This is the highest-impact fix for Largest Contentful Paint — it beats any lazy-load the theme applied.', 'xspeed' ),
79 85 ),
80 86 'lcp_image_count' => array(
81 87 'type' => 'int',
82 88 'default' => 1,
@@ -81,35 +87,61 @@
81 87 'type' => 'int',
82 88 'default' => 1,
83 89 'min' => 0,
84 90 'max' => 3,
85 - 'label' => 'Images to Preload',
86 - 'description' => 'How many of the first images on the page to preload. 1 is right for most sites (the single hero). Raise it only if the fold shows a small gallery.',
91 + 'label' => __( 'Images to Preload', 'xspeed' ),
92 + 'description' => __( 'How many of the first images on the page to preload. 1 is right for most sites (the single hero). Raise it only if the fold shows a small gallery.', 'xspeed' ),
87 93 ),
88 94 'lcp_exclusions' => array(
89 95 'type' => 'list',
90 96 'default' => array(),
91 97 'item_type' => 'string',
92 - 'label' => 'Exclude From Preload',
93 - 'description' => 'Substring patterns (filename or class) that, if found in an <img>, exempt it from being treated as the LCP image. Useful for tracking pixels, spacers, or a decorative first image that is not the hero.',
98 + 'label' => __( 'Exclude From Preload', 'xspeed' ),
99 + 'description' => __( 'Substring patterns (filename or class) that, if found in an <img>, exempt it from being treated as the LCP image. Useful for tracking pixels, spacers, or a decorative first image that is not the hero.', 'xspeed' ),
94 100 ),
101 + 'preload_images' => array(
102 + 'type' => 'list',
103 + 'default' => array(),
104 + 'item_type' => 'string',
105 + 'label' => __( 'Always Preload These Images', 'xspeed' ),
106 + 'description' => __( 'Image URLs (full or site-relative) to preload with high priority on every page. This is the escape hatch for an LCP image the detector cannot see — most often a hero section\'s CSS background-image, which carries none of the signals the automatic pick reads. Keep it to one or two images: preloading many hands them all top network priority and the page itself loses. The first three entries are used.', 'xspeed' ),
107 + ),
95 108 'preconnect' => array(
96 109 'type' => 'bool',
97 110 'default' => true,
98 - 'label' => 'Preconnect to Font Hosts',
99 - 'description' => 'When Google Fonts are detected, emit <link rel="preconnect"> to fonts.googleapis.com and fonts.gstatic.com so the DNS + TLS handshake happens ahead of the font request instead of on the critical path.',
111 + 'label' => __( 'Preconnect to Font Hosts', 'xspeed' ),
112 + 'description' => __( 'When Google Fonts are detected, emit <link rel="preconnect"> to fonts.googleapis.com and fonts.gstatic.com so the DNS + TLS handshake happens ahead of the font request instead of on the critical path.', 'xspeed' ),
100 113 ),
101 114 'preconnect_hosts' => array(
102 115 'type' => 'list',
103 116 'default' => array(),
104 117 'item_type' => 'url',
105 - 'label' => 'Extra Preconnect Hosts',
106 - 'description' => 'One origin per line (e.g. https://cdn.example.com) to preconnect in addition to the auto-detected font hosts. Use for a CDN or third-party origin that serves above-the-fold assets.',
118 + 'label' => __( 'Extra Preconnect Hosts', 'xspeed' ),
119 + 'description' => __( 'One origin per line (e.g. https://cdn.example.com) to preconnect in addition to the auto-detected font hosts. Use for a CDN or third-party origin that serves above-the-fold assets.', 'xspeed' ),
107 120 ),
108 121 );
109 122 }
110 123
111 124 public function boot(): void {
125 + /*
126 + * Deferred to `init`. This module reads its own settings to decide
127 + * what to hook, and reading settings builds settings_schema(), whose
128 + * labels are declared through __(). boot() runs on `plugins_loaded`,
129 + * before `after_setup_theme` — the point WordPress 6.7+ treats as the
130 + * earliest safe moment to translate — so doing that here fires
131 + * _load_textdomain_just_in_time on every request AND resolves the
132 + * labels against a domain that is not loaded yet.
133 + *
134 + * Everything below hooks actions that fire after `init`, so running
135 + * one hook later is equivalent.
136 + */
137 + add_action( 'init', array( $this, 'boot_on_init' ) );
138 + }
139 +
140 + /**
141 + * The real boot body — see boot() for why it runs on `init`.
142 + */
143 + public function boot_on_init(): void {
112 144 // Frontend page renders only. Admin / feed / cron / AJAX / REST never
113 145 // produce an HTML document we should rewrite.
114 146 if ( is_admin()
115 147 || ( defined( 'DOING_AJAX' ) && DOING_AJAX )
@@ -114,8 +146,12 @@
114 146 if ( is_admin()
115 147 || ( defined( 'DOING_AJAX' ) && DOING_AJAX )
116 148 || ( defined( 'DOING_CRON' ) && DOING_CRON )
117 149 || ( defined( 'REST_REQUEST' ) && REST_REQUEST )
150 + // Builder editing screens are front-end URLs; injecting hints into
151 + // the editor document helps nobody and can preload the wrong
152 + // assets. (#281)
153 + || \XSpeed\Builder_Editor::is_active()
118 154 ) {
119 155 return;
120 156 }
121 157
@@ -204,8 +240,9 @@
204 240 array(
205 241 'name' => 'xspeed resource-hints',
206 242 'callback' => array( $this, 'cli_handler' ),
207 243 'shortdesc' => 'Show LCP-preload / preconnect resource-hint settings.',
244 + 'ai_hint' => 'Browser resource hints — preload, prefetch, preconnect — for the resources that block first paint. Use for LCP problems or "preconnect to required origins" in PageSpeed. Not the same as the Preloader, which warms the page cache.',
208 245 'synopsis' => array(),
209 246 ),
210 247 );
211 248 }
@@ -215,8 +252,9 @@
215 252 \WP_CLI::log( sprintf( '%-20s %s', 'enabled', ! empty( $opts['enabled'] ) ? 'on' : 'off' ) );
216 253 \WP_CLI::log( sprintf( '%-20s %s', 'lcp_preload', ! empty( $opts['lcp_preload'] ) ? 'on' : 'off' ) );
217 254 \WP_CLI::log( sprintf( '%-20s %d', 'lcp_image_count', (int) ( $opts['lcp_image_count'] ?? 1 ) ) );
218 255 \WP_CLI::log( sprintf( '%-20s %d pattern(s)', 'lcp_exclusions', count( (array) ( $opts['lcp_exclusions'] ?? array() ) ) ) );
256 + \WP_CLI::log( sprintf( '%-20s %d url(s)', 'preload_images', count( (array) ( $opts['preload_images'] ?? array() ) ) ) );
219 257 \WP_CLI::log( sprintf( '%-20s %s', 'preconnect', ! empty( $opts['preconnect'] ) ? 'on' : 'off' ) );
220 258 \WP_CLI::log( sprintf( '%-20s %d host(s)', 'preconnect_hosts', count( (array) ( $opts['preconnect_hosts'] ?? array() ) ) ) );
221 259 }
222 260 }