Hiệu suất gỡ lỗi trong trường

Tìm hiểu cách liên kết dữ liệu hiệu suất với thông tin gỡ lỗi để giúp bạn xác định và khắc phục các vấn đề của người dùng thực bằng số liệu phân tích

Google cung cấp 2 danh mục công cụ để đo lường và gỡ lỗi hiệu suất:

  • Công cụ phòng thí nghiệm: Các công cụ như Lighthouse, nơi trang của bạn được tải trong một môi trường mô phỏng có thể bắt chước nhiều điều kiện (ví dụ: mạng chậm và thiết bị di động cấp thấp).
  • Công cụ thực tế: Các công cụ như Báo cáo trải nghiệm người dùng trên Chrome (CrUX) dựa trên dữ liệu tổng hợp của người dùng thực tế từ Chrome. (Xin lưu ý rằng dữ liệu thực tế do các công cụ như PageSpeed Insights và Search Console báo cáo được lấy từ dữ liệu CrUX.)

Mặc dù các công cụ thực địa cung cấp dữ liệu chính xác hơn (dữ liệu thực sự thể hiện trải nghiệm của người dùng thực tế), nhưng các công cụ phòng thí nghiệm thường giúp bạn xác định và khắc phục vấn đề hiệu quả hơn.

Dữ liệu CrUX thể hiện hiệu suất thực tế của trang một cách chính xác hơn, nhưng việc biết điểm CrUX của bạn khó có thể giúp bạn tìm ra cách cải thiện hiệu suất.

Mặt khác, Lighthouse sẽ xác định các vấn đề và đưa ra các đề xuất cụ thể về cách cải thiện. Tuy nhiên, Lighthouse sẽ chỉ đưa ra đề xuất cho các vấn đề về hiệu suất mà công cụ này phát hiện được tại thời điểm tải trang. Công cụ này không phát hiện những vấn đề chỉ xuất hiện do người dùng tương tác, chẳng hạn như thao tác cuộn hoặc nhấp vào các nút trên trang.

Điều này đặt ra một câu hỏi quan trọng: làm cách nào để bạn có thể thu thập thông tin gỡ lỗi cho Core Web Vitals hoặc các chỉ số hiệu suất khác từ người dùng thực tế?

Bài đăng này sẽ giải thích chi tiết những API mà bạn có thể dùng để thu thập thông tin gỡ lỗi bổ sung cho từng chỉ số hiện tại trong số Core Web Vitals, đồng thời đưa ra ý tưởng về cách thu thập dữ liệu này trong công cụ phân tích hiện có.

API để phân bổ và gỡ lỗi

Điểm số tổng hợp về mức thay đổi bố cục (CLS)

Trong số tất cả các chỉ số Core Web Vitals, CLS có lẽ là chỉ số quan trọng nhất để thu thập thông tin gỡ lỗi tại trang. CLS được đo lường trong toàn bộ thời gian tồn tại của trang, vì vậy, cách người dùng tương tác với trang (họ cuộn bao xa, họ nhấp vào nội dung gì, v.v.) có thể ảnh hưởng đáng kể đến việc có sự thay đổi bố cục hay không và những phần tử nào đang thay đổi.

Hãy xem xét báo cáo sau đây của PageSpeed Insights:

Báo cáo PageSpeed Insights với các giá trị CLS khác nhau
PageSpeed Insights cho thấy cả dữ liệu thực tế và dữ liệu thử nghiệm (nếu có) và những dữ liệu này có thể khác nhau

Giá trị được báo cáo cho CLS từ phòng thí nghiệm (Lighthouse) so với CLS từ thực tế (dữ liệu CrUX) khá khác nhau. Điều này là hợp lý nếu bạn cho rằng trang có thể có nhiều nội dung tương tác không được sử dụng khi kiểm thử trong Lighthouse.

Nhưng ngay cả khi hiểu rằng hoạt động tương tác của người dùng ảnh hưởng đến dữ liệu trường, bạn vẫn cần biết những phần tử nào trên trang đang thay đổi để dẫn đến điểm số là 0,28 ở phân vị thứ 75. Giao diện LayoutShiftAttribution giúp bạn thực hiện được điều đó.

Nhận thông tin phân bổ về mức thay đổi bố cục

Giao diện LayoutShiftAttribution được hiển thị trên mỗi mục nhập layout-shift mà Layout Instability API phát ra.

Để biết nội dung giải thích chi tiết về cả hai giao diện này, hãy xem phần Gỡ lỗi các thay đổi về bố cục. Đối với mục đích của bài đăng này, điều chính mà bạn cần biết là với tư cách là nhà phát triển, bạn có thể quan sát mọi thay đổi về bố cục xảy ra trên trang cũng như những phần tử đang thay đổi.

