API Khung hoạt ảnh dài

Long Animation Frames API (LoAF – phát âm là Lo-Af) là một bản cập nhật cho Long Tasks API để giúp bạn hiểu rõ hơn về các bản cập nhật giao diện người dùng (UI) bị chậm. Điều này có thể hữu ích để xác định các khung ảnh động chậm có khả năng ảnh hưởng đến chỉ số Lượt tương tác đến nội dung hiển thị tiếp theo (INP) trong Chỉ số quan trọng chính của trang web, chỉ số này đo lường khả năng phản hồi, hoặc để xác định các hiện tượng giật khác trên giao diện người dùng ảnh hưởng đến độ mượt mà.

Trạng thái của API

Hỗ trợ trình duyệt

  • Chrome: 123.
  • Edge: 123.
  • Firefox: không được hỗ trợ.
  • Safari: không được hỗ trợ.

Nguồn

Sau một bản dùng thử theo nguyên gốc từ Chrome 116 đến Chrome 122, LoAF API đã được phát hành từ Chrome 123.

Nền: API Tác vụ dài

Hỗ trợ trình duyệt

  • Chrome: 58.
  • Edge: 79.
  • Firefox: không được hỗ trợ.
  • Safari: không được hỗ trợ.

Nguồn

API Khung ảnh động dài là một giải pháp thay thế cho API Tác vụ dài đã có trong Chrome được một thời gian (kể từ Chrome 58). Như tên gọi, Long Task API (API Tác vụ dài) cho phép bạn theo dõi các tác vụ dài, tức là các tác vụ chiếm luồng chính trong vòng 50 mili giây trở lên. Bạn có thể theo dõi các tác vụ dài bằng giao diện PerformanceLongTaskTiming, với PeformanceObserver:

const observer = new PerformanceObserver((list) => {
  console.log(list.getEntries());
});

observer.observe({ type: 'longtask', buffered: true });

Các tác vụ dài có thể gây ra vấn đề về khả năng phản hồi. Nếu người dùng cố gắng tương tác với một trang (ví dụ: nhấp vào một nút hoặc mở một trình đơn) nhưng luồng chính đang xử lý một tác vụ dài, thì hành động tương tác của người dùng sẽ bị trì hoãn để chờ tác vụ đó hoàn tất.

Để cải thiện khả năng phản hồi, bạn thường nên chia nhỏ các tác vụ dài. Nếu mỗi tác vụ dài được chia thành một loạt nhiều tác vụ nhỏ hơn, thì điều này có thể cho phép thực thi các tác vụ quan trọng hơn ở giữa các tác vụ đó để tránh bị trễ đáng kể trong việc phản hồi các lượt tương tác.

Vì vậy, khi cố gắng cải thiện khả năng phản hồi, nỗ lực đầu tiên thường là chạy dấu vết hiệu suất và xem xét các tác vụ dài. Bạn có thể thực hiện việc này thông qua một công cụ kiểm tra dựa trên phòng thí nghiệm như Lighthouse (có quy trình kiểm tra Tránh các tác vụ dài trong luồng chính) hoặc bằng cách xem các tác vụ dài trong Công cụ dành cho nhà phát triển của Chrome.

Việc kiểm thử dựa trên phòng thí nghiệm thường không phải là điểm khởi đầu tốt để xác định các vấn đề về khả năng phản hồi, vì các công cụ này có thể không bao gồm các hoạt động tương tác. Nếu có, thì đó chỉ là một tập hợp con nhỏ các hoạt động tương tác có thể xảy ra. Lý tưởng nhất là bạn sẽ đo lường các nguyên nhân gây ra tình trạng tương tác chậm trong thực tế.

Điểm hạn chế của Long Tasks API

Việc đo lường các tác vụ dài trong trường bằng Trình quan sát hiệu suất chỉ hữu ích ở một mức độ nào đó. Trên thực tế, thông tin này không cung cấp nhiều thông tin ngoài việc một tác vụ dài đã xảy ra và mất bao lâu.

Các công cụ Theo dõi người dùng thực (RUM) thường sử dụng chỉ số này để theo dõi xu hướng về số lượng hoặc thời lượng của các tác vụ dài hoặc xác định những trang mà các tác vụ dài đó xảy ra. Tuy nhiên, nếu không có thông tin chi tiết cơ bản về nguyên nhân gây ra tác vụ dài, thì chỉ số này chỉ có thể sử dụng ở mức hạn chế. API Tác vụ dài chỉ có một mô hình phân bổ cơ bản, tốt nhất chỉ cho bạn biết vùng chứa mà tác vụ dài đã xảy ra (tài liệu cấp cao nhất hoặc <iframe>), nhưng không phải tập lệnh hoặc hàm đã gọi vùng chứa đó, như trong mục nhập thông thường:

{
  "name": "unknown",
  "entryType": "longtask",
  "startTime": 31.799999997019768,
  "duration": 136,
  "attribution": [
    {
      "name": "unknown",
      "entryType": "taskattribution",
      "startTime": 0,
      "duration": 0,
      "containerType": "window",
      "containerSrc": "",
      "containerId": "",
      "containerName": ""
    }
  ]
}

