Page profiler never treats the detected LCP image as LCP, so it gets no fetchpriority="high" (stored ID is a string, compared with === to an int)
Maintainer antworten meist innerhalb von 1 Tag
Bewertung
- Schwierigkeit
- 2/5
- Geschätzter Aufwand
- 1-3 Stunden
- Anfängerfreundlichkeit
- 88/100
- Issue-Typ
- Bug
- Klarheit
- Klar beschrieben
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- javascript, php
- Bereich
- backend, performance
Rechercherichtung
Beginne bei inc/rest.php etwa bei Zeile 1032, wo die LCP-imageId über sanitize_text_field() gespeichert wird, und untersuche dann Profile.php:385-393, wo is_lcp_image_in_all_viewports() striktes === verwendet. Reproduziere es über das WP-CLI-Snippet oder den vorhandenen Test test_lazyload_viewport_with_lcp_data, der derzeit den REST-Pfad umgeht. Fertig bedeutet: Die gespeicherte ID ist ein int (oder wird vor dem Vergleich gecastet), die Methode gibt für beide Viewport-Profile true zurück, und der LCP-Zweig in tag_replacer.php fügt fetchpriority="high" hinzu.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
Description
The page profiler detects the LCP image in the browser and sends its data-opt-id to /optimizations as an integer. The REST handler stores it with sanitize_text_field(), which always returns a string. Profile::is_lcp_image_in_all_viewports( int $image_id ) then compares that string to the int ID with ===, so it is always false.
Result, with the default "fixed|viewport" lazy load type and profile data stored for both devices:
- Optimole never adds
fetchpriority="high"to the LCP image (tag_replacer.phpLCP branch is dead, and the fixed-count fallback is skipped because profile data exists). - If the LCP image is not in the above-the-fold list for both devices, it is lazy-loaded anyway (and any
fetchpriority="high"on it is stripped).
Expected: the stored LCP image gets fetchpriority="high" and is never lazy-loaded. Likely fix: store absint( $lcp_data['i'] ?? 0 ) in inc/rest.php (or cast before comparing in Profile.php). Existing profiles in transients/object cache keep the string until they expire, so casting at compare time also covers those.
The unit test test_lazyload_viewport_with_lcp_data stores imageId as an int directly through Profile::store(), so it does not cover the REST path.
Step-by-step reproduction instructions
- On a test site with Optimole 4.2.17 connected and default Lazy Load settings, run this with WP-CLI (it stores LCP data the same way
inc/rest.php:1032does):wp eval ' $p = new OptimoleWP\PageProfiler\Profile(); $img = 1578474861; $lcp = [ "imageId" => sanitize_text_field( $img ), "type" => "img" ]; foreach ( [ 1, 2 ] as $d ) { $p->store( "bugcheck", $d, [], [], $lcp ); } OptimoleWP\PageProfiler\Profile::set_current_profile_id( "bugcheck" ); $p->set_current_profile_data(); var_dump( $p->is_lcp_image_in_all_viewports( $img ) ); ' - Expected
bool(true). Actualbool(false). - Clean up:
wp transient delete _oprof_bugcheck_1 && wp transient delete _oprof_bugcheck_2(or flush theoptimole_page_profilercache group if an object cache is used).
End to end check on a real page: open a page with a large hero image once on desktop and once in mobile emulation so both profiles are stored, then reload and view source. The hero <img data-opt-id=...> has no fetchpriority="high" added by Optimole, and wp transient get _oprof_<profile id>_2 --format=json shows "imageId":"<id>" as a string.
Pure PHP reproduction of the same path (json_decode of the REST body, core _sanitize_text_fields cast, transient serialize round trip, the Profile.php:387 comparison), PHP 8.4:
REST param l.i type: integer
[transient] stored imageId='1578474861' (string), page image_id=1578474861 (integer) -> is_lcp_image_in_all_viewports=false; loose == would be true
[object-cache-json] stored imageId='1578474861' (string), page image_id=1578474861 (integer) -> is_lcp_image_in_all_viewports=false; loose == would be true
Screenshots, screen recording, code snippet or Help Scout ticket
Browser sends an int: https://github.com/Codeinwp/optimole-wp/blob/v4.2.17/assets/js/modules/lcp.js#L88-L92
lcpData.imageId = parseInt(id, 10);
REST handler stores a string: https://github.com/Codeinwp/optimole-wp/blob/v4.2.17/inc/rest.php#L1032
$sanitized_lcp_data['imageId'] = sanitize_text_field( $lcp_data['i'] ?? '' );
Strict compare with the int data-opt-id: https://github.com/Codeinwp/optimole-wp/blob/v4.2.17/inc/v2/PageProfiler/Profile.php#L385-L393
public function is_lcp_image_in_all_viewports( int $image_id ): bool {
...
( ( self::$current_profile_data[ $device ]['lcp']['imageId'] ?? null ) === $image_id )
Callers that never fire:
- https://github.com/Codeinwp/optimole-wp/blob/v4.2.17/inc/tag_replacer.php#L434-L445 (adds
fetchpriority="high") - https://github.com/Codeinwp/optimole-wp/blob/v4.2.17/inc/lazyload_replacer.php#L464-L480 (skips lazy load for the LCP image)
$image_id comes from get_id_by_url(), which returns rand() (an int): https://github.com/Codeinwp/optimole-wp/blob/v4.2.17/inc/app_replacer.php#L691-L697
Core: _sanitize_text_fields() casts to string: https://github.com/WordPress/WordPress/blob/7.1.3/wp-includes/formatting.php#L5708-L5713
Environment info
- Optimole 4.2.17 (same code on
masterand back to 4.0.0) - WordPress 5.5 to 7.1 (
_sanitize_text_fields()casts to string in 5.5, 6.8.3 and 7.1.3) - PHP 7.4 to 8.4 (strict
===behaves the same on all) - Lazy load type "fixed|viewport" (default), page profiler enabled (default)
Is the issue you are reporting a regression
No. The string store and the strict compare are both present in 4.0.0.
Found while writing the WordPress compatibility checks for Optimole.
- Vorherrschende Sprache
- PHP
- Sterne
- 74
- Forks
- 14
- Ø Merge
- 1 T. 22 Std.
- Gemergte PRs (30 T.)
- 29
Entwicklungsumgebung
- Enthält ein Dockerfile oder eine Docker-Compose-Datei
- Hat eine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus Codeinwp/optimole-wp
-
Page profiler endpoint fatals on PHP 8 when the request has no `b` (background selectors) fieldEvtl. vergeben @girishpanchal30 hat das vor 1 Tag übernommen. Offenbug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 88/100
Codeinwp/optimole-wp#1204 · 4 Kommentare · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 1 Tag
-
Background image with a gradient is not lazy-loaded on WordPress 7.1 (Quote, Pullquote, Verse, Post Content, Accordion)Evtl. vergeben @girishpanchal30 hat das vor 1 Tag übernommen. Offenbug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 78/100
Codeinwp/optimole-wp#1203 · 3 Kommentare · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 1 Tag
-
Account sign-up fatals when the Optimole API returns an empty or non-JSON responseEvtl. vergeben @girishpanchal30 hat das vor 1 Tag übernommen. Offenbug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 85/100
Codeinwp/optimole-wp#1200 · 3 Kommentare · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 1 Tag
-
Renaming an image leaves the old URL in comments and term descriptions, with "Unknown column 'ID'" database errorsEvtl. vergeben @girishpanchal30 hat das vor 1 Tag übernommen. Offenbug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 74/100
Codeinwp/optimole-wp#1199 · 3 Kommentare · 1 zugewiesene Person ·
Maintainer antworten meist innerhalb von 1 Tag
-
bug-report customer report
Schwierigkeit 4/5 3-5 Tage Anfängerfreundlichkeit 56/100
Codeinwp/optimole-wp#1211 ·
Maintainer antworten meist innerhalb von 1 Tag
Alle Issues in Codeinwp/optimole-wp
Ähnliche Issues
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 82/100
unopim/shopify-connector#55 ·
-
14.3.x
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 65/100
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 68/100
-
CMS video element: "CmsVideoPlugin" sets `volume = 0`, so videos cannot be unmuted on Android ChromeOffenneeds-triage Platform(Default)
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
Maintainer antworten meist innerhalb von 1 Tag
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
PrestaShop/ps_googleanalytics#187 ·