Sau đây là một số mã ví dụ ghi lại từng thay đổi bố cục cũng như các phần tử đã thay đổi:

new PerformanceObserver((list) => {
  for (const {value, startTime, sources} of list.getEntries()) {
    // Log the shift amount and other entry info.
    console.log('Layout shift:', {value, startTime});
    if (sources) {
      for (const {node, curRect, prevRect} of sources) {
        // Log the elements that shifted.
        console.log('  Shift source:', node, {curRect, prevRect});
      }
    }
  }
}).observe({type: 'layout-shift', buffered: true});

Có lẽ không thực tế khi đo lường và gửi dữ liệu đến công cụ phân tích của bạn cho mọi thay đổi bố cục xảy ra; tuy nhiên, bằng cách theo dõi tất cả các thay đổi, bạn có thể theo dõi những thay đổi tồi tệ nhất và chỉ báo cáo thông tin về những thay đổi đó.

Mục tiêu không phải là xác định và khắc phục từng thay đổi bố cục xảy ra cho mọi người dùng; mục tiêu là xác định những thay đổi ảnh hưởng đến số lượng người dùng lớn nhất và do đó đóng góp nhiều nhất vào CLS của trang ở phân vị thứ 75.

Ngoài ra, bạn không cần tính toán phần tử nguồn lớn nhất mỗi khi có sự thay đổi, bạn chỉ cần làm như vậy khi sẵn sàng gửi giá trị CLS đến công cụ phân tích của mình.

Đoạn mã sau đây lấy một danh sách các mục layout-shift đã đóng góp vào CLS và trả về phần tử nguồn lớn nhất từ mức thay đổi lớn nhất:

function getCLSDebugTarget(entries) {
  const largestEntry = entries.reduce((a, b) => {
    return a && a.value > b.value ? a : b;
  });
  if (largestEntry && largestEntry.sources && largestEntry.sources.length) {
    const largestSource = largestEntry.sources.reduce((a, b) => {
      return a.node && a.previousRect.width * a.previousRect.height >
          b.previousRect.width * b.previousRect.height ? a : b;
    });
    if (largestSource) {
      return largestSource.node;
    }
  }
}

Sau khi xác định được phần tử lớn nhất đóng góp vào sự thay đổi lớn nhất, bạn có thể báo cáo phần tử đó cho công cụ phân tích của mình.

Phần tử đóng góp nhiều nhất vào CLS cho một trang nhất định có thể khác nhau tuỳ theo người dùng, nhưng nếu tổng hợp các phần tử đó trên tất cả người dùng, bạn sẽ có thể tạo một danh sách các phần tử thay đổi ảnh hưởng đến nhiều người dùng nhất.

Sau khi bạn xác định và khắc phục nguyên nhân gốc rễ của các thay đổi đối với những phần tử đó, mã phân tích sẽ bắt đầu báo cáo các thay đổi nhỏ hơn dưới dạng các thay đổi "tệ nhất" cho các trang của bạn. Cuối cùng, tất cả các thay đổi được báo cáo sẽ đủ nhỏ để các trang của bạn nằm trong ngưỡng "tốt" là 0,1!

Một số siêu dữ liệu khác có thể hữu ích khi bạn ghi lại cùng với phần tử nguồn có mức thay đổi lớn nhất là:

  • Thời gian thay đổi lớn nhất
  • Đường dẫn URL tại thời điểm có sự thay đổi lớn nhất (đối với những trang web cập nhật URL một cách linh hoạt, chẳng hạn như ứng dụng trang đơn).

Thời gian hiển thị nội dung lớn nhất (LCP)

Để gỡ lỗi LCP trong trường, thông tin chính mà bạn cần là phần tử cụ thể nào là phần tử lớn nhất (phần tử đề xuất LCP) cho lần tải trang cụ thể đó.

Xin lưu ý rằng hoàn toàn có thể (thực tế là khá phổ biến) khi phần tử LCP đề xuất sẽ khác nhau giữa người dùng, ngay cả đối với cùng một trang.

Điều này có thể xảy ra vì một vài lý do:

  • Thiết bị của người dùng có độ phân giải màn hình khác nhau, dẫn đến bố cục trang khác nhau và do đó, các phần tử khác nhau sẽ xuất hiện trong khung nhìn.
  • Người dùng không phải lúc nào cũng tải các trang được cuộn lên trên cùng. Đường liên kết thường chứa mã nhận dạng theo đoạn hoặc thậm chí là đoạn văn bản, tức là các trang của bạn có thể được tải và hiển thị ở bất kỳ vị trí cuộn nào trên trang.
  • Nội dung có thể được cá nhân hoá cho người dùng hiện tại, vì vậy, phần tử LCP đề xuất có thể khác nhau rất nhiều giữa người dùng này với người dùng khác.