API Tác vụ dài cũng là một chế độ xem chưa hoàn chỉnh vì API này cũng có thể loại trừ một số tác vụ quan trọng. Một số nội dung cập nhật (chẳng hạn như kết xuất) xảy ra trong các tác vụ riêng biệt. Tốt nhất là bạn nên đưa các tác vụ này cùng với quá trình thực thi trước đó đã gây ra nội dung cập nhật đó vào để đo lường chính xác "tổng công việc" cho lượt tương tác đó. Để biết thêm thông tin chi tiết về các hạn chế khi dựa vào tác vụ, hãy xem phần "Những hạn chế của tác vụ dài" trong nội dung giải thích.

Vấn đề cuối cùng là việc đo lường các tác vụ dài chỉ báo cáo về các tác vụ riêng lẻ mất nhiều thời gian hơn giới hạn 50 mili giây. Một khung ảnh động có thể bao gồm một số tác vụ nhỏ hơn giới hạn 50 mili giây này, nhưng tổng thể vẫn chặn khả năng hiển thị của trình duyệt.

API Khung ảnh động dài

Hỗ trợ trình duyệt

  • Chrome: 123.
  • Edge: 123.
  • Firefox: không được hỗ trợ.
  • Safari: không được hỗ trợ.

Nguồn

Long Animation Frames API (LoAF) là một API mới nhằm giải quyết một số điểm yếu của Long Tasks API để nhà phát triển có thể nhận được thông tin chi tiết hữu ích hơn để giải quyết các vấn đề về khả năng phản hồi và cải thiện INP, cũng như nhận thông tin chi tiết về các vấn đề về độ mượt.

Tốc độ phản hồi tốt có nghĩa là trang phản hồi nhanh các lượt tương tác với trang đó. Điều đó liên quan đến việc có thể vẽ mọi nội dung cập nhật mà người dùng cần một cách kịp thời và tránh chặn các nội dung cập nhật này. Đối với INP, bạn nên phản hồi trong vòng 200 mili giây trở xuống, nhưng đối với các nội dung cập nhật khác (ví dụ: ảnh động), ngay cả 200 mili giây cũng có thể là quá lâu.

API Khung ảnh động dài là một phương pháp thay thế để đo lường công việc chặn. Thay vì đo lường từng tác vụ, API Khung ảnh động dài (như tên gọi) đo lường khung ảnh động dài. Khung ảnh động dài là khi bản cập nhật kết xuất bị trì hoãn quá 50 mili giây (tương tự như ngưỡng cho API Tác vụ dài).

Khung ảnh động dài được đo từ khi bắt đầu các tác vụ cần kết xuất. Nếu tác vụ đầu tiên trong khung ảnh động dài tiềm năng không yêu cầu kết xuất, thì khung ảnh động dài sẽ kết thúc sau khi hoàn tất tác vụ không kết xuất và một khung ảnh động dài tiềm năng mới sẽ bắt đầu với tác vụ tiếp theo. Khung ảnh động dài không kết xuất như vậy vẫn được đưa vào API Khung ảnh động dài khi lớn hơn 50 mili giây (với thời gian renderStart là 0) để cho phép đo lường công việc có thể chặn.

Bạn có thể quan sát các khung ảnh động dài theo cách tương tự như các tác vụ dài bằng PerformanceObserver, nhưng hãy xem loại long-animation-frame:

const observer = new PerformanceObserver((list) => {
  console.log(list.getEntries());
});

observer.observe({ type: 'long-animation-frame', buffered: true });

Bạn cũng có thể truy vấn các khung ảnh động dài trước đó từ Dòng thời gian hiệu suất như sau:

const loafs = performance.getEntriesByType('long-animation-frame');

Tuy nhiên, có một maxBufferSize cho các mục nhập hiệu suất, sau đó các mục nhập mới hơn sẽ bị loại bỏ, vì vậy, phương pháp PerformanceObserver là phương pháp được đề xuất. Kích thước vùng đệm long-animation-frame được đặt thành 200, giống như đối với long-tasks.

Ưu điểm của việc xem xét khung hình thay vì tác vụ

Ưu điểm chính của việc xem xét vấn đề này từ góc độ khung hình thay vì góc độ tác vụ là ảnh động dài có thể được tạo thành từ bất kỳ số lượng tác vụ nào tích luỹ được trong một khung ảnh động dài. Điều này giải quyết điểm cuối cùng được đề cập trước đó, trong đó tổng của nhiều tác vụ nhỏ hơn, chặn kết xuất trước khi khung ảnh động có thể không được API Tác vụ dài hiển thị.

Một ưu điểm khác của chế độ xem thay thế này đối với các tác vụ dài là khả năng cung cấp thông tin chi tiết về thời gian của toàn bộ khung. Thay vì chỉ bao gồm startTimeduration, như API Tác vụ dài, LoAF bao gồm bảng chi tiết chi tiết hơn nhiều về các phần khác nhau của thời lượng khung hình.

