Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

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)

Đang mở Phù hợp với người mới
#1,202 3 bình luận 0 reaction 1 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

@girishpanchal30 đang làm issue này rồi.

Từ ngày 29/10/2026.

  • #1213 của @girishpanchal30 — đang mở

Đánh giá

Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức phù hợp với người mới
88/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
javascript, php
Lĩnh vực
backend, performance

Hướng nghiên cứu

Bắt đầu tại inc/rest.php quanh dòng 1032, nơi imageId của LCP được lưu qua sanitize_text_field(), sau đó kiểm tra Profile.php:385-393, nơi is_lcp_image_in_all_viewports() dùng === nghiêm ngặt. Tái hiện qua đoạn mã WP-CLI hoặc test hiện có test_lazyload_viewport_with_lcp_data, vốn hiện đang bỏ qua đường dẫn REST. Hoàn thành nghĩa là ID được lưu là int (hoặc được ép kiểu trước khi so sánh), phương thức trả về true cho cả hai cấu hình viewport, và nhánh LCP trong tag_replacer.php thêm fetchpriority="high".

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

bug
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.php LCP 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
  1. 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:1032 does):
    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 ) );
    '
    
  2. Expected bool(true). Actual bool(false).
  3. Clean up: wp transient delete _oprof_bugcheck_1 && wp transient delete _oprof_bugcheck_2 (or flush the optimole_page_profiler cache 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:

$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 master and 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.

Ngôn ngữ chính
PHP
Star
74
Fork
14
Merge trung bình
1 ngày 21 giờ
Pull request đã merge (30 ngày)
30

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của Codeinwp/optimole-wp

Tất cả issue của Codeinwp/optimole-wp

Issue tương tự

Thêm issue về PHP

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.