Điều này có nghĩa là bạn không thể giả định về phần tử hoặc nhóm phần tử nào sẽ là phần tử LCP phổ biến nhất cho một trang cụ thể. Bạn phải đo lường chỉ số này dựa trên hành vi của người dùng thực.

Xác định phần tử LCP đề xuất

Để xác định phần tử đề xuất LCP trong JavaScript, bạn có thể sử dụng Largest Contentful Paint API (API hiển thị nội dung lớn nhất), đây cũng là API mà bạn dùng để xác định giá trị thời gian LCP.

Khi quan sát các mục largest-contentful-paint, bạn có thể xác định phần tử ứng cử viên LCP hiện tại bằng cách xem thuộc tính element của mục cuối cùng:

new PerformanceObserver((list) => {
  const entries = list.getEntries();
  const lastEntry = entries[entries.length - 1];

  console.log('LCP element:', lastEntry.element);
}).observe({type: 'largest-contentful-paint', buffered: true});

Sau khi biết phần tử đề xuất LCP, bạn có thể gửi phần tử đó đến công cụ phân tích cùng với giá trị chỉ số. Tương tự như CLS, chỉ số này sẽ giúp bạn xác định những phần tử quan trọng nhất cần tối ưu hoá trước.

Ngoài phần tử đề xuất LCP, bạn cũng nên đo lường thời gian của các phần phụ LCP. Điều này có thể hữu ích trong việc xác định những bước tối ưu hoá cụ thể phù hợp với trang web của bạn.

Lượt tương tác đến nội dung hiển thị tiếp theo (INP)

Những thông tin quan trọng nhất cần thu thập tại hiện trường cho INP là:

  1. Phần tử nào đã được tương tác
  2. Loại tương tác
  3. Thời điểm diễn ra hoạt động tương tác đó

Nguyên nhân chính gây ra các lượt tương tác chậm là do luồng chính bị chặn. Điều này có thể xảy ra khi JavaScript đang tải. Việc biết được liệu hầu hết các lượt tương tác diễn ra chậm có xảy ra trong quá trình tải trang hay không sẽ giúp xác định những việc cần làm để khắc phục vấn đề.

Chỉ số INP xem xét toàn bộ độ trễ của một lượt tương tác, bao gồm cả thời gian cần thiết để chạy mọi trình nghe sự kiện đã đăng ký cũng như thời gian cần thiết để hiển thị khung hình tiếp theo sau khi tất cả trình nghe sự kiện đã chạy. Điều này có nghĩa là đối với INP, bạn nên biết những phần tử đích nào thường dẫn đến các lượt tương tác diễn ra chậm và đó là những loại lượt tương tác nào.

Đoạn mã sau đây ghi lại phần tử đích và thời gian của mục nhập INP.

function logINPDebugInfo(inpEntry) {
  console.log('INP target element:', inpEntry.target);
  console.log('INP interaction type:', inpEntry.name);
  console.log('INP time:', inpEntry.startTime);
}

Xin lưu ý rằng mã này không cho biết cách xác định mục nhập event nào là mục nhập INP, vì logic đó phức tạp hơn. Tuy nhiên, phần sau đây giải thích cách lấy thông tin này bằng thư viện JavaScript web-vitals.

Cách sử dụng với thư viện JavaScript web-vitals

Các phần trước đưa ra một số đề xuất chung và ví dụ về mã để ghi lại thông tin gỡ lỗi nhằm đưa vào dữ liệu mà bạn gửi đến công cụ phân tích.

Kể từ phiên bản 3, thư viện JavaScript web-vitals có một bản dựng phân bổ hiển thị tất cả thông tin này, cũng như một số tín hiệu bổ sung.

Ví dụ về mã sau đây cho thấy cách bạn có thể đặt một tham số sự kiện bổ sung (hoặc phương diện tuỳ chỉnh) chứa một chuỗi gỡ lỗi hữu ích để giúp xác định nguyên nhân gốc rễ của các vấn đề về hiệu suất.

import {onCLS, onINP, onLCP} from 'web-vitals/attribution';