Dấu thời gian và thời lượng của khung hình

  • startTime: thời gian bắt đầu của khung ảnh động dài so với thời gian bắt đầu điều hướng.
  • duration: thời lượng của khung ảnh động dài (không bao gồm thời gian trình bày).
  • renderStart: thời gian bắt đầu của chu kỳ kết xuất, bao gồm các lệnh gọi lại requestAnimationFrame, tính toán kiểu và bố cục, lệnh gọi lại trình quan sát đổi kích thước và trình quan sát giao nhau.
  • styleAndLayoutStart: thời điểm bắt đầu khoảng thời gian dành cho việc tính toán kiểu và bố cục.
  • firstUIEventTimestamp: thời gian của sự kiện giao diện người dùng đầu tiên (chuột/bàn phím, v.v.) sẽ được xử lý trong quá trình của khung này.
  • blockingDuration: tổng thời lượng tính bằng mili giây mà khung ảnh động sẽ chặn quá trình xử lý dữ liệu đầu vào hoặc các tác vụ ưu tiên cao khác.

Giải thích về blockingDuration

Một khung ảnh động dài có thể được tạo thành từ một số tác vụ. blockingDuration là tổng thời lượng của các tác vụ dài hơn 50 mili giây (bao gồm cả thời lượng kết xuất cuối cùng trong tác vụ dài nhất).

Ví dụ: nếu một khung ảnh động dài được tạo thành từ hai tác vụ là 55 mili giây và 65 mili giây, theo sau là một khung hiển thị 20 mili giây, thì duration sẽ là khoảng 140 mili giây với blockingDuration là (55 – 50) + (65 + 20 – 50) = 40 mili giây. Trong 40 mili giây trong khung ảnh động dài 140 mili giây này, khung ảnh được coi là bị chặn xử lý dữ liệu đầu vào.

Xem duration hay blockingDuration

Đối với màn hình 60 hertz phổ biến, trình duyệt sẽ cố gắng lên lịch một khung hình ít nhất 16,66 mili giây một lần (để đảm bảo cập nhật mượt mà) hoặc sau một tác vụ có mức độ ưu tiên cao như xử lý đầu vào (để đảm bảo cập nhật thích ứng). Tuy nhiên, nếu không có dữ liệu đầu vào hoặc tác vụ ưu tiên cao nào khác nhưng có hàng đợi tác vụ khác, thì trình duyệt thường sẽ tiếp tục khung hình hiện tại sau 16,66 mili giây, bất kể các tác vụ trong đó được phân chia tốt đến mức nào. Tức là trình duyệt sẽ luôn cố gắng ưu tiên đầu vào, nhưng có thể chọn xử lý hàng đợi tác vụ thay vì cập nhật kết xuất. Điều này là do quá trình kết xuất là một quá trình tốn kém, vì vậy, việc xử lý một tác vụ kết xuất kết hợp cho nhiều tác vụ thường dẫn đến việc giảm tổng thể công việc.

Do đó, các khung ảnh động dài có blockingDuration thấp hoặc bằng 0 vẫn sẽ phản hồi với hoạt động đầu vào. Do đó, việc giảm hoặc loại bỏ blockingDuration bằng cách chia nhỏ các tác vụ dài là yếu tố then chốt để cải thiện khả năng phản hồi được đo lường bằng INP.

Tuy nhiên, nhiều khung ảnh động dài, bất kể blockingDuration cho biết các bản cập nhật giao diện người dùng bị trì hoãn và do đó vẫn có thể ảnh hưởng đến độ mượt mà và khiến người dùng có cảm giác giao diện người dùng bị giật khi cuộn hoặc ảnh động, ngay cả khi những vấn đề này ít ảnh hưởng đến khả năng phản hồi được đo lường bằng INP. Để hiểu các vấn đề trong lĩnh vực này, hãy xem duration, nhưng những vấn đề này có thể khó tối ưu hoá hơn vì bạn không thể giải quyết vấn đề này bằng cách chia nhỏ công việc, mà phải giảm công việc.

Thời gian kết xuất khung hình

Dấu thời gian được đề cập trước đó cho phép khung ảnh động dài được chia thành các thời gian:

Thời gian Cách tính
Thời gian bắt đầu startTime
Thời gian kết thúc startTime + duration
Thời lượng công việc renderStart ? renderStart - startTime : duration
Thời lượng kết xuất renderStart ? (startTime + duration) - renderStart: 0
Kết xuất: Thời lượng trước bố cục styleAndLayoutStart ? styleAndLayoutStart - renderStart : 0
Kết xuất: Thời lượng của bố cục và kiểu styleAndLayoutStart ? (startTime + duration) - styleAndLayoutStart : 0

Phân bổ tập lệnh hiệu quả hơn

Loại mục nhập long-animation-frame bao gồm dữ liệu phân bổ tốt hơn của từng tập lệnh đã đóng góp vào một khung ảnh động dài (đối với các tập lệnh dài hơn 5 mili giây).

