Tìm các hoạt động tương tác chậm trong trường

Tìm hiểu cách tìm lượt tương tác chậm trong dữ liệu trường trên trang web của bạn để tìm cơ hội cải thiện Lượt tương tác với nội dung hiển thị tiếp theo.

Dữ liệu trường là dữ liệu cho bạn biết trải nghiệm thực tế của người dùng trên trang web của bạn. Công cụ này hé lộ các vấn đề mà bạn không thể tìm thấy riêng trong dữ liệu phòng thí nghiệm. Trong trường hợp liên quan đến Tương tác với nội dung hiển thị tiếp theo (INP), dữ liệu thực địa là yếu tố cần thiết trong việc xác định các tương tác chậm, đồng thời cung cấp các gợi ý quan trọng để giúp bạn khắc phục các tương tác đó.

Trong hướng dẫn này, bạn sẽ tìm hiểu cách nhanh chóng đánh giá INP của trang web bằng cách sử dụng dữ liệu trường từ Báo cáo trải nghiệm người dùng trên Chrome (CrUX) để xem trang web của bạn có gặp vấn đề về INP hay không. Sau đó, bạn sẽ tìm hiểu cách sử dụng bản dựng phân bổ của thư viện JavaScript quan trọng trên web và những thông tin chi tiết mới mà thư viện này cung cấp từ API Khung ảnh động dài (LoAF) để thu thập và diễn giải dữ liệu trường cho các lượt tương tác chậm trên trang web của bạn.

Bắt đầu sử dụng CrUX để đánh giá INP của trang web

Nếu bạn không thu thập dữ liệu tại chỗ từ người dùng trang web của mình, thì CrUX có thể là một điểm khởi đầu phù hợp. CrUX thu thập dữ liệu tại trường từ những người dùng Chrome thực tế đã chọn gửi dữ liệu đo từ xa.

Dữ liệu CrUX xuất hiện ở một số khu vực, tuỳ thuộc vào phạm vi của thông tin bạn đang tìm kiếm. CrUX có thể cung cấp dữ liệu về INP và các Chỉ số quan trọng chính khác của trang web đối với:

  • Từng trang và toàn bộ nguồn gốc bằng PageSpeed Insights.
  • Loại trang. Ví dụ: nhiều trang web thương mại điện tử có loại Trang chi tiết sản phẩm và Trang danh sách sản phẩm. Bạn có thể xem dữ liệu CrUX cho các loại trang riêng biệt trong Search Console.

Để bắt đầu, bạn có thể nhập URL của trang web của mình trong PageSpeed Insights. Sau khi bạn nhập URL, dữ liệu trường liên quan (nếu có) sẽ hiển thị cho nhiều chỉ số, bao gồm cả INP. Bạn cũng có thể sử dụng nút bật/tắt để kiểm tra giá trị INP cho phương diện thiết bị di động và máy tính.

Dữ liệu trường do CrUX hiển thị trong PageSpeed Insights, cho thấy LCP, INP, CLS ở 3 Chỉ số quan trọng chính của trang web và TTFB, FCP làm chỉ số chẩn đoán và FID là chỉ số Chỉ số quan trọng chính của trang web không dùng nữa.
Đọc to dữ liệu CrUX như trong Thông tin chi tiết về tốc độ trang. Trong ví dụ này, INP của trang web nhất định cần được cải thiện.

Dữ liệu này rất hữu ích vì nó cho bạn biết nếu bạn gặp sự cố. Tuy nhiên, CrUX không thể cho bạn biết nguyên nhân gây ra vấn đề. Có nhiều giải pháp Giám sát người dùng thực (RUM) giúp bạn thu thập dữ liệu trường của riêng mình từ người dùng trên trang web để giúp bạn trả lời câu hỏi đó. Ngoài ra, có một lựa chọn là tự thu thập dữ liệu trường đó bằng thư viện JavaScript quan trọng.

Thu thập dữ liệu trường bằng thư viện JavaScript web-vitals

