← All changes
|
includes/modules/ResourceHints/ResourceHintsModule.php
+56
-15
1.0.9
→
1.3.7
View file →
| @@ -56,12 +56,13 @@ | ||
| 56 | 56 | private static $buffering = false; |
| 57 | 57 | |
| 58 | 58 | public function ui_metadata(): array { |
| 59 | 59 | return array( |
| 60 | - 'label' => 'Resource Hints', | |
| 61 | - 'tab_label' => 'Hints', // its own tab on the Resource Hints page | |
| 60 | + 'label' => __( 'Resource Hints', 'xspeed' ), | |
| 61 | + 'tab_label' => __( 'Hints', 'xspeed' ), // its own tab on the Resource Hints page | |
| 62 | 62 | 'icon' => 'Zap', |
| 63 | - 'description' => 'Preload the LCP hero image and preconnect to font hosts so the largest element paints sooner.', | |
| 63 | + 'description' => __( 'Tells the browser to fetch the main image and fonts early.', 'xspeed' ), | |
| 64 | + 'group' => 'performance', | |
| 64 | 65 | // Host page: Hints (this module) + a Speculation Rules section |
| 65 | 66 | // (SmartPredict, Pro). SmartPredict prefetches the next page in |
| 66 | 67 | // the visitor's browser — same family as preload/preconnect, so |
| 67 | 68 | // it belongs here, not under AI (FBS-83633). |
| @@ -73,16 +74,17 @@ | ||
| 73 | 74 | return array( |
| 74 | 75 | 'enabled' => array( |
| 75 | 76 | 'type' => 'bool', |
| 76 | 77 | 'default' => true, |
| 77 | - 'label' => 'Enable Resource Hints', | |
| 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.', | |
| 78 | + 'label' => __( 'Enable resource hints', 'xspeed' ), | |
| 79 | + 'description' => __( 'Turns on all the hints below. They are safe on every theme, so this is on by default.', 'xspeed' ), | |
| 79 | 80 | ), |
| 80 | 81 | 'lcp_preload' => array( |
| 81 | 82 | 'type' => 'bool', |
| 82 | 83 | 'default' => true, |
| 83 | - 'label' => 'Preload LCP Image', | |
| 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.', | |
| 84 | + 'label' => __( 'Preload the main image', 'xspeed' ), | |
| 85 | + 'description' => __( 'Finds the largest image at the top of the page and tells the browser to fetch it first. This usually gives the biggest LCP gain.', 'xspeed' ), | |
| 86 | + 'dependsOn' => array( 'field' => 'enabled' ), | |
| 85 | 87 | ), |
| 86 | 88 | 'lcp_image_count' => array( |
| 87 | 89 | 'type' => 'int', |
| 88 | 90 | 'default' => 1, |
| @@ -87,35 +89,68 @@ | ||
| 87 | 89 | 'type' => 'int', |
| 88 | 90 | 'default' => 1, |
| 89 | 91 | 'min' => 0, |
| 90 | 92 | 'max' => 3, |
| 91 | - 'label' => 'Images to Preload', | |
| 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.', | |
| 93 | + 'label' => __( 'Images to preload', 'xspeed' ), | |
| 94 | + 'description' => __( 'How many images at the top of the page to preload. 1 suits most sites; raise it only if the top shows a small gallery.', 'xspeed' ), | |
| 95 | + 'advanced' => true, | |
| 96 | + 'dependsOn' => array( 'field' => 'lcp_preload' ), | |
| 93 | 97 | ), |
| 94 | 98 | 'lcp_exclusions' => array( |
| 95 | 99 | 'type' => 'list', |
| 96 | 100 | 'default' => array(), |
| 97 | 101 | 'item_type' => 'string', |
| 98 | - 'label' => 'Exclude From Preload', | |
| 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.', | |
| 102 | + 'label' => __( 'Excluded from preload', 'xspeed' ), | |
| 103 | + 'description' => __( 'Images whose tag contains a line here, such as a file name or class, are never picked as the main image. Useful for tracking pixels and spacers.', 'xspeed' ), | |
| 104 | + 'dependsOn' => array( 'field' => 'lcp_preload' ), | |
| 100 | 105 | ), |
| 106 | + 'preload_images' => array( | |
| 107 | + 'type' => 'list', | |
| 108 | + 'default' => array(), | |
| 109 | + 'item_type' => 'string', | |
| 110 | + 'label' => __( 'Always preload these images', 'xspeed' ), | |
| 111 | + 'description' => __( 'Image URLs to fetch first on every page, such as a hero background set in CSS. Keep it to one or two; only the first three are used.', 'xspeed' ), | |
| 112 | + 'dependsOn' => array( 'field' => 'enabled' ), | |
| 113 | + ), | |
| 101 | 114 | 'preconnect' => array( |
| 102 | 115 | 'type' => 'bool', |
| 103 | 116 | 'default' => true, |
| 104 | - 'label' => 'Preconnect to Font Hosts', | |
| 105 | - '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.', | |
| 117 | + 'label' => __( 'Connect early to Google Fonts', 'xspeed' ), | |
| 118 | + 'description' => __( 'When the page uses Google Fonts, the browser connects to Google\'s servers early, so fonts arrive sooner.', 'xspeed' ), | |
| 119 | + 'dependsOn' => array( 'field' => 'enabled' ), | |
| 106 | 120 | ), |
| 107 | 121 | 'preconnect_hosts' => array( |
| 108 | 122 | 'type' => 'list', |
| 109 | 123 | 'default' => array(), |
| 110 | 124 | 'item_type' => 'url', |
| 111 | - 'label' => 'Extra Preconnect Hosts', | |
| 112 | - '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.', | |
| 125 | + 'label' => __( 'Other domains to connect early', 'xspeed' ), | |
| 126 | + 'description' => __( 'One address per line, such as https://cdn.example.com. Use for a CDN or other domain that serves files at the top of the page.', 'xspeed' ), | |
| 127 | + 'advanced' => true, | |
| 128 | + 'dependsOn' => array( 'field' => 'enabled' ), | |
| 113 | 129 | ), |
| 114 | 130 | ); |
| 115 | 131 | } |
| 116 | 132 | |
| 117 | 133 | public function boot(): void { |
| 134 | + /* | |
| 135 | + * Deferred to `init`. This module reads its own settings to decide | |
| 136 | + * what to hook, and reading settings builds settings_schema(), whose | |
| 137 | + * labels are declared through __(). boot() runs on `plugins_loaded`, | |
| 138 | + * before `after_setup_theme` — the point WordPress 6.7+ treats as the | |
| 139 | + * earliest safe moment to translate — so doing that here fires | |
| 140 | + * _load_textdomain_just_in_time on every request AND resolves the | |
| 141 | + * labels against a domain that is not loaded yet. | |
| 142 | + * | |
| 143 | + * Everything below hooks actions that fire after `init`, so running | |
| 144 | + * one hook later is equivalent. | |
| 145 | + */ | |
| 146 | + add_action( 'init', array( $this, 'boot_on_init' ) ); | |
| 147 | + } | |
| 148 | + | |
| 149 | + /** | |
| 150 | + * The real boot body — see boot() for why it runs on `init`. | |
| 151 | + */ | |
| 152 | + public function boot_on_init(): void { | |
| 118 | 153 | // Frontend page renders only. Admin / feed / cron / AJAX / REST never |
| 119 | 154 | // produce an HTML document we should rewrite. |
| 120 | 155 | if ( is_admin() |
| 121 | 156 | || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) |
| @@ -120,8 +155,12 @@ | ||
| 120 | 155 | if ( is_admin() |
| 121 | 156 | || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) |
| 122 | 157 | || ( defined( 'DOING_CRON' ) && DOING_CRON ) |
| 123 | 158 | || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) |
| 159 | + // Builder editing screens are front-end URLs; injecting hints into | |
| 160 | + // the editor document helps nobody and can preload the wrong | |
| 161 | + // assets. (#281) | |
| 162 | + || \XSpeed\Builder_Editor::is_active() | |
| 124 | 163 | ) { |
| 125 | 164 | return; |
| 126 | 165 | } |
| 127 | 166 | |
| @@ -210,8 +249,9 @@ | ||
| 210 | 249 | array( |
| 211 | 250 | 'name' => 'xspeed resource-hints', |
| 212 | 251 | 'callback' => array( $this, 'cli_handler' ), |
| 213 | 252 | 'shortdesc' => 'Show LCP-preload / preconnect resource-hint settings.', |
| 253 | + '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.', | |
| 214 | 254 | 'synopsis' => array(), |
| 215 | 255 | ), |
| 216 | 256 | ); |
| 217 | 257 | } |
| @@ -221,8 +261,9 @@ | ||
| 221 | 261 | \WP_CLI::log( sprintf( '%-20s %s', 'enabled', ! empty( $opts['enabled'] ) ? 'on' : 'off' ) ); |
| 222 | 262 | \WP_CLI::log( sprintf( '%-20s %s', 'lcp_preload', ! empty( $opts['lcp_preload'] ) ? 'on' : 'off' ) ); |
| 223 | 263 | \WP_CLI::log( sprintf( '%-20s %d', 'lcp_image_count', (int) ( $opts['lcp_image_count'] ?? 1 ) ) ); |
| 224 | 264 | \WP_CLI::log( sprintf( '%-20s %d pattern(s)', 'lcp_exclusions', count( (array) ( $opts['lcp_exclusions'] ?? array() ) ) ) ); |
| 265 | + \WP_CLI::log( sprintf( '%-20s %d url(s)', 'preload_images', count( (array) ( $opts['preload_images'] ?? array() ) ) ) ); | |
| 225 | 266 | \WP_CLI::log( sprintf( '%-20s %s', 'preconnect', ! empty( $opts['preconnect'] ) ? 'on' : 'off' ) ); |
| 226 | 267 | \WP_CLI::log( sprintf( '%-20s %d host(s)', 'preconnect_hosts', count( (array) ( $opts['preconnect_hosts'] ?? array() ) ) ) ); |
| 227 | 268 | } |
| 228 | 269 | } |