Tương tự như API Tác vụ dài, thông tin này sẽ được cung cấp trong một mảng các mục phân bổ, mỗi mục sẽ có thông tin chi tiết về:

  • nameEntryType đều sẽ trả về script.
  • invoker có ý nghĩa, cho biết cách gọi tập lệnh (ví dụ: 'IMG#id.onload', 'Window.requestAnimationFrame' hoặc 'Response.json.then').
  • invokerType của điểm truy cập tập lệnh:
    • user-callback: Lệnh gọi lại đã biết được đăng ký từ API nền tảng web (ví dụ: setTimeout, requestAnimationFrame).
    • event-listener: Trình nghe sự kiện nền tảng (ví dụ: click, load, keyup).
    • resolve-promise: Trình xử lý của một lời hứa trên nền tảng (ví dụ: fetch(). Lưu ý rằng trong trường hợp của các lời hứa, tất cả các trình xử lý của cùng một lời hứa được kết hợp với nhau dưới dạng một "tập lệnh").
    • reject-promise: Tương tự như resolve-promise, nhưng dành cho trường hợp từ chối.
    • classic-script: Đánh giá tập lệnh (ví dụ: <script> hoặc import())
    • module-script: Tương tự như classic-script, nhưng dành cho tập lệnh mô-đun.
  • Tách dữ liệu thời gian cho tập lệnh đó:
    • startTime: Thời gian gọi hàm nhập.
    • duration: Khoảng thời gian từ startTime đến khi hàng đợi tác vụ vi mô tiếp theo xử lý xong.
    • executionStart: Thời gian sau khi biên dịch.
    • forcedStyleAndLayoutDuration: Tổng thời gian xử lý bố cục và kiểu buộc bên trong hàm này (xem tình trạng nhồi nhét).
    • pauseDuration: Tổng thời gian dành cho các thao tác đồng bộ "tạm dừng" (cảnh báo, XHR đồng bộ).
  • Thông tin chi tiết về nguồn tập lệnh:
    • sourceURL: Tên tài nguyên tập lệnh (nếu có) (hoặc để trống nếu không tìm thấy).
    • sourceFunctionName: Tên hàm tập lệnh (nếu có) (hoặc để trống nếu không tìm thấy).
    • sourceCharPosition: Vị trí ký tự tập lệnh (nếu có) (hoặc -1 nếu không tìm thấy).
  • windowAttribution: Vùng chứa (tài liệu cấp cao nhất hoặc <iframe>) nơi xảy ra khung ảnh động dài.
  • window: Tham chiếu đến cửa sổ cùng nguồn gốc.

Nếu được cung cấp, các mục nhập nguồn cho phép nhà phát triển biết chính xác cách mỗi tập lệnh trong khung ảnh động dài được gọi, cho đến vị trí ký tự trong tập lệnh gọi. Thông tin này cho biết vị trí chính xác trong tài nguyên JavaScript dẫn đến khung ảnh động dài.

Ví dụ về mục nhập hiệu suất long-animation-frame

Ví dụ về mục nhập hiệu suất long-animation-frame đầy đủ, chứa một tập lệnh duy nhất:

{
  "blockingDuration": 0,
  "duration": 60,
  "entryType": "long-animation-frame",
  "firstUIEventTimestamp": 11801.099999999627,
  "name": "long-animation-frame",
  "renderStart": 11858.800000000745,
  "scripts": [
    {
      "duration": 45,
      "entryType": "script",
      "executionStart": 11803.199999999255,
      "forcedStyleAndLayoutDuration": 0,
      "invoker": "DOMWindow.onclick",
      "invokerType": "event-listener",
      "name": "script",
      "pauseDuration": 0,
      "sourceURL": "https://web.dev/js/index-ffde4443.js",
      "sourceFunctionName": "myClickHandler",
      "sourceCharPosition": 17796,
      "startTime": 11803.199999999255,
      "window": [Window object],
      "windowAttribution": "self"
    }
  ],
  "startTime": 11802.400000000373,
  "styleAndLayoutStart": 11858.800000000745
}

Như bạn có thể thấy, điều này cung cấp một lượng dữ liệu chưa từng có để các trang web có thể hiểu được nguyên nhân gây ra tình trạng cập nhật kết xuất bị giật.

Sử dụng API Khung ảnh động dài trong trường

Các công cụ như Công cụ của Chrome cho nhà phát triển và Lighthouse (dù hữu ích trong việc phát hiện và tái hiện vấn đề) là các công cụ trong phòng thí nghiệm có thể bỏ lỡ các khía cạnh quan trọng của trải nghiệm người dùng mà chỉ dữ liệu thực tế mới có thể cung cấp.

API Khung ảnh động dài được thiết kế để sử dụng trong trường hợp thực tế nhằm thu thập dữ liệu theo ngữ cảnh quan trọng cho các lượt tương tác của người dùng mà API Tác vụ dài không thể làm được. Điều này có thể giúp bạn xác định và tái hiện các vấn đề về khả năng tương tác mà bạn có thể không phát hiện được.

Tính năng phát hiện tính năng hỗ trợ API Khung ảnh động dài

Bạn có thể sử dụng mã sau để kiểm tra xem API có được hỗ trợ hay không:

if (PerformanceObserver.supportedEntryTypes.includes('long-animation-frame')) {
  // Monitor LoAFs
}

Trường hợp sử dụng rõ ràng nhất của API Khung ảnh động dài là giúp chẩn đoán và khắc phục các vấn đề về Tương tác với lần vẽ tiếp theo (INP). Đó là một trong những lý do chính khiến nhóm Chrome phát triển API này. INP tốt là khi tất cả các lượt tương tác được phản hồi trong vòng 200 mili giây kể từ khi tương tác cho đến khi khung hình được vẽ. Vì API Khung ảnh động dài đo lường tất cả các khung hình mất 50 mili giây trở lên, nên hầu hết các INP có vấn đề đều phải bao gồm dữ liệu LoAF để giúp bạn chẩn đoán các lượt tương tác đó.

