Memiliki metrik universal yang berpusat pada pengguna yang dapat Anda ukur di situs mana pun dapat sangat membantu dalam memahami pengalaman pengguna Anda di web, dan dalam membandingkan situs Anda dengan situs pesaing. Namun, dalam banyak kasus, Anda perlu mengukur lebih dari sekadar metrik universal untuk menangkap pengalaman lengkap untuk situs tertentu Anda.
Metrik kustom memungkinkan Anda mengukur aspek pengalaman situs Anda yang mungkin hanya berlaku untuk situs Anda, seperti:
- Waktu yang diperlukan aplikasi satu halaman (SPA) untuk bertransisi dari satu "halaman" ke halaman lainnya.
- Waktu yang diperlukan halaman untuk menampilkan data yang diambil dari database bagi pengguna yang login.
- Waktu yang dibutuhkan aplikasi yang dirender sisi server (SSR) untuk menghidrasi.
- Rasio cache ditemukan untuk resource yang dimuat oleh pengunjung yang kembali.
- Latensi peristiwa klik atau peristiwa keyboard dalam game.
API untuk mengukur metrik kustom
Developer web secara historis belum memiliki banyak API level rendah untuk mengukur
performa, sehingga mereka harus melakukan peretasan untuk mengukur
apakah situs berperforma baik. Misalnya, Anda dapat menentukan apakah thread utama diblokir oleh tugas JavaScript yang berjalan lama dengan menjalankan loop requestAnimationFrame
dan menghitung delta di antara setiap frame. Jika
delta jauh lebih panjang dari kecepatan frame tampilan, Anda dapat melaporkannya
sebagai tugas yang berjalan lama.
Namun, peretasan seperti ini dapat memengaruhi performa situs Anda, misalnya dengan menghabiskan baterai perangkat. Jika teknik pengukuran performa Anda menyebabkan masalah performa, data yang didapatkan dari teknik tersebut tidak akan akurat. Oleh karena itu, sebaiknya gunakan salah satu API berikut untuk membuat metrik kustom.
API Performance Observer
Performance Observer API adalah mekanisme yang mengumpulkan dan menampilkan data dari semua API performa lainnya yang dibahas di halaman ini. Memahami sangat penting untuk mendapatkan data yang baik.
Anda dapat menggunakan PerformanceObserver
untuk berlangganan peristiwa terkait performa secara pasif. Hal ini memungkinkan callback API diaktifkan selama periode tidak ada aktivitas, yang berarti callback biasanya tidak akan mengganggu performa halaman.
Saat membuat PerformanceObserver
, teruskan callback yang berjalan setiap kali
entri performa baru dikirim. Kemudian, gunakan metode observe()
untuk memberi tahu observer jenis entri yang akan diproses sebagai berikut:
// Catch errors that some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
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'});
} catch (e) {
// Do nothing if the browser doesn't support this API.
}
Bagian berikut mencantumkan semua jenis entri yang dapat Anda amati. Di browser
yang lebih baru, Anda juga dapat memeriksa jenis entri yang tersedia menggunakan properti
PerformanceObserver.supportedEntryTypes
statis.
Amati entri yang sudah terjadi
Secara default, objek PerformanceObserver
hanya dapat mengamati entri saat terjadi. Hal ini dapat menyebabkan masalah jika Anda ingin memuat kode analisis performa secara lambat agar tidak memblokir resource yang berprioritas lebih tinggi.
Untuk mendapatkan entri historis, panggil observe
dengan flag buffered
yang ditetapkan ke
true
. Kemudian, browser akan menyertakan entri historis dari
buffer entri performa
saat callback PerformanceObserver
dipanggil untuk pertama kalinya.
po.observe({
type: 'some-entry-type',
buffered: true,
});
API performa lama yang harus dihindari
Sebelum Performance Observer API, developer dapat mengakses entri
performa menggunakan metode berikut yang ditentukan pada
objek performance
. Sebaiknya jangan
menggunakannya karena Anda tidak dapat memproses entri baru.
Selain itu, banyak API baru (seperti Tugas Panjang) yang tidak diekspos oleh objek performance
, hanya oleh PerformanceObserver
. Oleh karena itu, kecuali jika Anda
sangat memerlukan kompatibilitas Internet Explorer, sebaiknya hindari metode ini
dalam kode Anda dan gunakan PerformanceObserver
untuk ke depannya.
API Waktu Pengguna
User Timing API adalah API pengukuran tujuan umum untuk metrik berbasis waktu. Hal ini memungkinkan Anda untuk menandai titik dalam waktu secara bebas, lalu mengukur durasi di antara tanda tersebut nanti.
// 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');
Meskipun API seperti Date.now()
atau performance.now()
memberi Anda kemampuan yang serupa, User Timing API lebih baik terintegrasi dengan alat performa.
Misalnya, Chrome DevTools memvisualisasikan pengukuran Waktu Pengguna di
panel Performa, dan banyak penyedia analisis secara otomatis melacak
setiap pengukuran yang Anda buat dan mengirim data durasi ke backend analisis mereka.
Untuk melaporkan pengukuran Waktu Pengguna, daftarkan
PerformanceObserver untuk mengamati entri
measure
jenis:
// Catch errors some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
// 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.
po.observe({type: 'measure', buffered: true});
} catch (e) {
// Do nothing if the browser doesn't support this API.
}
API Tugas Panjang
Long Tasks API berguna untuk menentukan kapan thread utama browser diblokir cukup lama untuk memengaruhi kecepatan frame atau latensi input. API melaporkan setiap tugas yang dijalankan lebih dari 50 milidetik (md).
Setiap kali Anda perlu menjalankan kode yang mahal, atau memuat dan mengeksekusi skrip besar, sebaiknya lacak apakah kode tersebut memblokir thread utama. Bahkan, banyak metrik tingkat yang lebih tinggi dibuat berdasarkan Long Tasks API itu sendiri (seperti Waktu untuk Interaktif (TTI) dan Total Waktu Pemblokiran (TBT)).
Untuk menentukan kapan tugas panjang terjadi, daftarkan
PerformanceObserver
untuk mengamati entri jenis longtask
:
// Catch errors since some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
// 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});
} catch (e) {
// Do nothing if the browser doesn't support this API.
}
API Waktu Elemen
Metrik Largest Contentful Paint (LCP) berguna untuk mengetahui kapan gambar atau blok teks terbesar di halaman Anda digambar ke layar, tetapi dalam beberapa kasus, Anda ingin mengukur waktu render elemen yang berbeda.
Untuk kasus ini, gunakan Element Timing API.
LCP API sebenarnya dibuat di atas Element Timing API dan menambahkan pelaporan
otomatis elemen contentful terbesar, tetapi Anda juga dapat melaporkan
elemen lain dengan secara eksplisit menambahkan atribut elementtiming
ke dalamnya, dan
mendaftarkan PerformanceObserver untuk mengamati jenis entri element
.
<img elementtiming="hero-image" />
<p elementtiming="important-paragraph">This is text I care about.</p>
...
<script>
// Catch errors since some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
// Create the performance observer.
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});
} catch (e) {
// Do nothing if the browser doesn't support this API.
}
</script>
API Waktu Peristiwa
Metrik Penundaan Input Pertama (FID) mengukur waktu sejak pengguna pertama kali berinteraksi dengan halaman hingga saat browser dapat mulai memproses pengendali peristiwa sebagai respons terhadap interaksi tersebut. Namun, dalam beberapa kasus, ada baiknya juga mengukur waktu pemrosesan peristiwa itu sendiri.
Hal ini dapat dilakukan menggunakan Event Timing API, yang, selain mengukur FID, juga menampilkan sejumlah stempel waktu dalam siklus proses peristiwa, termasuk:
startTime
: waktu saat browser menerima peristiwa.processingStart
: waktu saat browser dapat mulai memproses pengendali peristiwa untuk peristiwa.processingEnd
: waktu saat browser selesai mengeksekusi semua kode sinkron yang dimulai dari pengendali peristiwa untuk peristiwa ini.duration
: waktu (dibulatkan menjadi 8 milidetik untuk alasan keamanan) antara saat browser menerima peristiwa hingga dapat menggambar frame berikutnya setelah menyelesaikan semua kode sinkron yang dimulai dari pengendali peristiwa.
Contoh berikut menunjukkan cara menggunakan nilai ini untuk membuat pengukuran kustom:
// Catch errors some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
const po = new PerformanceObserver((entryList) => {
const firstInput = entryList.getEntries()[0];
// Measure First Input Delay (FID).
const firstInputDelay = firstInput.processingStart - firstInput.startTime;
// Measure the time it takes to run all event handlers
// Doesn't include work scheduled asynchronously using methods like
// `requestAnimationFrame()` or `setTimeout()`.
const firstInputProcessingTime = firstInput.processingEnd - firstInput.processingStart;
// Measure the entire duration of the event, from when input is received by
// the browser until the next frame can be painted after processing all
// event handlers.
// Doesn't include work scheduled asynchronously using
// `requestAnimationFrame()` or `setTimeout()`.
// For security reasons, this value is rounded to the nearest 8 ms.
const firstInputDuration = firstInput.duration;
// Log these values to the console.
console.log({
firstInputDelay,
firstInputProcessingTime,
firstInputDuration,
});
});
po.observe({type: 'first-input', buffered: true});
} catch (error) {
// Do nothing if the browser doesn't support this API.
}
API Waktu Resource
Resource Timing API memberikan analisis mendetail kepada developer tentang cara pemuatan resource untuk halaman tertentu. Terlepas dari nama API, informasi yang disediakan tidak hanya terbatas pada data pengaturan waktu (meskipun masih banyak). Data lain yang dapat Anda akses meliputi:
- initiatorType:
cara resource diambil, seperti dari tag
<script>
atau<link>
, atau darifetch()
. - nextHopProtocol:
protokol yang digunakan untuk mengambil resource, seperti
h2
atauquic
. - encodedBodySize dan decodedBodySize]: ukuran resource dalam bentuknya yang dienkode atau didekode (masing-masing).
- transferSize:
ukuran resource yang benar-benar ditransfer melalui jaringan. Jika
resource dipenuhi menggunakan cache, nilai ini bisa jauh lebih kecil daripada
encodedBodySize
, dan dalam beberapa kasus bisa nol, jika validasi ulang cache tidak diperlukan.
Anda dapat menggunakan properti transferSize
dari entri waktu resource untuk mengukur metrik rasio hit cache atau metrik total ukuran resource yang di-cache, yang dapat berguna untuk memahami pengaruh strategi caching resource Anda terhadap performa bagi pengunjung berulang.
Contoh berikut mencatat semua resource yang diminta oleh halaman ke dalam log dan menunjukkan apakah setiap resource terpenuhi menggunakan cache atau tidak:
// Catch errors some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
// Create the performance observer.
const po = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// If transferSize is 0, the resource was fulfilled via the cache.
console.log(entry.name, entry.transferSize === 0);
}
});
// Start listening for `resource` entries to be dispatched.
po.observe({type: 'resource', buffered: true});
} catch (e) {
// Do nothing if the browser doesn't support this API.
}
API Waktu Navigasi
Navigation Timing API mirip
dengan Resource Timing API, tetapi hanya melaporkan
permintaan navigasi.
Jenis entri navigation
juga mirip dengan jenis entri resource
, tetapi
berisi beberapa informasi tambahan
khusus untuk permintaan navigasi saja (seperti saat peristiwa DOMContentLoaded
dan
load
diaktifkan).
Satu metrik yang dilacak banyak developer untuk memahami waktu respons server, Time to
First Byte (TTFB), tersedia
melalui stempel waktu responseStart
di Navigation Timing API.
// Catch errors since browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
// 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});
} catch (e) {
// Do nothing if the browser doesn't support this API.
}
Developer metrik lain yang mungkin penting bagi developer layanan yang menggunakan pekerja layanan adalah waktu startup pekerja layanan untuk permintaan navigasi. Ini adalah jumlah waktu yang diperlukan browser untuk memulai thread pekerja layanan sebelum dapat mulai menangkap peristiwa pengambilan.
Waktu startup pekerja layanan untuk permintaan navigasi tertentu dapat
ditentukan dari delta antara entry.responseStart
dan entry.workerStart
sebagai berikut:
// Catch errors some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
// 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});
} catch (e) {
// Do nothing if the browser doesn't support this API.
}
API Waktu Server
Server Timing API memungkinkan Anda meneruskan data pengaturan waktu khusus permintaan dari server ke browser menggunakan header respons. Misalnya, Anda dapat menunjukkan berapa lama waktu yang dibutuhkan untuk mencari data di database untuk permintaan tertentu, yang dapat berguna dalam men-debug masalah performa yang disebabkan oleh kelambatan server.
Bagi developer yang menggunakan penyedia analisis pihak ketiga, Server Timing API adalah satu-satunya cara untuk menghubungkan data performa server dengan metrik bisnis lainnya yang diukur oleh alat analisis ini.
Untuk menentukan data waktu server dalam respons Anda, gunakan header respons Server-Timing
. Berikut contohnya:
HTTP/1.1 200 OK
Server-Timing: miss, db;dur=53, app;dur=47.2
Kemudian, dari halaman, Anda dapat membaca data ini pada entri resource
atau navigation
dari Resource Timing API dan Navigation Timing API.
// Catch errors some browsers throw when using the new `type` option.
// https://bugs.webkit.org/show_bug.cgi?id=209216
try {
// 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});
} catch (e) {
// Do nothing if the browser doesn't support this API.
}