Các chỉ số tập trung vào người dùng mang lại rất nhiều giá trị mà bạn có thể đo lường trên mọi trang web trên toàn cầu. Các chỉ số này cho phép bạn:
- Hiểu cách người dùng thực trải nghiệm web nói chung.
- So sánh trang web của bạn với trang web của đối thủ cạnh tranh.
- Theo dõi dữ liệu hữu ích và hữu ích trong các công cụ phân tích mà không cần viết mã tuỳ chỉnh.
Các chỉ số chung cung cấp một đường cơ sở hữu ích, nhưng trong nhiều trường hợp, bạn cần đo lường nhiều hơn ngoài những chỉ số này để nắm bắt được toàn bộ trải nghiệm cho trang web cụ thể của mình.
Chỉ số tuỳ chỉnh cho phép bạn đo lường các khía cạnh về trải nghiệm trên trang web mà chỉ có thể áp dụng cho trang web của bạn, chẳng hạn như:
- Thời gian để một ứng dụng trang đơn (SPA) chuyển đổi từ một "trang" sang một thiết bị khác.
- Khoảng thời gian mà một trang hiển thị dữ liệu được tìm nạp từ cơ sở dữ liệu đối với người dùng đã đăng nhập.
- Thời gian cần thiết để một ứng dụng hiển thị phía máy chủ (SSR) hydrat hoá.
- Tỷ lệ truy cập vào bộ nhớ đệm cho các tài nguyên do khách truy cập cũ tải.
- Độ trễ của các sự kiện nhấp chuột hoặc bàn phím trong một trò chơi.
Các API dùng để đo lường chỉ số tuỳ chỉnh
Trước đây, các nhà phát triển web chưa có nhiều API cấp thấp để đo lường hiệu suất. Vì vậy, họ phải sử dụng phương thức tấn công để đo lường xem một trang web có hoạt động hiệu quả hay không.
Ví dụ: bạn có thể xác định xem luồng chính có bị chặn do các tác vụ JavaScript chạy trong thời gian dài hay không bằng cách chạy vòng lặp requestAnimationFrame
và tính toán delta giữa mỗi khung. Nếu delta dài hơn đáng kể so với tốc độ khung hình của màn hình, bạn có thể báo cáo việc đó dưới dạng một tác vụ dài. Tuy nhiên, những kiểu tấn công như vậy không được khuyến khích vì chúng thực sự tự ảnh hưởng đến hiệu suất (chẳng hạn như làm tiêu hao pin).
Nguyên tắc đầu tiên để đo lường hiệu suất hiệu quả là đảm bảo các kỹ thuật đo lường hiệu suất của bạn không gây ra các vấn đề về hiệu suất. Vì vậy, đối với mọi chỉ số tuỳ chỉnh mà bạn đo lường trên trang web của mình, tốt nhất bạn nên sử dụng một trong các API sau nếu có thể.
Performance Observer API (API Trình quan sát hiệu suất)
Performance Observer API là cơ chế thu thập và hiển thị dữ liệu từ tất cả các API hiệu suất khác được thảo luận trên trang này. Việc hiểu rõ điều quan trọng là phải có được dữ liệu chất lượng cao.
Bạn có thể sử dụng PerformanceObserver
để đăng ký nhận các sự kiện liên quan đến hiệu suất theo cách thụ động. Điều này cho phép các lệnh gọi lại API kích hoạt trong thời gian không hoạt động, nghĩa là các lệnh gọi lại này thường sẽ không ảnh hưởng đến hiệu suất của trang.
Để tạo PerformanceObserver
, hãy truyền lệnh gọi lại đó để chạy bất cứ khi nào các mục nhập hiệu suất mới được gửi đi. Sau đó, bạn cho trình quan sát biết loại mục nhập nào cần theo dõi bằng cách sử dụng phương thức observe()
:
const po = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// Log the entry and all associated details.
console.log(entry.toJSON());
}
});
po.observe({type: 'some-entry-type'});
Các phần sau liệt kê tất cả các loại mục nhập hiện có để quan sát. Tuy nhiên, trong các trình duyệt mới hơn, bạn có thể kiểm tra xem những loại mục nhập nào có sẵn thông qua thuộc tính PerformanceObserver.supportedEntryTypes
tĩnh.
Quan sát các mục đã xảy ra
Theo mặc định, các đối tượng PerformanceObserver
chỉ có thể quan sát các mục nhập khi chúng xảy ra. Điều này có thể gây ra vấn đề nếu bạn muốn tải từng phần mã phân tích hiệu suất để mã không chặn các tài nguyên có mức độ ưu tiên cao hơn.
Để nhận các mục nhập trước đây (sau khi chúng xuất hiện), hãy đặt cờ buffered
thành true
khi bạn gọi observe()
. Trình duyệt sẽ đưa các mục nhập trước đây vào vùng đệm mục nhập hiệu suất vào lần đầu tiên lệnh gọi lại PerformanceObserver
được gọi, lên tới dung lượng bộ nhớ đệm tối đa cho kiểu đó.
po.observe({
type: 'some-entry-type',
buffered: true,
});
Những API hiệu suất cũ cần tránh
Trước khi có Performance Observer API, nhà phát triển có thể truy cập vào các mục hiệu suất bằng cách dùng 3 phương thức sau được xác định trên đối tượng performance
:
Mặc dù các API này vẫn được hỗ trợ, nhưng bạn không nên sử dụng chúng vì chúng không cho phép bạn nghe khi các mục nhập mới được phát ra. Ngoài ra, nhiều API mới (chẳng hạn như largest-contentful-paint
) không được hiển thị thông qua đối tượng performance
mà chỉ hiển thị thông qua PerformanceObserver
.
Trừ phi bạn cần khả năng tương thích cụ thể với Internet Explorer, tốt nhất là nên tránh sử dụng các phương thức này trong mã và sử dụng PerformanceObserver
từ giờ trở đi.
API Thời gian người dùng
API Thời gian người dùng là mục đích chung đo lường cho các chỉ số dựa trên thời gian. Tính năng này cho phép bạn tuỳ ý đánh dấu các điểm trong và sau đó đo lường khoảng thời gian giữa các mốc đó.
// Record the time immediately before running a task.
performance.mark('myTask:start');
await doMyTask();
// Record the time immediately after running a task.
performance.mark('myTask:end');
// Measure the delta between the start and end of the task
performance.measure('myTask', 'myTask:start', 'myTask:end');
Mặc dù các API như Date.now()
hoặc performance.now()
cũng cung cấp cho bạn những khả năng tương tự, nhưng lợi ích của việc sử dụng API Thời gian người dùng là tích hợp tốt với công cụ hiệu suất. Ví dụ: Công cụ của Chrome cho nhà phát triển trực quan hoá các chỉ số đo lường Thời gian người dùng trong bảng Hiệu suất và nhiều nhà cung cấp dịch vụ phân tích cũng sẽ tự động theo dõi mọi hoạt động đo lường mà bạn thực hiện và gửi dữ liệu thời lượng đến phần phụ trợ phân tích của họ.
Để báo cáo hoạt động đo lường Thời gian người dùng, bạn có thể sử dụng PerformanceObserver và đăng ký để quan sát các mục thuộc loại measure
:
// Create the performance observer.
const po = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// Log the entry and all associated details.
console.log(entry.toJSON());
}
});
// Start listening for `measure` entries to be dispatched.
po.observe({type: 'measure', buffered: true});
API Tác vụ dài
Long Tasks API giúp bạn biết thời điểm luồng chính của trình duyệt bị chặn đủ lâu để ảnh hưởng đến tốc độ khung hình hoặc độ trễ đầu vào. API sẽ báo cáo mọi tác vụ thực thi lâu hơn 50 mili giây.
Bất cứ khi nào cần chạy mã đắt tiền hoặc tải và thực thi các tập lệnh lớn, bạn nên theo dõi xem mã đó có chặn luồng chính hay không. Trên thực tế, nhiều chỉ số ở cấp cao hơn được xây dựng dựa trên chính API Long Tasks (chẳng hạn như Thời gian tương tác (TTI) và Tổng thời gian chặn (TBT)).
Để xác định thời điểm diễn ra các tác vụ cần thời gian dài, bạn có thể sử dụng PerformanceObserver và đăng ký để quan sát các mục thuộc loại longtask
:
// Create the performance observer.
const po = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// Log the entry and all associated details.
console.log(entry.toJSON());
}
});
// Start listening for `longtask` entries to be dispatched.
po.observe({type: 'longtask', buffered: true});
API Khung hoạt ảnh dài
API Khung ảnh động dài là một phiên bản mới của Long Tasks API xem xét các khung hình dài (thay vì các tác vụ dài) với thời lượng trên 50 mili giây. Việc này giúp giải quyết một số nhược điểm của Long Tasks API, chẳng hạn như khả năng phân bổ hiệu quả hơn và phạm vi rộng hơn của độ trễ có thể có vấn đề.
Để xác định thời điểm xảy ra khung hình dài, bạn có thể dùng PerformanceObserver và đăng ký để quan sát các mục thuộc loại long-animation-frame
:
// Create the performance observer.
const po = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// Log the entry and all associated details.
console.log(entry.toJSON());
}
});
// Start listening for `long-animation-frame` entries to be dispatched.
po.observe({type: 'long-animation-frame', buffered: true});
API Thời gian phần tử
Chỉ số Nội dung lớn nhất hiển thị (LCP) rất hữu ích khi biết thời điểm hình ảnh hoặc khối văn bản lớn nhất được hiển thị lên màn hình, nhưng trong một số trường hợp, bạn muốn đo thời gian hiển thị của một phần tử khác.
Đối với những trường hợp này, hãy sử dụng Element Timing API. LCP API thực sự được xây dựng dựa trên API Thời gian phần tử và thêm tính năng báo cáo tự động cho phần tử có nội dung lớn nhất. Tuy nhiên, bạn cũng có thể báo cáo về các phần tử khác bằng cách thêm rõ ràng thuộc tính elementtiming
vào các phần tử đó và đăng ký PerformanceObserver để quan sát loại mục nhập element
.
<img elementtiming="hero-image" />
<p elementtiming="important-paragraph">This is text I care about.</p>
<!-- ... -->
<script>
const po = new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
// Log the entry and all associated details.
console.log(entry.toJSON());
}
});
// Start listening for `element` entries to be dispatched.
po.observe({type: 'element', buffered: true});
</script>
API Thời gian sự kiện
Chỉ số Tương tác với lần hiển thị tiếp theo (INP) đánh giá khả năng phản hồi tổng thể của trang bằng cách quan sát tất cả các lần nhấp, nhấn và bàn phím trong suốt thời gian hoạt động của một trang. INP của một trang thường là tương tác mất nhiều thời gian nhất để hoàn tất nhất, từ thời điểm người dùng bắt đầu tương tác đến thời điểm trình duyệt hiển thị khung tiếp theo cho thấy kết quả trực quan từ hoạt động đầu vào của người dùng.
Chỉ số INP có thể được thực hiện nhờ Event Timing API. API này hiển thị một số dấu thời gian xảy ra trong vòng đời sự kiện, bao gồm:
startTime
: thời điểm trình duyệt nhận được sự kiện.processingStart
: thời gian mà trình duyệt có thể bắt đầu xử lý trình xử lý sự kiện cho sự kiện.processingEnd
: thời gian khi trình duyệt hoàn tất việc thực thi tất cả mã đồng bộ được bắt đầu từ các trình xử lý sự kiện cho sự kiện này.duration
: khoảng thời gian (được làm tròn thành 8 mili giây vì lý do bảo mật) tính từ khi trình duyệt nhận được sự kiện cho đến khi có thể vẽ khung tiếp theo sau khi hoàn tất việc thực thi tất cả mã đồng bộ được bắt đầu từ trình xử lý sự kiện.
Ví dụ sau đây cho thấy cách sử dụng các giá trị này để tạo các phép đo tuỳ chỉnh:
const po = new PerformanceObserver((entryList) => {
// Get the last interaction observed:
const entries = Array.from(entryList.getEntries()).forEach((entry) => {
// Get various bits of interaction data:
const inputDelay = entry.processingStart - entry.startTime;
const processingTime = entry.processingEnd - entry.processingStart;
const presentationDelay = entry.startTime + entry.duration - entry.processingEnd;
const duration = entry.duration;
const eventType = entry.name;
const target = entry.target || "(not set)"
console.log("----- INTERACTION -----");
console.log(`Input delay (ms): ${inputDelay}`);
console.log(`Event handler processing time (ms): ${processingTime}`);
console.log(`Presentation delay (ms): ${presentationDelay}`);
console.log(`Total event duration (ms): ${duration}`);
console.log(`Event type: ${eventType}`);
console.log(target);
});
});
// A durationThreshold of 16ms is necessary to include more
// interactions, since the default is 104ms. The minimum
// durationThreshold is 16ms.
po.observe({type: 'event', buffered: true, durationThreshold: 16});
API Thời gian tài nguyên
API Thời gian tài nguyên cung cấp cho nhà phát triển thông tin chi tiết về cách tải tài nguyên cho một trang cụ thể. Mặc dù API này có tên như vậy, thông tin mà API này cung cấp không chỉ giới hạn ở dữ liệu thời gian (mặc dù còn có rất nhiều thông tin như vậy). Các dữ liệu khác mà bạn có thể truy cập bao gồm:
initiatorType
: cách tìm nạp tài nguyên: chẳng hạn như từ thẻ<script>
hay<link>
hoặc từ lệnh gọifetch()
.nextHopProtocol
: giao thức dùng để tìm nạp tài nguyên, chẳng hạn nhưh2
hoặcquic
.encodedBodySize
/decodedBodySize]: kích thước của tài nguyên ở dạng được mã hoá hoặc giải mã (tương ứng)transferSize
: kích thước của tài nguyên thực sự được chuyển qua mạng. Khi bộ nhớ đệm thực hiện các tài nguyên, giá trị này có thể nhỏ hơn nhiều so vớiencodedBodySize
và trong một số trường hợp, giá trị này có thể bằng 0 (nếu không yêu cầu xác thực lại bộ nhớ đệm).
Bạn có thể sử dụng thuộc tính transferSize
của các mục nhập thời gian tài nguyên để đo lường chỉ số tỷ lệ truy cập vào bộ nhớ đệm hoặc chỉ số tổng dung lượng tài nguyên được lưu vào bộ nhớ đệm. Điều này có thể hữu ích trong việc giúp bạn hiểu được chiến lược lưu tài nguyên vào bộ nhớ đệm ảnh hưởng như thế nào đến hiệu suất của những khách truy cập quay lại nhiều lần.
Ví dụ sau đây ghi lại tất cả tài nguyên mà trang yêu cầu và cho biết liệu mỗi tài nguyên đã được bộ nhớ đệm thực hiện hay chưa.
// Create the performance observer.
const po = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// If transferSize is 0, the resource was fulfilled using the cache.
console.log(entry.name, entry.transferSize === 0);
}
});
// Start listening for `resource` entries to be dispatched.
po.observe({type: 'resource', buffered: true});
API Navigation Timing
Navigation Timing API tương tự như Resource Timing API, nhưng chỉ báo cáo các yêu cầu điều hướng. Loại mục nhập navigation
cũng tương tự như loại mục nhập resource
nhưng chứa một số thông tin bổ sung dành riêng cho các yêu cầu điều hướng (chẳng hạn như khi các sự kiện DOMContentLoaded
và load
kích hoạt).
Một chỉ số mà nhiều nhà phát triển theo dõi để nắm được thời gian phản hồi của máy chủ (Time to First Byte (TTFB)) có sẵn bằng cách sử dụng Navigation Timing API – cụ thể là dấu thời gian responseStart
của mục nhập.
// Create the performance observer.
const po = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// If transferSize is 0, the resource was fulfilled using the cache.
console.log('Time to first byte', entry.responseStart);
}
});
// Start listening for `navigation` entries to be dispatched.
po.observe({type: 'navigation', buffered: true});
Một chỉ số khác mà các nhà phát triển sử dụng trình chạy dịch vụ có thể quan tâm là thời gian khởi động trình chạy dịch vụ cho các yêu cầu điều hướng. Đây là khoảng thời gian mà trình duyệt cần để bắt đầu luồng trình chạy dịch vụ trước khi có thể bắt đầu chặn các sự kiện tìm nạp.
Thời gian khởi động trình chạy dịch vụ cho một yêu cầu điều hướng cụ thể có thể được xác định từ delta giữa entry.responseStart
và entry.workerStart
.
// Create the performance observer.
const po = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log('Service Worker startup time:',
entry.responseStart - entry.workerStart);
}
});
// Start listening for `navigation` entries to be dispatched.
po.observe({type: 'navigation', buffered: true});
API Thời gian máy chủ
Server Timing API cho phép bạn truyền dữ liệu thời gian dành riêng cho yêu cầu từ máy chủ đến trình duyệt thông qua các tiêu đề phản hồi. Ví dụ: bạn có thể cho biết khoảng thời gian cần để tra cứu dữ liệu trong cơ sở dữ liệu cho một yêu cầu cụ thể. Việc này có thể hữu ích trong việc gỡ lỗi các vấn đề về hiệu suất do máy chủ hoạt động chậm.
Đối với những nhà phát triển sử dụng nhà cung cấp dịch vụ phân tích bên thứ ba, Server Timing API là cách duy nhất để tạo mối liên hệ giữa dữ liệu hiệu suất của máy chủ với các chỉ số kinh doanh khác mà những công cụ phân tích này có thể đang đo lường.
Để chỉ định dữ liệu về thời gian của máy chủ trong phản hồi, bạn có thể sử dụng tiêu đề phản hồi Server-Timing
. Dưới đây là một ví dụ.
HTTP/1.1 200 OK
Server-Timing: miss, db;dur=53, app;dur=47.2
Sau đó, từ các trang của mình, bạn có thể đọc dữ liệu này trên cả hai mục nhập resource
hoặc navigation
từ các API Thời gian tài nguyên và Thời gian điều hướng.
// Create the performance observer.
const po = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// Logs all server timing data for this response
console.log('Server Timing', entry.serverTiming);
}
});
// Start listening for `navigation` entries to be dispatched.
po.observe({type: 'navigation', buffered: true});