"INP LoAF" là LoAF bao gồm hoạt động tương tác INP, như trong sơ đồ sau:

Ví dụ về các khung ảnh động dài trên một trang, trong đó LoAF INP được làm nổi bật.
Một trang có thể có nhiều LoAF, trong đó một LoAF liên quan đến lượt tương tác INP.

Trong một số trường hợp, sự kiện INP có thể trải dài trên hai LoAF – thường là nếu lượt tương tác xảy ra sau khi khung đã bắt đầu phần kết xuất của khung trước đó, do đó, trình xử lý sự kiện sẽ được xử lý trong khung tiếp theo:

Ví dụ về các khung ảnh động dài trên một trang, trong đó LoAF INP được làm nổi bật.
Một trang có thể có nhiều LoAF, trong đó một LoAF liên quan đến lượt tương tác INP.

Thậm chí, trong một số ít trường hợp, một phiên bản có thể trải dài trên nhiều LoAF.

Việc ghi lại dữ liệu LoAF liên kết với lượt tương tác INP cho phép bạn nhận được nhiều thông tin hơn về lượt tương tác INP để giúp chẩn đoán lượt tương tác đó. Điều này đặc biệt hữu ích để hiểu độ trễ đầu vào: vì bạn có thể thấy những tập lệnh khác đang chạy trong khung đó.

Bạn cũng có thể hiểu rõ thời gian xử lýđộ trễ hiển thị không giải thích được nếu trình xử lý sự kiện không tái tạo các giá trị được thấy cho những giá trị đó vì các tập lệnh khác có thể đang chạy cho người dùng của bạn và có thể không được đưa vào quy trình kiểm thử của riêng bạn.

Không có API trực tiếp nào để liên kết một mục nhập INP với mục nhập hoặc các mục nhập LoAF liên quan, mặc dù bạn có thể thực hiện việc này trong mã bằng cách so sánh thời gian bắt đầu và kết thúc của từng mục (xem tập lệnh ví dụ WhyNp). Thư viện web-vitals bao gồm tất cả các LoAF giao nhau trong thuộc tính longAnimationFramesEntries của giao diện phân bổ INP từ phiên bản 4.

Sau khi liên kết mục nhập LoAF, bạn có thể thêm thông tin có mô hình phân bổ INP. Đối tượng scripts chứa một số thông tin có giá trị nhất vì đối tượng này có thể cho biết những hoạt động khác đang chạy trong các khung đó. Vì vậy, việc gửi lại dữ liệu đó đến dịch vụ phân tích sẽ giúp bạn hiểu rõ hơn về lý do khiến các lượt tương tác bị chậm.

Việc báo cáo LoAF cho lượt tương tác INP là một cách hay để tìm ra những vấn đề về khả năng tương tác cấp thiết nhất trên trang của bạn. Mỗi người dùng có thể tương tác với trang của bạn theo cách khác nhau và với đủ lượng dữ liệu phân bổ INP, một số vấn đề tiềm ẩn sẽ được đưa vào dữ liệu phân bổ INP. Thao tác này cho phép bạn sắp xếp tập lệnh theo số lượng để xem tập lệnh nào có liên quan đến INP chậm.

Báo cáo thêm dữ liệu ảnh động dài về một điểm cuối phân tích

Một nhược điểm của việc chỉ xem(các) LoAF INP là bạn có thể bỏ lỡ các khía cạnh tiềm năng khác để cải thiện có thể gây ra vấn đề về INP trong tương lai. Điều này có thể khiến bạn cảm thấy như đang chạy theo đuôi khi bạn khắc phục một vấn đề về INP và mong đợi thấy sự cải thiện đáng kể, nhưng lại thấy lượt tương tác chậm nhất tiếp theo chỉ tốt hơn một chút so với lượt tương tác đó, vì vậy, INP của bạn không cải thiện nhiều.

Vì vậy, thay vì chỉ xem xét LoAF INP, bạn nên xem xét tất cả LoAF trong suốt thời gian hoạt động của trang:

Một trang có nhiều LoAF, một số trong đó xảy ra trong quá trình tương tác ngay cả khi không phải là lượt tương tác INP.
Việc xem xét tất cả LoAF có thể giúp xác định các vấn đề về INP trong tương lai.

Tuy nhiên, mỗi mục nhập LoAF chứa một lượng dữ liệu đáng kể, vì vậy, bạn có thể chỉ muốn giới hạn việc phân tích ở một số LoAF. Ngoài ra, vì các mục khung ảnh động dài có thể khá lớn, nên nhà phát triển cần quyết định dữ liệu nào trong mục đó sẽ được gửi đến công cụ phân tích. Ví dụ: thời gian tóm tắt của mục nhập và có thể là tên tập lệnh hoặc một số tập hợp tối thiểu khác của dữ liệu theo ngữ cảnh khác có thể được coi là cần thiết.

Một số mẫu được đề xuất để giảm lượng dữ liệu khung ảnh động dài bao gồm:

Mẫu nào trong số này phù hợp nhất với bạn còn tuỳ thuộc vào mức độ tối ưu hoá của bạn và mức độ phổ biến của khung ảnh động dài. Đối với một trang web chưa từng được tối ưu hoá để phản hồi, có thể có nhiều LoAF. Bạn nên chỉ giới hạn ở những LoAF có lượt tương tác, hoặc đặt ngưỡng cao hoặc chỉ xem xét những LoAF tệ nhất.