Thư viện JavaScript web-vitals là tập lệnh bạn có thể tải trên trang web của mình để thu thập dữ liệu trường từ người dùng trang web. Bạn có thể sử dụng công cụ này để ghi lại một số chỉ số, bao gồm cả INP trong các trình duyệt có hỗ trợ chỉ số này.

Hỗ trợ trình duyệt

  • 96
  • 96
  • x
  • x

Nguồn

Bạn có thể sử dụng bản dựng chuẩn của thư viện web-vitals để lấy dữ liệu INP cơ bản từ người dùng trong trường:

import {onINP} from 'web-vitals';

onINP(({name, value, rating}) => {
  console.log(name);    // 'INP'
  console.log(value);   // 512
  console.log(rating);  // 'poor'
});

Để phân tích dữ liệu trường của bạn từ người dùng, bạn sẽ muốn gửi dữ liệu này đến nơi nào đó:

import {onINP} from 'web-vitals';

onINP(({name, value, rating}) => {
  // Prepare JSON to be sent for collection. Note that
  // you can add anything else you'd want to collect here:
  const body = JSON.stringify({name, value, rating});

  // Use `sendBeacon` to send data to an analytics endpoint.
  // For Google Analytics, see https://github.com/GoogleChrome/web-vitals#send-the-results-to-google-analytics.
  navigator.sendBeacon('/analytics', body);
});

Tuy nhiên, chỉ riêng dữ liệu này không cho bạn biết nhiều thông tin hơn so với CrUX. Đây chính là lúc bạn cần tạo bản dựng phân bổ của thư viện web-vitals.

Tiến xa hơn với bản dựng phân bổ của thư viện web-vitals

Bản dựng phân bổ của thư viện web-vitals cung cấp dữ liệu bổ sung mà bạn có thể nhận được từ những người dùng trong hiện trường để giúp bạn khắc phục hiệu quả hơn những lượt tương tác có vấn đề đang ảnh hưởng đến INP của trang web. Bạn có thể truy cập dữ liệu này thông qua đối tượng attribution xuất hiện trong phương thức onINP() của thư viện:

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

onINP(({name, value, rating, attribution}) => {
  console.log(name);         // 'INP'
  console.log(value);        // 56
  console.log(rating);       // 'good'
  console.log(attribution);  // Attribution data object
});
Cách xuất hiện của nhật ký trên bảng điều khiển trong thư viện web-vitals. Bảng điều khiển trong ví dụ này hiển thị tên của chỉ số (INP), giá trị INP (56), trong đó giá trị đó nằm trong ngưỡng INP (tốt) và nhiều bit thông tin khác nhau được hiển thị trong đối tượng phân bổ, bao gồm các mục nhập từ Long Animation Frame API.
Cách dữ liệu của thư viện web-vitals xuất hiện trong bảng điều khiển.

Ngoài bản thân INP của trang, bản dựng phân bổ cung cấp nhiều dữ liệu bạn có thể sử dụng để giúp tìm hiểu lý do dẫn đến tương tác chậm, bao gồm phần nào của tương tác bạn nên tập trung vào. Công cụ này có thể giúp bạn trả lời các câu hỏi quan trọng như:

  • "Người dùng có tương tác với trang trong khi đang tải không?"
  • "Trình xử lý sự kiện của tương tác có chạy trong một thời gian dài không?"
  • "Mã trình xử lý sự kiện tương tác có bị trì hoãn bắt đầu không? Nếu có thì điều gì khác đang xảy ra trên luồng chính vào thời điểm đó?"
  • "Có phải sự tương tác đó gây ra nhiều công việc kết xuất khiến khung hình tiếp theo không được vẽ không?"

Bảng sau đây trình bày một số dữ liệu phân bổ cơ bản mà bạn có thể nhận được từ thư viện. Dữ liệu này có thể giúp bạn tìm ra một số nguyên nhân tổng quan gây ra tình trạng tương tác chậm trên trang web của mình:

