1. Giới thiệu
Đây là một lớp học lập trình mang tính tương tác để tìm hiểu cách đo lường Lượt tương tác đến nội dung hiển thị tiếp theo (INP) bằng thư viện web-vitals
.
Điều kiện tiên quyết
- Kiến thức về phát triển HTML và JavaScript.
- Bạn nên đọc tài liệu về chỉ số INP trên web.dev.
Kiến thức bạn sẽ học được
- Cách thêm thư viện
web-vitals
vào trang và sử dụng dữ liệu phân bổ của thư viện đó. - Sử dụng dữ liệu phân bổ để chẩn đoán vị trí và cách bắt đầu cải thiện INP.
Bạn cần có
- Máy tính có khả năng sao chép mã từ GitHub và chạy các lệnh npm.
- Trình chỉnh sửa văn bản.
- Phiên bản Chrome mới nhất để tất cả các phép đo lường lượt tương tác đều hoạt động.
2. Bắt đầu thiết lập
Tải và chạy mã
Bạn có thể tìm thấy mã này trong kho lưu trữ web-vitals-codelabs
.
- Sao chép kho lưu trữ trong thiết bị đầu cuối:
git clone https://github.com/GoogleChromeLabs/web-vitals-codelabs.git
. - Di chuyển vào thư mục được sao chép:
cd web-vitals-codelabs/measuring-inp
. - Cài đặt phần phụ thuộc:
npm ci
. - Khởi động máy chủ web:
npm run start
. - Truy cập vào http://localhost:8080/ trong trình duyệt.
Dùng thử trang
Lớp học lập trình này sử dụng Gastropodicon (một trang web tham khảo phổ biến về giải phẫu ốc) để khám phá các vấn đề tiềm ẩn với INP.
Hãy thử tương tác với trang để biết những lượt tương tác nào bị chậm.
3. Làm quen với Công cụ của Chrome cho nhà phát triển
Mở DevTools trong trình đơn Công cụ khác > Công cụ cho nhà phát triển, bằng cách nhấp chuột phải vào trang rồi chọn Kiểm tra hoặc bằng cách sử dụng phím tắt.
Trong lớp học lập trình này, chúng ta sẽ sử dụng cả bảng điều khiển Hiệu suất và Bảng điều khiển. Bạn có thể chuyển đổi giữa các chế độ này trong các thẻ ở đầu DevTools bất cứ lúc nào.
- Các vấn đề về INP thường xảy ra trên thiết bị di động, vì vậy, hãy chuyển sang mô phỏng màn hình thiết bị di động.
- Nếu bạn đang kiểm thử trên máy tính để bàn hoặc máy tính xách tay, hiệu suất có thể sẽ tốt hơn đáng kể so với trên thiết bị di động thực. Để xem hiệu suất một cách thực tế hơn, hãy nhấn vào biểu tượng bánh răng ở trên cùng bên phải của bảng điều khiển Hiệu suất, sau đó chọn CPU chậm 4 lần.
4. Cài đặt web-vitals
web-vitals
là một thư viện JavaScript dùng để đo lường các chỉ số Web Vitals mà người dùng trải nghiệm. Bạn có thể sử dụng thư viện này để ghi lại các giá trị đó, sau đó gửi các giá trị đó đến một điểm cuối phân tích để phân tích sau này, nhằm mục đích xác định thời điểm và vị trí xảy ra các lượt tương tác chậm.
Có một số cách để thêm thư viện vào trang. Cách bạn cài đặt thư viện trên trang web của riêng mình sẽ phụ thuộc vào cách bạn quản lý các phần phụ thuộc, quy trình xây dựng và các yếu tố khác. Hãy nhớ xem tài liệu của thư viện để biết tất cả các lựa chọn.
Lớp học lập trình này sẽ cài đặt từ npm và tải trực tiếp tập lệnh để tránh đi sâu vào một quy trình xây dựng cụ thể.
Bạn có thể sử dụng hai phiên bản web-vitals
:
- Bạn nên sử dụng bản dựng "tiêu chuẩn" nếu muốn theo dõi các giá trị chỉ số của Core Web Vitals khi tải trang.
- Bản dựng "phân bổ" sẽ thêm thông tin gỡ lỗi bổ sung vào từng chỉ số để chẩn đoán lý do một chỉ số có giá trị như vậy.
Để đo lường INP trong lớp học lập trình này, chúng ta cần bản dựng phân bổ.
Thêm web-vitals
vào devDependencies
của dự án bằng cách chạy npm install -D web-vitals
Thêm web-vitals
vào trang:
Thêm phiên bản phân bổ của tập lệnh vào cuối index.html
và ghi lại kết quả vào bảng điều khiển:
<script type="module">
import {onINP} from './node_modules/web-vitals/dist/web-vitals.attribution.js';
onINP(console.log);
</script>
Dùng thử
Hãy thử tương tác lại với trang khi bảng điều khiển đang mở. Khi bạn nhấp xung quanh trang, không có gì được ghi lại!
INP được đo lường trong toàn bộ vòng đời của một trang. Do đó, theo mặc định, web-vitals
sẽ không báo cáo INP cho đến khi người dùng rời khỏi hoặc đóng trang. Đây là hành vi lý tưởng để truyền beacon cho những thông tin như số liệu phân tích, nhưng không lý tưởng lắm để gỡ lỗi theo cách tương tác.
web-vitals
cung cấp tuỳ chọn reportAllChanges
để báo cáo chi tiết hơn. Khi bật, không phải mọi lượt tương tác đều được báo cáo, mà chỉ những lượt tương tác chậm hơn mọi lượt tương tác trước đó mới được báo cáo.
Hãy thử thêm tuỳ chọn này vào tập lệnh và tương tác lại với trang:
<script type="module">
import {onINP} from './node_modules/web-vitals/dist/web-vitals.attribution.js';
onINP(console.log, {reportAllChanges: true});
</script>
Làm mới trang và các lượt tương tác hiện sẽ được báo cáo cho bảng điều khiển, cập nhật bất cứ khi nào có lượt tương tác chậm nhất mới. Ví dụ: hãy thử nhập vào hộp tìm kiếm rồi xoá nội dung đã nhập.
5. Thuộc tính chứa nội dung gì?
Hãy bắt đầu với lượt tương tác đầu tiên mà hầu hết người dùng sẽ có với trang này, đó là hộp thoại đồng ý sử dụng cookie.
Nhiều trang sẽ có các tập lệnh cần kích hoạt cookie đồng bộ khi người dùng chấp nhận cookie, khiến lượt nhấp trở thành một lượt tương tác chậm. Đó là những gì xảy ra ở đây.
Nhấp vào Yes (Có) để chấp nhận cookie (minh hoạ) và xem dữ liệu INP hiện đã được ghi lại vào bảng điều khiển DevTools.
Thông tin cấp cao nhất này có trong cả bản dựng web-vitals chuẩn và bản phân bổ:
{
name: 'INP',
value: 344,
rating: 'needs-improvement',
entries: [...],
id: 'v4-1715732159298-8028729544485',
navigationType: 'reload',
attribution: {...},
}
Khoảng thời gian bắt đầu từ khi người dùng nhấp vào lần vẽ tiếp theo là 344 mili giây – một INP"cần cải thiện". Mảng entries
có tất cả các giá trị PerformanceEntry
liên kết với lượt tương tác này – trong trường hợp này, chỉ có một sự kiện nhấp.
Tuy nhiên, để tìm hiểu những gì đang diễn ra trong thời gian này, chúng ta quan tâm nhất đến thuộc tính attribution
. Để tạo dữ liệu phân bổ, web-vitals
sẽ tìm Khung ảnh động dài (LoAF) trùng lặp với sự kiện nhấp. Sau đó, LoAF có thể cung cấp dữ liệu chi tiết về thời gian đã dùng trong khung đó, từ các tập lệnh đã chạy cho đến thời gian dùng trong lệnh gọi lại requestAnimationFrame
, kiểu và bố cục.
Mở rộng thuộc tính attribution
để xem thêm thông tin. Dữ liệu phong phú hơn nhiều.
attribution: {
interactionTargetElement: Element,
interactionTarget: '#confirm',
interactionType: 'pointer',
inputDelay: 27,
processingDuration: 295.6,
presentationDelay: 21.4,
processedEventEntries: [...],
longAnimationFrameEntries: [...],
}
Trước tiên, có thông tin về nội dung được tương tác:
interactionTargetElement
: tham chiếu trực tiếp đến phần tử đã tương tác (nếu phần tử đó chưa bị xoá khỏi DOM).interactionTarget
: bộ chọn để tìm phần tử trong trang.
Tiếp theo, thời gian được chia nhỏ theo cách tổng quan:
inputDelay
: thời gian từ khi người dùng bắt đầu tương tác (ví dụ: nhấp chuột) đến khi trình nghe sự kiện cho lượt tương tác đó bắt đầu chạy. Trong trường hợp này, độ trễ đầu vào chỉ khoảng 27 mili giây, ngay cả khi bật tính năng điều tiết CPU.processingDuration
: thời gian cần thiết để trình nghe sự kiện chạy xong. Thông thường, các trang sẽ có nhiều trình nghe cho một sự kiện (ví dụ:pointerdown
,pointerup
vàclick
). Nếu tất cả các trình nghe này chạy trong cùng một khung ảnh động, thì chúng sẽ được hợp nhất vào thời gian này. Trong trường hợp này, thời gian xử lý mất 295,6 mili giây – phần lớn thời gian INP.presentationDelay
: thời gian từ khi trình nghe sự kiện hoàn tất cho đến khi trình duyệt hoàn tất việc vẽ khung hình tiếp theo. Trong trường hợp này là 21, 4 mili giây.
Các giai đoạn INP này có thể là một tín hiệu quan trọng để chẩn đoán những gì cần được tối ưu hoá. Hướng dẫn về cách tối ưu hoá INP có thêm thông tin về chủ đề này.
Tìm hiểu sâu hơn một chút, processedEventEntries
chứa năm sự kiện, trái ngược với một sự kiện duy nhất trong mảng INP entries
cấp cao nhất. Điểm khác biệt là gì?
processedEventEntries: [
{
name: 'mouseover',
entryType: 'event',
startTime: 1801.6,
duration: 344,
processingStart: 1825.3,
processingEnd: 1825.3,
cancelable: true
},
{
name: 'mousedown',
entryType: 'event',
startTime: 1801.6,
duration: 344,
processingStart: 1825.3,
processingEnd: 1825.3,
cancelable: true
},
{name: 'mousedown', ...},
{name: 'mouseup', ...},
{name: 'click', ...},
],
Mục nhập cấp cao nhất là sự kiện INP, trong trường hợp này là một lượt nhấp. Thuộc tính processedEventEntries
là tất cả các sự kiện đã được xử lý trong cùng một khung. Lưu ý rằng nó bao gồm các sự kiện khác như mouseover
và mousedown
, chứ không chỉ sự kiện nhấp. Việc biết về các sự kiện khác này có thể rất quan trọng nếu chúng cũng bị chậm, vì tất cả đều góp phần làm chậm phản hồi.
Cuối cùng là mảng longAnimationFrameEntries
. Đây có thể là một mục nhập duy nhất, nhưng có những trường hợp một lượt tương tác có thể trải dài trên nhiều khung hình. Đây là trường hợp đơn giản nhất với một khung ảnh động dài.
longAnimationFrameEntries
Mở rộng mục nhập LoAF:
longAnimationFrameEntries: [{
name: 'long-animation-frame',
startTime: 1823,
duration: 319,
renderStart: 2139.5,
styleAndLayoutStart: 2139.7,
firstUIEventTimestamp: 1801.6,
blockingDuration: 268,
scripts: [{...}]
}],
Có một số giá trị hữu ích ở đây, chẳng hạn như chia nhỏ thời gian tạo kiểu. Bài viết về Long Animation Frames API (API Khung ảnh động dài) trình bày chi tiết hơn về các thuộc tính này. Hiện tại, chúng ta chủ yếu quan tâm đến thuộc tính scripts
. Thuộc tính này chứa các mục cung cấp thông tin chi tiết về các tập lệnh chịu trách nhiệm cho khung chạy trong thời gian dài:
scripts: [{
name: 'script',
invoker: 'BUTTON#confirm.onclick',
invokerType: 'event-listener',
startTime: 1828.6,
executionStart: 1828.6,
duration: 294,
sourceURL: 'http://localhost:8080/third-party/cmp.js',
sourceFunctionName: '',
sourceCharPosition: 1144
}]
Trong trường hợp này, chúng ta có thể biết thời gian chủ yếu được dùng trong một event-listener
, được gọi trên BUTTON#confirm.onclick
. Chúng ta thậm chí có thể thấy URL nguồn tập lệnh và vị trí ký tự của nơi hàm được xác định!
Điểm chính
Bạn có thể xác định điều gì về trường hợp này từ dữ liệu phân bổ này?
- Lượt tương tác được kích hoạt bằng một lượt nhấp vào phần tử
button#confirm
(từattribution.interactionTarget
và thuộc tínhinvoker
trên mục nhập phân bổ tập lệnh). - Thời gian chủ yếu được dùng để thực thi trình nghe sự kiện (từ
attribution.processingDuration
so với tổng chỉ sốvalue
). - Mã trình nghe sự kiện chậm bắt đầu từ trình nghe lượt nhấp được xác định trong
third-party/cmp.js
(từscripts.sourceURL
).
Đó là đủ dữ liệu để biết chúng ta cần tối ưu hoá ở đâu!
6. Nhiều trình nghe sự kiện
Làm mới trang để bảng điều khiển DevTools trở nên rõ ràng và lượt tương tác về sự đồng ý sử dụng cookie không còn là lượt tương tác dài nhất.
Bắt đầu nhập vào hộp tìm kiếm. Dữ liệu phân bổ cho biết điều gì? Bạn nghĩ điều gì đang xảy ra?
Dữ liệu phân bổ
Trước tiên, hãy xem xét một ví dụ về cách kiểm thử bản minh hoạ ở cấp cao:
{
name: 'INP',
value: 1072,
rating: 'poor',
attribution: {
interactionTargetElement: Element,
interactionTarget: '#search-terms',
interactionType: 'keyboard',
inputDelay: 3.3,
processingDuration: 1060.6,
presentationDelay: 8.1,
processedEventEntries: [...],
longAnimationFrameEntries: [...],
}
}
Đây là giá trị INP kém (khi bật tính năng điều tiết CPU) từ hoạt động tương tác bằng bàn phím với phần tử input#search-terms
. Phần lớn thời gian (1061 mili giây trong tổng số 1072 mili giây của INP) đã được dùng để xử lý.
Tuy nhiên, các mục nhập scripts
thú vị hơn.
Tình trạng đơ bố cục
Mục đầu tiên của mảng scripts
cung cấp cho chúng ta một số thông tin hữu ích:
scripts: [{
name: 'script',
invoker: 'BUTTON#confirm.onclick',
invokerType: 'event-listener',
startTime: 4875.6,
executionStart: 4875.6,
duration: 497,
forcedStyleAndLayoutDuration: 388,
sourceURL: 'http://localhost:8080/js/index.js',
sourceFunctionName: 'handleSearch',
sourceCharPosition: 940
},
...]
Phần lớn thời gian xử lý xảy ra trong quá trình thực thi tập lệnh này, đây là trình nghe input
(trình gọi là INPUT#search-terms.oninput
). Tên hàm được cung cấp (handleSearch
), cũng như vị trí ký tự bên trong tệp nguồn index.js
.
Tuy nhiên, có một thuộc tính mới: forcedStyleAndLayoutDuration
. Đây là thời gian trong lệnh gọi tập lệnh này, khi trình duyệt buộc phải bố trí lại trang. Nói cách khác, 78% thời gian (388 mili giây trong số 497 mili giây) để thực thi trình nghe sự kiện này thực sự đã được dành cho việc làm rối bố cục.
Đây là vấn đề cần ưu tiên hàng đầu để khắc phục.
Trình nghe lặp lại
Riêng hai mục nhập tập lệnh tiếp theo không có gì đặc biệt đáng chú ý:
scripts: [...,
{
name: 'script',
invoker: '#document.onkeyup',
invokerType: 'event-listener',
startTime: 5375.3,
executionStart: 5375.3,
duration: 124,
sourceURL: 'http://localhost:8080/js/index.js',
sourceFunctionName: '',
sourceCharPosition: 1526,
},
{
name: 'script',
invoker: '#document.onkeyup',
invokerType: 'event-listener',
startTime: 5673.9,
executionStart: 5673.9,
duration: 95,
sourceURL: 'http://localhost:8080/js/index.js',
sourceFunctionName: '',
sourceCharPosition: 1526
}]
Cả hai mục đều là trình nghe keyup
, thực thi lần lượt từng mục. Trình nghe là các hàm ẩn danh (do đó, không có gì được báo cáo trong thuộc tính sourceFunctionName
), nhưng chúng ta vẫn có tệp nguồn và vị trí ký tự để có thể tìm thấy vị trí của mã.
Điều kỳ lạ là cả hai đều đến từ cùng một tệp nguồn và vị trí ký tự.
Cuối cùng, trình duyệt đã xử lý nhiều thao tác nhấn phím trong một khung ảnh động, dẫn đến việc trình nghe sự kiện này chạy hai lần trước khi có thể vẽ bất kỳ nội dung nào!
Hiệu ứng này cũng có thể tăng lên, trong đó thời gian hoàn tất trình nghe sự kiện càng lâu thì càng có nhiều sự kiện đầu vào bổ sung có thể xảy ra, kéo dài thời gian tương tác chậm hơn nhiều.
Vì đây là một hoạt động tương tác tìm kiếm/tự động hoàn thành, nên việc loại bỏ độ trễ đầu vào sẽ là một chiến lược hay để mỗi khung hình xử lý tối đa một thao tác nhấn phím.
7. Độ trễ khi nhập
Lý do phổ biến gây ra độ trễ đầu vào (thời gian từ khi người dùng tương tác đến khi trình nghe sự kiện có thể bắt đầu xử lý lượt tương tác) là do luồng chính đang bận. Có nhiều nguyên nhân dẫn đến việc này:
- Trang đang tải và luồng chính đang bận thực hiện công việc ban đầu là thiết lập DOM, bố trí và tạo kiểu cho trang, cũng như đánh giá và chạy tập lệnh.
- Trang thường bận – ví dụ: đang chạy các phép tính, ảnh động dựa trên tập lệnh hoặc quảng cáo.
- Các lượt tương tác trước đó mất nhiều thời gian để xử lý nên làm chậm các lượt tương tác trong tương lai, như đã thấy trong ví dụ cuối cùng.
Trang minh hoạ có một tính năng bí mật, nếu bạn nhấp vào biểu trưng ốc sên ở đầu trang, trang này sẽ bắt đầu tạo ảnh động và thực hiện một số tác vụ JavaScript nặng trên luồng chính.
- Nhấp vào biểu trưng ốc sên để bắt đầu ảnh động.
- Các tác vụ JavaScript được kích hoạt khi ốc sên ở cuối độ nảy. Cố gắng tương tác với trang gần cuối trang thoát nhất có thể và xem bạn có thể kích hoạt INP ở mức cao như thế nào.
Ví dụ: ngay cả khi bạn không kích hoạt trình nghe sự kiện nào khác (chẳng hạn như khi nhấp và đặt tiêu điểm vào hộp tìm kiếm ngay khi ốc sên bật lên), công việc của luồng chính sẽ khiến trang không phản hồi trong một khoảng thời gian đáng kể.
Trên nhiều trang, công việc nặng trên luồng chính sẽ không hoạt động tốt như vậy, nhưng đây là ví dụ minh hoạ hiệu quả để xem cách xác định công việc đó trong dữ liệu phân bổ INP.
Dưới đây là ví dụ về mô hình phân bổ chỉ tập trung vào hộp tìm kiếm trong lượt thoát kiểu ốc sên:
{
name: 'INP',
value: 728,
rating: 'poor',
attribution: {
interactionTargetElement: Element,
interactionTarget: '#search-terms',
interactionType: 'pointer',
inputDelay: 702.3,
processingDuration: 4.9,
presentationDelay: 20.8,
longAnimationFrameEntries: [{
name: 'long-animation-frame',
startTime: 2064.8,
duration: 790,
renderStart: 2065,
styleAndLayoutStart: 2854.2,
firstUIEventTimestamp: 0,
blockingDuration: 740,
scripts: [{...}]
}]
}
}
Như dự đoán, trình nghe sự kiện đã thực thi nhanh chóng – cho thấy thời gian xử lý là 4,9 mili giây và phần lớn hoạt động tương tác kém là do độ trễ đầu vào, mất 702,3 mili giây trong tổng số 728.
Tình huống này có thể khó gỡ lỗi. Mặc dù biết người dùng đã tương tác với nội dung gì và cách tương tác, nhưng chúng ta cũng biết rằng phần tương tác đó đã hoàn tất nhanh chóng và không có vấn đề gì. Thay vào đó, có một yếu tố khác trên trang đã trì hoãn quá trình tương tác bắt đầu xử lý, nhưng làm cách nào để chúng ta biết bắt đầu tìm kiếm từ đâu?
Các mục nhập tập lệnh LoAF sẽ giúp bạn giải quyết vấn đề này:
scripts: [{
name: 'script',
invoker: 'SPAN.onanimationiteration',
invokerType: 'event-listener',
startTime: 2065,
executionStart: 2065,
duration: 788,
sourceURL: 'http://localhost:8080/js/index.js',
sourceFunctionName: 'cryptodaphneCoinHandler',
sourceCharPosition: 1831
}]
Mặc dù không liên quan gì đến hoạt động tương tác, nhưng hàm này đã làm chậm khung ảnh động và do đó được đưa vào dữ liệu LoAF được kết hợp với sự kiện tương tác.
Từ đó, chúng ta có thể thấy cách hàm trì hoãn quá trình xử lý tương tác được kích hoạt (bởi trình nghe animationiteration
), chính xác là hàm nào chịu trách nhiệm và vị trí của hàm đó trong tệp nguồn.
8. Độ trễ của bản trình bày: khi bản cập nhật không vẽ
Độ trễ hiển thị đo lường thời gian từ khi trình nghe sự kiện chạy xong cho đến khi trình duyệt có thể vẽ một khung hình mới lên màn hình, hiển thị phản hồi trực quan cho người dùng.
Làm mới trang để đặt lại giá trị INP, sau đó mở trình đơn có biểu tượng ba dấu gạch ngang. Có một sự cố rõ ràng khi cửa sổ này mở ra.
Giao diện này trông như thế nào?
{
name: 'INP',
value: 376,
rating: 'needs-improvement',
delta: 352,
attribution: {
interactionTarget: '#sidenav-button>svg',
interactionType: 'pointer',
inputDelay: 12.8,
processingDuration: 14.7,
presentationDelay: 348.5,
longAnimationFrameEntries: [{
name: 'long-animation-frame',
startTime: 651,
duration: 365,
renderStart: 673.2,
styleAndLayoutStart: 1004.3,
firstUIEventTimestamp: 138.6,
blockingDuration: 315,
scripts: [{...}]
}]
}
}
Lần này, độ trễ hiển thị chiếm phần lớn thời gian tương tác chậm. Điều đó có nghĩa là bất cứ điều gì đang chặn luồng chính đều xảy ra sau khi trình nghe sự kiện hoàn tất.
scripts: [{
entryType: 'script',
invoker: 'FrameRequestCallback',
invokerType: 'user-callback',
startTime: 673.8,
executionStart: 673.8,
duration: 330,
sourceURL: 'http://localhost:8080/js/side-nav.js',
sourceFunctionName: '',
sourceCharPosition: 1193,
}]
Khi xem xét một mục trong mảng scripts
, chúng ta thấy thời gian được dùng trong user-callback
từ FrameRequestCallback
. Lần này, độ trễ của bản trình bày là do lệnh gọi lại requestAnimationFrame
.
9. Kết luận
Tổng hợp dữ liệu trường
Điều đáng nhận thấy là tất cả những điều này sẽ dễ dàng hơn khi bạn xem một mục phân bổ INP từ một lượt tải trang. Làm cách nào để tổng hợp dữ liệu này nhằm gỡ lỗi INP dựa trên dữ liệu trường? Lượng thông tin chi tiết hữu ích thực sự khiến việc này trở nên khó khăn hơn.
Ví dụ: bạn sẽ rất cần biết phần tử trang nào là nguồn gây ra tình trạng tương tác chậm. Tuy nhiên, nếu trang của bạn có tên lớp CSS được biên dịch thay đổi từ bản dựng này sang bản dựng khác, thì bộ chọn web-vitals
từ cùng một phần tử có thể khác nhau giữa các bản dựng.
Thay vào đó, bạn phải nghĩ đến ứng dụng cụ thể của mình để xác định dữ liệu nào hữu ích nhất và cách tổng hợp dữ liệu. Ví dụ: trước khi gửi lại dữ liệu phân bổ beacon, bạn có thể thay thế bộ chọn web-vitals
bằng một giá trị nhận dạng của riêng mình, dựa trên thành phần chứa mục tiêu hoặc vai trò ARIA mà mục tiêu thực hiện.
Tương tự, các mục nhập scripts
có thể có hàm băm dựa trên tệp trong đường dẫn sourceURL
khiến các mục nhập này khó kết hợp, nhưng bạn có thể xoá hàm băm dựa trên quy trình xây dựng đã biết trước khi gửi lại dữ liệu.
Rất tiếc, không có cách nào dễ dàng để xử lý dữ liệu phức tạp như vậy, nhưng ngay cả việc sử dụng một tập hợp con của dữ liệu này cũng có giá trị hơn so với việc không có dữ liệu phân bổ nào cho quá trình gỡ lỗi.
Ghi công ở mọi nơi!
Mô hình phân bổ INP dựa trên LoAF là một công cụ gỡ lỗi mạnh mẽ. Báo cáo này cung cấp dữ liệu chi tiết về những gì đã xảy ra cụ thể trong một INP. Trong nhiều trường hợp, công cụ này có thể chỉ cho bạn vị trí chính xác trong tập lệnh mà bạn nên bắt đầu nỗ lực tối ưu hoá.
Giờ đây, bạn đã có thể sử dụng dữ liệu phân bổ INP trên bất kỳ trang web nào!
Ngay cả khi không có quyền chỉnh sửa trang, bạn vẫn có thể tạo lại quy trình trong lớp học lập trình này bằng cách chạy đoạn mã sau trong bảng điều khiển DevTools để xem những gì bạn có thể tìm thấy:
const script = document.createElement('script');
script.src = 'https://unpkg.com/web-vitals@4/dist/web-vitals.attribution.iife.js';
script.onload = function () {
webVitals.onINP(console.log, {reportAllChanges: true});
};
document.head.appendChild(script);