Khi giải quyết các vấn đề thường gặp về khả năng phản hồi, bạn có thể mở rộng phạm vi này bằng cách không chỉ giới hạn ở các lượt tương tác hoặc thời lượng chặn cao hoặc bằng cách hạ thấp ngưỡng.

Quan sát các khung ảnh động dài có tương tác

Để có thông tin chi tiết không chỉ về khung ảnh động dài INP, bạn có thể xem tất cả LoAF có lượt tương tác (có thể được phát hiện bằng sự hiện diện của giá trị firstUIEventTimestamp) với blockingDuration cao.

Đây cũng có thể là một phương pháp dễ dàng hơn để theo dõi LoAF INP thay vì cố gắng liên hệ hai phương pháp này với nhau, điều này có thể phức tạp hơn. Trong hầu hết các trường hợp, báo cáo này sẽ bao gồm LoAF INP cho một lượt truy cập nhất định. Trong một số ít trường hợp, báo cáo này vẫn hiển thị các lượt tương tác dài cần khắc phục, vì đó có thể là lượt tương tác INP cho người dùng khác.

Mã sau đây ghi lại tất cả các mục nhập LoAF có blockingDuration lớn hơn 100 mili giây, trong đó có một lượt tương tác xảy ra trong khung. Giá trị 100 được chọn ở đây vì nó nhỏ hơn ngưỡng INP "tốt" là 200 mili giây. Bạn có thể chọn một giá trị cao hơn hoặc thấp hơn tuỳ theo nhu cầu của mình.

const REPORTING_THRESHOLD_MS = 100;

const observer = new PerformanceObserver(list => {
  for (const entry of list.getEntries()) {
    if (entry.blockingDuration > REPORTING_THRESHOLD_MS &&
      entry.firstUIEventTimestamp > 0
    ) {
      // Example here logs to console, but could also report back to analytics
      console.log(entry);
    }
  }
});
observer.observe({ type: 'long-animation-frame', buffered: true });

Quan sát các khung ảnh động dài có thời lượng chặn cao

Để cải thiện việc xem tất cả khung ảnh động dài có tương tác, bạn nên xem tất cả khung ảnh động dài có thời lượng chặn cao. Những thông tin này cho biết các vấn đề tiềm ẩn về INP nếu người dùng tương tác trong các khung ảnh động dài này.

Mã sau đây ghi lại tất cả các mục LoAF có thời lượng chặn lớn hơn 100 mili giây, trong đó có một lượt tương tác xảy ra trong khung. Giá trị 100 được chọn ở đây vì nhỏ hơn ngưỡng INP "tốt" 200 mili giây để giúp xác định các khung hình có thể gặp vấn đề, đồng thời giữ cho số lượng khung hình ảnh động dài được báo cáo ở mức tối thiểu. Bạn có thể chọn một giá trị cao hơn hoặc thấp hơn tuỳ theo nhu cầu của mình.

const REPORTING_THRESHOLD_MS = 100;

const observer = new PerformanceObserver(list => {
  for (const entry of list.getEntries()) {
    if (entry.blockingDuration > REPORTING_THRESHOLD_MS) {
      // Example here logs to console, but could also report back to analytics
      console.log(entry);
    }
  }
});
observer.observe({ type: 'long-animation-frame', buffered: true });

Quan sát các khung ảnh động dài trong quá trình cập nhật giao diện người dùng quan trọng để cải thiện độ mượt mà

Như đã đề cập trước đó, việc xem xét các khung ảnh động dài có thời lượng chặn cao có thể giúp giải quyết vấn đề về khả năng phản hồi đầu vào. Tuy nhiên, để có độ mượt mà, bạn nên xem tất cả các khung ảnh động dài có duration dài.

Vì điều này có thể gây ra nhiều tạp âm, nên bạn nên giới hạn việc đo lường các điểm này ở các điểm chính theo mẫu như sau:

const REPORTING_THRESHOLD_MS = 100;

const observer = new PerformanceObserver(list => {
  if (measureImportantUIupdate) {
    for (const entry of list.getEntries()) {
      if (entry.duration > REPORTING_THRESHOLD_MS) {
        // Example here logs to console, but could also report back to analytics
        console.log(entry);
      }
    }
  }
});
observer.observe({ type: 'long-animation-frame', buffered: true });

async function doUIUpdatesWithMeasurements() {
  measureImportantUIupdate = true;
  await doUIUpdates();
  measureImportantUIupdate = false;
}

Quan sát các khung ảnh động dài nhất

Thay vì đặt ngưỡng, các trang web có thể muốn thu thập dữ liệu về (các) khung ảnh động dài nhất để giảm lượng dữ liệu cần được truyền qua beacon. Vì vậy, bất kể một trang có bao nhiêu khung ảnh động dài, chỉ dữ liệu cho khung ảnh động dài nhất, 5, 10 hoặc bất kỳ số lượng khung ảnh động dài nào là tuyệt đối cần thiết mới được gửi lại.

MAX_LOAFS_TO_CONSIDER = 10;
let longestBlockingLoAFs = [];