Khoá đối tượng attribution Dữ liệu
interactionTarget Bộ chọn CSS trỏ đến phần tử đã tạo ra giá trị INP của trang – ví dụ: button#save.
interactionType Loại lượt tương tác, từ lượt nhấp, lượt nhấn hoặc hoạt động nhập bằng bàn phím.
inputDelay* Độ trễ đầu vào của lượt tương tác.
processingDuration* Khoảng thời gian từ khi trình nghe sự kiện đầu tiên bắt đầu chạy để phản hồi hoạt động tương tác của người dùng cho đến khi tất cả quá trình xử lý trình nghe sự kiện hoàn tất.
presentationDelay* Độ trễ trình bày của tương tác, diễn ra từ khi trình xử lý sự kiện kết thúc cho đến thời điểm hiển thị khung hình tiếp theo.
longAnimationFrameEntries* Các mục nhập từ LoAF được liên kết với hoạt động tương tác này. Xem phần tiếp theo để biết thêm thông tin.
*Tính năng mới trong phiên bản 4

Kể từ phiên bản 4 của thư viện web-vitals, bạn có thể hiểu rõ hơn nữa về các hoạt động tương tác có vấn đề thông qua dữ liệu mà thư viện này cung cấp cùng với thông tin chi tiết theo giai đoạn INP (độ trễ đầu vào, thời lượng xử lý và độ trễ trình bày) và API Khung ảnh động dài (LoAF).

API khung ảnh động dài (LoAF)

Hỗ trợ trình duyệt

  • 123
  • 123
  • x
  • x

Nguồn

Gỡ lỗi tương tác bằng dữ liệu trường là một nhiệm vụ khó khăn. Tuy nhiên, với dữ liệu từ LoAF, giờ đây bạn có thể hiểu rõ hơn về nguyên nhân gây ra tương tác chậm, vì LoAF hiển thị một số thời gian chi tiết và dữ liệu khác mà bạn có thể sử dụng để xác định nguyên nhân chính xác — và quan trọng hơn là nguồn gốc của vấn đề nằm ở mã trang web của bạn.

Bản dựng phân bổ của thư viện web-vitals hiển thị một mảng các mục nhập LoAF trong khoá longAnimationFrameEntries của đối tượng attribution. Bảng sau đây liệt kê một số bit dữ liệu chính mà bạn có thể tìm thấy trong mỗi mục nhập LoAF:

Khoá đối tượng mục nhập LoAF Dữ liệu
duration Thời lượng của khung hoạt ảnh dài, tính đến khi bố cục hoàn tất, nhưng không bao gồm việc vẽ và kết hợp.
blockingDuration Tổng thời gian trong khung hình mà trình duyệt không thể phản hồi nhanh do các tác vụ dài. Thời gian chặn này có thể bao gồm các tác vụ dài chạy JavaScript, cũng như bất kỳ tác vụ kết xuất mất thời gian dài nào tiếp theo trong khung hình.
firstUIEventTimestamp Dấu thời gian khi sự kiện được đưa vào hàng đợi trong khung hình. Được dùng để xác định thời điểm bắt đầu độ trễ đầu vào của một lượt tương tác.
startTime Dấu thời gian bắt đầu của khung.
renderStart Thời điểm quá trình kết xuất khung hình bắt đầu. Điều này bao gồm mọi lệnh gọi lại requestAnimationFrame (và lệnh gọi lại ResizeObserver nếu có), nhưng có thể trước khi bất kỳ tác vụ tạo kiểu/bố cục nào bắt đầu.
styleAndLayoutStart Khi hoạt động định kiểu/bố cục trong khung diễn ra. Có thể hữu ích trong việc tính toán độ dài của kiểu/bố cục công việc khi tính trong các dấu thời gian có sẵn khác.
scripts Một mảng các mục chứa thông tin phân bổ tập lệnh đóng góp vào INP của trang.
Hình ảnh một khung hoạt ảnh dài theo mô hình LoAF.
Sơ đồ thời gian của một khung ảnh động dài theo API LoAF (trừ blockingDuration).