function sendToGoogleAnalytics({name, value, id, attribution}) {
  const eventParams = {
    metric_value: value,
    metric_id: id,
  }

  switch (name) {
    case 'CLS':
      eventParams.debug_target = attribution.largestShiftTarget;
      break;
    case 'LCP':
      eventParams.debug_target = attribution.element;
      break;
    case 'INP':
      eventParams.debug_target = attribution.interactionTarget;
      break;
  }

  // Assumes the global `gtag()` function exists, see:
  // https://developers.google.com/analytics/devguides/collection/ga4
  gtag('event', name, eventParams);
}

onCLS(sendToGoogleAnalytics);
onLCP(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);

Mã này dành riêng cho Google Analytics, nhưng ý tưởng chung cũng sẽ áp dụng được cho các công cụ phân tích khác.

Đoạn mã này cũng chỉ cho thấy cách báo cáo một tín hiệu gỡ lỗi duy nhất, nhưng bạn nên có thể thu thập và báo cáo nhiều tín hiệu khác nhau cho mỗi chỉ số.

Ví dụ: để gỡ lỗi INP, bạn có thể muốn thu thập phần tử đang tương tác, loại tương tác, thời gian, loadState, các giai đoạn tương tác và nhiều thông tin khác (chẳng hạn như dữ liệu khung hoạt hoạ cần nhiều thời gian).

Bản dựng phân bổ web-vitals cho thấy thông tin phân bổ bổ sung, như trong ví dụ sau về INP:

import {onCLS, onINP, onLCP} from 'web-vitals/attribution';

function sendToGoogleAnalytics({name, value, id, attribution}) {
  const eventParams = {
    metric_value: value,
    metric_id: id,
  }

  switch (name) {
    case 'INP':
      eventParams.debug_target = attribution.interactionTarget;
      eventParams.debug_type = attribution.interactionType;
      eventParams.debug_time = attribution.interactionTime;
      eventParams.debug_load_state = attribution.loadState;
      eventParams.debug_interaction_delay = Math.round(attribution.inputDelay);
      eventParams.debug_processing_duration = Math.round(attribution.processingDuration);
      eventParams.debug_presentation_delay =  Math.round(attribution.presentationDelay);
      break;

    // Additional metric logic...
  }

  // Assumes the global `gtag()` function exists, see:
  // https://developers.google.com/analytics/devguides/collection/ga4
  gtag('event', name, eventParams);
}

onCLS(sendToGoogleAnalytics);
onLCP(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);

Hãy tham khảo tài liệu về việc phân bổ web-vitals để biết danh sách đầy đủ các tín hiệu gỡ lỗi được hiển thị.

Báo cáo và trực quan hoá dữ liệu

Sau khi bắt đầu thu thập thông tin gỡ lỗi cùng với các giá trị chỉ số, bước tiếp theo là tổng hợp dữ liệu của tất cả người dùng để bắt đầu tìm kiếm các mẫu và xu hướng.

Như đã đề cập trước đó, bạn không nhất thiết phải giải quyết từng vấn đề mà người dùng gặp phải. Thay vào đó, bạn nên giải quyết (đặc biệt là ban đầu) những vấn đề ảnh hưởng đến nhiều người dùng nhất, đồng thời cũng là những vấn đề có tác động tiêu cực lớn nhất đến điểm số Core Web Vitals.

Đối với GA4, hãy xem bài viết riêng về cách truy vấn và trực quan hoá dữ liệu bằng BigQuery.

Tóm tắt

Hy vọng bài đăng này đã giúp bạn nắm được những cách cụ thể để sử dụng các API hiệu suất hiện có và thư viện web-vitals nhằm nhận thông tin gỡ lỗi để giúp chẩn đoán hiệu suất dựa trên lượt truy cập của người dùng thực tế. Mặc dù hướng dẫn này tập trung vào Core Web Vitals, nhưng các khái niệm này cũng áp dụng cho việc gỡ lỗi mọi chỉ số hiệu suất có thể đo lường được bằng JavaScript.

Nếu bạn là nhà cung cấp dịch vụ phân tích và đang muốn cải thiện sản phẩm cũng như cung cấp thêm thông tin gỡ lỗi cho người dùng, hãy cân nhắc một số kỹ thuật được mô tả ở đây nhưng đừng chỉ giới hạn bản thân trong những ý tưởng được trình bày ở đây. Bài đăng này thường áp dụng cho tất cả các công cụ phân tích; tuy nhiên, từng công cụ phân tích có thể (và nên) thu thập cũng như báo cáo nhiều thông tin gỡ lỗi hơn.

Cuối cùng, nếu bạn cảm thấy có những điểm thiếu sót trong khả năng gỡ lỗi các chỉ số này do thiếu thông tin hoặc tính năng trong chính các API, hãy gửi ý kiến phản hồi của bạn đến web-vitals-feedback@googlegroups.com.