const observer = new PerformanceObserver(list => {
  longestBlockingLoAFs = longestBlockingLoAFs.concat(list.getEntries()).sort(
    (a, b) => b.blockingDuration - a.blockingDuration
  ).slice(0, MAX_LOAFS_TO_CONSIDER);
});
observer.observe({ type: 'long-animation-frame', buffered: true });

Bạn cũng có thể kết hợp các chiến lược này – chỉ xem xét 10 LoAF tệ nhất, với các lượt tương tác dài hơn 100 mili giây.

Vào thời điểm thích hợp (tốt nhất là trong sự kiện visibilitychange), beacon sẽ quay lại Analytics. Để kiểm thử cục bộ, bạn có thể định kỳ sử dụng console.table:

console.table(longestBlockingLoAFs);

Xác định các mẫu phổ biến trong các khung ảnh động dài

Một chiến lược thay thế là xem xét các tập lệnh phổ biến xuất hiện nhiều nhất trong các mục khung ảnh động dài. Dữ liệu có thể được báo cáo lại ở cấp tập lệnh và vị trí ký tự để xác định những người vi phạm nhiều lần.

Cách này có thể đặc biệt hiệu quả đối với các nền tảng có thể tuỳ chỉnh, trong đó có thể xác định được các chủ đề hoặc trình bổ trợ gây ra vấn đề về hiệu suất trên một số trang web.

Bạn có thể tổng hợp và báo cáo thời gian thực thi của các tập lệnh phổ biến (hoặc nguồn gốc của bên thứ ba) trong các khung ảnh động dài để xác định những yếu tố phổ biến góp phần tạo ra các khung ảnh động dài trên một trang web hoặc một tập hợp các trang web. Ví dụ: để xem URL:

const observer = new PerformanceObserver(list => {
  const allScripts = list.getEntries().flatMap(entry => entry.scripts);
  const scriptSource = [...new Set(allScripts.map(script => script.sourceURL))];
  const scriptsBySource= scriptSource.map(sourceURL => ([sourceURL,
      allScripts.filter(script => script.sourceURL === sourceURL)
  ]));
  const processedScripts = scriptsBySource.map(([sourceURL, scripts]) => ({
    sourceURL,
    count: scripts.length,
    totalDuration: scripts.reduce((subtotal, script) => subtotal + script.duration, 0)
  }));
  processedScripts.sort((a, b) => b.totalDuration - a.totalDuration);
  // Example here logs to console, but could also report back to analytics
  console.table(processedScripts);
});

observer.observe({type: 'long-animation-frame', buffered: true});

Ví dụ về kết quả này là:

(index) sourceURL count totalDuration
0 'https://example.consent.com/consent.js' 1 840
1 'https://example.com/js/analytics.js' 7 628
2 'https://example.chatapp.com/web-chat.js' 1 5

Sử dụng API Khung ảnh động dài trong công cụ

API này cũng cho phép nhà phát triển sử dụng thêm công cụ để gỡ lỗi cục bộ. Mặc dù một số công cụ như Lighthouse và Công cụ dành cho nhà phát triển của Chrome đã có thể thu thập nhiều dữ liệu này bằng cách sử dụng thông tin theo dõi cấp thấp hơn, nhưng việc có API cấp cao hơn này có thể cho phép các công cụ khác truy cập vào dữ liệu này.

Hiển thị dữ liệu về khung ảnh động dài trong Công cụ cho nhà phát triển

Bạn có thể hiển thị các khung ảnh động dài trong DevTools bằng API performance.measure(). Sau đó, các khung này sẽ hiển thị trong kênh theo dõi thời gian của người dùng DevTools trong dấu vết hiệu suất để cho biết bạn cần tập trung vào đâu để cải thiện hiệu suất. Khi sử dụng API Mở rộng DevTools, bạn thậm chí có thể xem các lỗi này trong kênh riêng:

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    performance.measure('LoAF', {
      start: entry.startTime,
      end: entry.startTime + entry.duration,
      detail: {
        devtools: {
          dataType: "track-entry",
          track: "Long animation frames",
          trackGroup: "Performance Timeline",
          color: "tertiary-dark",
          tooltipText: 'LoAF'
        }
      }
    });
  }
});

observer.observe({ type: 'long-animation-frame', buffered: true });
Dấu vết của Bảng điều khiển hiệu suất DevTools với một kênh tuỳ chỉnh hiển thị dữ liệu Khung ảnh động dài có thể so sánh với biểu đồ hình ngọn lửa chính.
Hiển thị dữ liệu khung ảnh Ảnh động dài trong Công cụ cho nhà phát triển.

Về lâu dài, các khung ảnh động dài có thể được tích hợp vào chính DevTools, nhưng đoạn mã trước đó cho phép hiển thị khung ảnh động đó trong thời gian chờ đợi.

Mục đầu tiên trong hình trước cũng minh hoạ nơi trình duyệt đã xử lý một số tác vụ cùng nhau trong cùng một khung ảnh động dài thay vì kết xuất giữa các tác vụ đó. Như đã đề cập trước đó, điều này có thể xảy ra khi không có tác vụ đầu vào có mức độ ưu tiên cao, nhưng có hàng đợi tác vụ. Tác vụ dài đầu tiên có một số nội dung cập nhật kết xuất cần hoàn tất (nếu không, khung ảnh động dài hiện tại sẽ được đặt lại sau đó và một khung ảnh động dài mới sẽ bắt đầu với tác vụ tiếp theo), nhưng thay vì thực hiện ngay thao tác kết xuất đó, trình duyệt đã xử lý một số tác vụ bổ sung và chỉ sau đó mới thực hiện tác vụ kết xuất dài và kết thúc khung ảnh động dài. Điều này cho thấy tính hữu ích của việc xem các khung ảnh động dài trong DevTools, thay vì chỉ các tác vụ dài, để giúp xác định các lần kết xuất bị trễ.