Tất cả những thông tin này có thể cho bạn biết nhiều điều về nguyên nhân khiến tương tác bị chậm, nhưng bạn nên đặc biệt quan tâm đến mảng scripts mà các mục nhập LoAF hiển thị:

Khoá đối tượng phân bổ tập lệnh Dữ liệu
invoker Phương thức gọi. Hàm này có thể thay đổi tuỳ theo loại phương thức gọi được mô tả ở hàng tiếp theo. Ví dụ về phương thức gọi có thể là các giá trị như 'IMG#id.onload', 'Window.requestAnimationFrame' hoặc 'Response.json.then'.
invokerType Loại phương thức gọi. Giá trị này có thể là 'user-callback', 'event-listener', 'resolve-promise', 'reject-promise', 'classic-script' hoặc 'module-script'.
sourceURL URL đến tập lệnh nơi bắt nguồn của khung hoạt ảnh dài.
sourceCharPosition Vị trí ký tự trong tập lệnh do sourceURL xác định.
sourceFunctionName Tên của hàm trong tập lệnh đã xác định.

Mỗi mục trong mảng này chứa dữ liệu hiển thị trong bảng này. Dữ liệu này cung cấp cho bạn thông tin về tập lệnh gây ra tương tác chậm cũng như trách nhiệm của tập lệnh đó.

Đo lường và xác định các nguyên nhân phổ biến gây ra tương tác chậm

Để giúp bạn biết cách sử dụng thông tin này, giờ đây, hướng dẫn này sẽ trình bày cách bạn có thể sử dụng dữ liệu LoAF trong thư viện web-vitals để xác định một số nguyên nhân gây ra tình trạng tương tác chậm.

Thời gian xử lý dài

Thời gian xử lý của một lượt tương tác là thời gian cần thiết để các lệnh gọi lại trình xử lý sự kiện đã đăng ký của tương tác chạy đến khi hoàn tất và bất kỳ điều gì khác có thể xảy ra giữa các lệnh gọi lại đó. Thư viện web-vitals sẽ hiển thị thời lượng xử lý cao:

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

onINP(({name, value, attribution}) => {
  const {processingDuration} = attribution; // 512.5
});

Đương nhiên khi nghĩ rằng nguyên nhân chính khiến lượt tương tác chậm là do mã xử lý sự kiện mất quá nhiều thời gian để chạy, nhưng không phải lúc nào cũng đúng! Sau khi xác nhận đây là vấn đề, bạn có thể tìm hiểu kỹ hơn bằng dữ liệu LoAF:

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

onINP(({name, value, attribution}) => {
  const {processingDuration} = attribution; // 512.5

  // Get the longest script from LoAF covering `processingDuration`:
  const loaf = attribution.longAnimationFrameEntries.at(-1);
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  if (script) {
    // Get attribution for the long-running event handler:
    const {invokerType} = script;        // 'event-listener'
    const {invoker} = script;            // 'BUTTON#update.onclick'
    const {sourceURL} = script;          // 'https://example.com/app.js'
    const {sourceCharPosition} = script; // 83
    const {sourceFunctionName} = script; // 'update'
  }
});

Như bạn có thể thấy trong đoạn mã trước, bạn có thể làm việc với dữ liệu LoAF để theo dõi chính xác nguyên nhân đằng sau một tương tác có các giá trị thời lượng xử lý cao, bao gồm:

  • Phần tử và trình nghe sự kiện đã đăng ký của phần tử này.
  • Tệp tập lệnh và vị trí ký tự trong tệp đó chứa mã xử lý sự kiện chạy trong thời gian dài.
  • Tên hàm.

Loại dữ liệu này là vô giá. Bạn không còn cần phải tìm hiểu chính xác tương tác nào (hoặc trình xử lý sự kiện nào của tương tác) chịu trách nhiệm về các giá trị thời lượng xử lý cao. Ngoài ra, vì các tập lệnh bên thứ ba thường có thể đăng ký trình xử lý sự kiện của riêng họ, nên bạn có thể xác định xem liệu có phải mã của bạn chịu trách nhiệm hay không! Đối với mã mà bạn có quyền kiểm soát, bạn nên xem xét việc tối ưu hoá các tác vụ dài.

Độ trễ đầu vào dài

Mặc dù các trình xử lý sự kiện chạy trong thời gian dài là phổ biến, nhưng vẫn có những phần khác của hoạt động tương tác cần xem xét. Một phần xảy ra trước thời lượng xử lý, còn gọi là độ trễ đầu vào. Đây là khoảng thời gian từ khi người dùng bắt đầu tương tác cho đến khi các lệnh gọi lại trình xử lý sự kiện bắt đầu chạy và diễn ra khi luồng chính đang xử lý một tác vụ khác. Bản dựng phân bổ của thư viện web-vitals có thể cho bạn biết độ trễ đầu vào cho một lượt tương tác:

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

onINP(({name, value, attribution}) => {
  const {inputDelay} = attribution; // 125.59439536
});

Nếu nhận thấy một số lượt tương tác có độ trễ đầu vào cao, thì bạn cần tìm hiểu xem điều gì đang xảy ra trên trang tại thời điểm tương tác gây ra độ trễ đầu vào dài. Điều này thường tập trung vào việc liệu lượt tương tác xảy ra khi trang đang tải hay sau đó.

Có xảy ra trong khi tải trang không?

Luồng chính thường bận rộn nhất khi một trang đang tải. Trong thời gian này, tất cả các loại tác vụ đang được xếp hàng đợi cũng như được xử lý và nếu người dùng cố tương tác với trang trong khi tất cả công việc này đang diễn ra, điều đó có thể làm chậm tương tác. Những trang tải nhiều JavaScript có thể bắt đầu công việc biên dịch và đánh giá tập lệnh, cũng như thực thi các chức năng để chuẩn bị một trang sẵn sàng cho tương tác của người dùng. Công việc này có thể gây cản trở nếu người dùng tương tác khi hoạt động này xảy ra và bạn có thể tìm hiểu xem liệu đó có phải là trường hợp của người dùng trên trang web của bạn hay không:

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

onINP(({name, value, attribution}) => {
  const {inputDelay} = attribution; // 125.59439536

  // Get the longest script from the first LoAF entry:
  const loaf = attribution.longAnimationFrameEntries[0];
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  if (script) {
    // Invoker types can describe if script eval blocked the main thread:
    const {invokerType} = script;    // 'classic-script' | 'module-script'
    const {sourceLocation} = script; // 'https://example.com/app.js'
  }
});

Nếu bạn ghi lại dữ liệu này trong trường này và thấy độ trễ đầu vào cao cũng như các loại phương thức gọi 'classic-script' hoặc 'module-script', thì có thể công bằng mà nói rằng các tập lệnh trên trang web của bạn mất nhiều thời gian để đánh giá và đang chặn luồng chính đủ lâu để trì hoãn tương tác. Bạn có thể giảm thời gian chặn này bằng cách chia nhỏ các tập lệnh của mình thành các gói nhỏ hơn, trì hoãn tải mã không sử dụng ban đầu vào một thời điểm sau đó và kiểm tra trang web để tìm mã không sử dụng mà bạn có thể xoá hoàn toàn.

Có phải là sau khi tải trang không?

Mặc dù độ trễ đầu vào thường xảy ra khi trang đang tải, nhưng vẫn có khả năng xảy ra sau khi trang tải xong, do một nguyên nhân hoàn toàn khác. Các nguyên nhân phổ biến gây ra độ trễ đầu vào sau khi tải trang có thể là mã chạy định kỳ do lệnh gọi setInterval trước đó hoặc thậm chí là các lệnh gọi lại sự kiện đã được xếp hàng đợi để chạy trước đó nhưng vẫn đang xử lý.

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