Sử dụng dữ liệu khung ảnh động dài trong các công cụ khác dành cho nhà phát triển

Tiện ích Web Vitals đã hiển thị giá trị trong thông tin gỡ lỗi tóm tắt nhật ký để chẩn đoán các vấn đề về hiệu suất.

Giờ đây, tính năng này cũng hiển thị dữ liệu khung ảnh động dài cho mỗi lệnh gọi lại INP và mỗi lượt tương tác:

Ghi nhật ký bảng điều khiển của Tiện ích Chỉ số quan trọng chính của trang web.
Bảng ghi nhật ký của bảng điều khiển Tiện ích Web Vitals hiển thị dữ liệu LoAF.

Sử dụng dữ liệu khung ảnh động dài trong các công cụ kiểm thử tự động

Tương tự, các công cụ kiểm thử tự động trong quy trình CI/CD có thể hiển thị thông tin chi tiết về các vấn đề tiềm ẩn về hiệu suất bằng cách đo lường các khung ảnh động dài trong khi chạy nhiều bộ kiểm thử.

Câu hỏi thường gặp

Sau đây là một số câu hỏi thường gặp về API này:

Tại sao không chỉ mở rộng hoặc lặp lại trên API Tác vụ dài?

Đây là một cách khác để báo cáo kết quả đo lường tương tự nhưng cuối cùng lại khác về các vấn đề về khả năng phản hồi tiềm ẩn. Điều quan trọng là phải đảm bảo các trang web dựa vào API Tác vụ dài hiện có tiếp tục hoạt động để tránh làm gián đoạn các trường hợp sử dụng hiện có.

Mặc dù API Tác vụ dài có thể hưởng lợi từ một số tính năng của LoAF (chẳng hạn như mô hình phân bổ tốt hơn), nhưng chúng tôi tin rằng việc tập trung vào khung thay vì tác vụ sẽ mang lại nhiều lợi ích khiến API này khác biệt về cơ bản so với API Tác vụ dài hiện có.

Tại sao tôi không có mục nhập tập lệnh?

Điều này có thể cho thấy rằng khung ảnh động dài không phải do JavaScipt mà là do công việc kết xuất lớn.

Điều này cũng có thể xảy ra khi khung ảnh động dài do JavaScript nhưng không thể cung cấp thông tin phân bổ tập lệnh vì nhiều lý do về quyền riêng tư như đã nêu trước đó (chủ yếu là JavaScript không thuộc quyền sở hữu của trang).

Tại sao tôi có các mục nhập tập lệnh nhưng không có hoặc có rất ít thông tin nguồn?

Điều này có thể xảy ra vì một số lý do, bao gồm cả việc không có nguồn nào phù hợp để trỏ đến.

Thông tin tập lệnh cũng sẽ bị hạn chế đối với các tập lệnh no-cors cross-origin, mặc dù bạn có thể giải quyết vấn đề này bằng cách tìm nạp các tập lệnh đó bằng CORS bằng cách thêm crossOrigin = "anonymous" vào lệnh gọi <script>.

Ví dụ: tập lệnh Trình quản lý thẻ của Google mặc định để thêm vào trang:

<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');</script>
<!-- End Google Tag Manager -->

Có thể nâng cao để thêm j.crossOrigin = "anonymous" nhằm cung cấp đầy đủ thông tin phân bổ cho GTM

API này có thay thế API Tác vụ dài không?

Mặc dù chúng tôi cho rằng API Khung ảnh động dài là một API tốt hơn, hoàn chỉnh hơn để đo lường các tác vụ dài, nhưng hiện tại, chúng tôi không có kế hoạch ngừng sử dụng API Tác vụ dài.

Muốn nhận ý kiến phản hồi

Bạn có thể gửi ý kiến phản hồi tại danh sách vấn đề trên GitHub hoặc gửi lỗi trong quá trình triển khai API của Chrome trong công cụ theo dõi lỗi của Chrome.

Kết luận

API Khung ảnh động dài là một API mới thú vị với nhiều lợi thế tiềm năng so với API Tác vụ dài trước đó.

Đây đang là một công cụ chính để giải quyết các vấn đề về khả năng phản hồi được đo lường bằng INP. INP là một chỉ số khó tối ưu hoá và API này là một trong những cách mà nhóm Chrome đang tìm cách giúp nhà phát triển dễ dàng xác định và giải quyết vấn đề.

Tuy nhiên, phạm vi của API Khung ảnh động dài không chỉ bao gồm INP mà còn có thể giúp xác định các nguyên nhân khác gây ra tình trạng cập nhật chậm, có thể ảnh hưởng đến trải nghiệm tổng thể của người dùng trên trang web.

Lời cảm ơn

Hình thu nhỏ của Henry Be trên Unsplash.