onINP(({name, value, attribution}) => {
  const {inputDelay} = attribution; // 125.59439536

  // Get the longest script from the first LoAF entry:
  const loaf = attribution.longAnimationFrameEntries[0];
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  if (script) {
    const {invokerType} = script;        // 'user-callback'
    const {sourceURL} = script;          // 'https://example.com/app.js'
    const {sourceCharPosition} = script; // 83
    const {sourceFunctionName} = script; // 'update'
  }
});

Tương tự như trong trường hợp khắc phục sự cố các giá trị thời lượng xử lý cao, độ trễ đầu vào cao do những nguyên nhân đã đề cập trước đó sẽ cung cấp cho bạn dữ liệu phân bổ tập lệnh chi tiết. Tuy nhiên, điểm khác biệt là kiểu trình gọi sẽ thay đổi dựa trên bản chất của công việc làm trì hoãn tương tác:

  • 'user-callback' cho biết tác vụ chặn đến từ setInterval, setTimeout hoặc thậm chí là requestAnimationFrame.
  • 'event-listener' cho biết tác vụ chặn bắt nguồn từ một dữ liệu đầu vào trước đó đã được đưa vào hàng đợi và vẫn đang xử lý.
  • 'resolve-promise''reject-promise' có nghĩa là tác vụ chặn bắt nguồn từ một số công việc không đồng bộ đã được bắt đầu trước đó, và được giải quyết hoặc bị từ chối vào thời điểm người dùng cố gắng tương tác với trang, làm trì hoãn tương tác.

Trong mọi trường hợp, dữ liệu phân bổ của tập lệnh sẽ giúp bạn biết nên bắt đầu tìm kiếm ở đâu và liệu độ trễ đầu vào là do mã của chính bạn hay do tập lệnh của bên thứ ba.

Chậm trễ trong thời gian dài khi trình bày

Độ trễ trình bày là chặng cuối cùng của một tương tác và bắt đầu khi trình xử lý sự kiện của tương tác kết thúc, cho tới thời điểm khung tiếp theo được vẽ. Chúng xảy ra khi công việc trong trình xử lý sự kiện do một lượt tương tác làm thay đổi trạng thái hình ảnh của giao diện người dùng. Tương tự như thời lượng xử lý và độ trễ đầu vào, thư viện web-vitals có thể cho bạn biết độ trễ trình bày dành cho một lượt tương tác:

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

onINP(({name, value, attribution}) => {
  const {presentationDelay} = attribution; // 113.32307691
});

Nếu bạn ghi lại dữ liệu này và thấy các lượt tương tác góp phần dẫn đến INP của trang web có độ trễ cao trong việc trình bày, thì nguyên nhân có thể khác nhau, nhưng dưới đây là một vài nguyên nhân cần chú ý.

Công việc bố cục và kiểu dáng tốn kém

Sự chậm trễ trong thời gian dài có thể dẫn đến việc tính toán lại kiểubố cục tốn kém phát sinh từ một số nguyên nhân, trong đó có bộ chọn CSS phức tạp và kích thước DOM lớn. Bạn có thể đo lường thời lượng công việc này bằng dấu thời gian LoAF trong thư viện web-vitals:

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

onINP(({name, value, attribution}) => {
  const {presentationDelay} = attribution; // 113.32307691

  // Get the longest script from the last LoAF entry:
  const loaf = attribution.longAnimationFrameEntries.at(-1);
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  // Get necessary timings:
  const {startTime} = loaf; // 2120.5
  const {duration} = loaf;  // 1002

  // Figure out the ending timestamp of the frame (approximate):
  const endTime = startTime + duration; // 3122.5

  // Get the start timestamp of the frame's style/layout work:
  const {styleAndLayoutStart} = loaf; // 3011.17692309

  // Calculate the total style/layout duration:
  const styleLayoutDuration = endTime - styleAndLayoutStart; // 111.32307691

  if (script) {
    // Get attribution for the event handler that triggered
    // the long-running style and layout operation:
    const {invokerType} = script;        // 'event-listener'
    const {invoker} = script;            // 'BUTTON#update.onclick'
    const {sourceURL} = script;          // 'https://example.com/app.js'
    const {sourceCharPosition} = script; // 83
    const {sourceFunctionName} = script; // 'update'
  }
});

LoAF sẽ không cho bạn biết thời lượng của công việc kiểu và bố cục là dành cho một khung hình, nhưng sẽ cho bạn biết thời điểm bắt đầu. Với dấu thời gian bắt đầu này, bạn có thể sử dụng dữ liệu khác từ LoAF để tính toán thời lượng chính xác của tác vụ đó bằng cách xác định thời gian kết thúc của khung hình rồi trừ đi dấu thời gian bắt đầu của tác vụ kiểu và bố cục.

Các lệnh gọi lại requestAnimationFrame lâu dài

Một nguyên nhân có thể gây ra độ trễ khi trình bày lâu là do thực hiện quá nhiều công việc trong lệnh gọi lại requestAnimationFrame. Nội dung của lệnh gọi lại này được thực thi sau khi trình xử lý sự kiện chạy xong, nhưng ngay trước khi tính toán lại kiểu và bố cục.

Các lệnh gọi lại này có thể mất nhiều thời gian để hoàn tất nếu công việc được thực hiện trong chúng phức tạp. Nếu nghi ngờ có giá trị độ trễ khi trình bày cao là do bạn đang xử lý requestAnimationFrame, thì bạn có thể sử dụng dữ liệu LoAF do thư viện web-vitals hiển thị để xác định các trường hợp sau:

onINP(({name, value, attribution}) => {
  const {presentationDelay} = attribution; // 543.1999999880791

  // Get the longest script from the last LoAF entry:
  const loaf = attribution.longAnimationFrameEntries.at(-1);
  const script = loaf?.scripts.sort((a, b) => b.duration - a.duration)[0];

  // Get the render start time and when style and layout began:
  const {renderStart} = loaf;         // 2489
  const {styleAndLayoutStart} = loaf; // 2989.5999999940395

  // Calculate the `requestAnimationFrame` callback's duration:
  const rafDuration = styleAndLayoutStart - renderStart; // 500.59999999403954

  if (script) {
    // Get attribution for the event handler that triggered
    // the long-running requestAnimationFrame callback:
    const {invokerType} = script;        // 'user-callback'
    const {invoker} = script;            // 'FrameRequestCallback'
    const {sourceURL} = script;          // 'https://example.com/app.js'
    const {sourceCharPosition} = script; // 83
    const {sourceFunctionName} = script; // 'update'
  }
});

Nếu bạn thấy một phần đáng kể thời gian trễ khi trình bày được dành cho lệnh gọi lại requestAnimationFrame, hãy đảm bảo công việc bạn đang thực hiện trong các lệnh gọi lại này chỉ giới hạn ở việc thực hiện tác vụ dẫn đến việc cập nhật thực tế giao diện người dùng. Bất kỳ tác vụ nào khác không chạm vào DOM hoặc cập nhật kiểu sẽ làm chậm trễ khung tiếp theo được vẽ một cách không cần thiết, vì vậy hãy cẩn thận!

Kết luận

Dữ liệu trường là nguồn thông tin tốt nhất mà bạn có thể sử dụng để hiểu những tương tác nào gây ra vấn đề cho người dùng thực tế trong trường. Bằng cách dựa vào các công cụ thu thập dữ liệu trường, chẳng hạn như thư viện JavaScript web-vitals (hoặc nhà cung cấp RUM), bạn có thể tự tin hơn về những hoạt động tương tác nào gây nhiều vấn đề nhất, sau đó chuyển sang tái tạo những hoạt động tương tác có vấn đề trong phòng thí nghiệm rồi tiến hành khắc phục các hoạt động tương tác đó.

Hình ảnh chính của Unsplash, của Federico Respini.