Herhangi bir web sitesiyle ilgili olarak evrensel olarak ölçebileceğiniz kullanıcı odaklı metriklere sahip olmak büyük önem taşır. Bu metrikler sayesinde:
- Gerçek kullanıcıların web'i bir bütün olarak nasıl deneyimlediğini anlayın.
- Sitenizi bir rakibinizin sitesiyle karşılaştırın.
- Özel kod yazmaya gerek kalmadan analiz araçlarınızdaki yararlı ve işlem yapılabilir verileri izleyin.
Evrensel metrikler iyi bir temel çizgisi sunar, ancak birçok durumda belirli bir sitenizde tüm deneyimi sunmak için bu metriklerden daha fazlasını ölçmeniz gerekir.
Özel metrikler, site deneyiminizin yalnızca siteniz için geçerli olabilecek yönlerini ölçmenizi sağlar. Örneğin:
- Tek sayfalık bir uygulamanın (SPA) bir "sayfadan" geçişi ne kadar sürer? başka bir kullanıcıya atanır.
- Bir sayfanın, giriş yapmış kullanıcılar için veritabanından getirilen verileri görüntülemesinin ne kadar sürdüğü.
- Sunucu tarafı olarak oluşturulan (SSR) bir uygulamanın hidrasyona uğraması için gereken süre.
- Geri gelen ziyaretçiler tarafından yüklenen kaynakların önbellek isabet oranı.
- Bir oyundaki tıklama veya klavye etkinliklerinin etkinlik gecikmesi.
Özel metrikleri ölçmek için API'ler
Geçmişte web geliştiricileri, performansı ölçecek çok sayıda alt düzey API'ye sahip değildi. Bunun sonucunda, bir sitenin iyi performans gösterip göstermediğini ölçmek için saldırılara başvurmak zorundaydılar.
Örneğin, bir requestAnimationFrame
döngüsü çalıştırarak ve her kare arasındaki deltayı hesaplayarak ana iş parçacığının uzun süreli JavaScript görevleri nedeniyle engellenip engellenmediğini belirleyebilirsiniz. Delta, ekranın kare hızından önemli ölçüde daha uzunsa bunu uzun bir görev olarak bildirebilirsiniz. Ancak bu tür saldırılar, gerçekte performansı etkilediği için (örneğin, pili tüketerek) önerilmez.
Etkili performans ölçümünün ilk kuralı, performans ölçümü tekniklerinizin performans sorunlarına neden olmadığından emin olmaktır. Bu nedenle, sitenizde ölçtüğünüz özel metrikler için mümkünse aşağıdaki API'lerden birini kullanmanız önerilir.
Performance Observer API'si
Performance Observer API, bu sayfada ele alınan diğer tüm performans API'lerinden veri toplayan ve görüntüleyen mekanizmadır. İyi veriler elde etmek için bu metriğin anlaşılması kritik önem taşır.
Performansla ilgili etkinliklere pasif olarak abone olmak için PerformanceObserver
öğesini kullanabilirsiniz. Bu sayede API geri çağırmaları boşta kalma sürelerinde etkinleşir, yani genellikle sayfa performansını etkilemezler.
Bir PerformanceObserver
oluşturmak için bu öğeye yeni performans girişleri gönderildiğinde çalıştırılacak bir geri çağırma iletin. Daha sonra, observe()
yöntemini kullanarak gözlemciye ne tür girişler dinlemesi gerektiğini söylersiniz:
// Catch errors since 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.
}
Aşağıdaki bölümlerde, gözlemlemek için kullanılabilecek çeşitli giriş türleri listelenmiştir. Ancak yeni tarayıcılarda, statik PerformanceObserver.supportedEntryTypes
özelliğini kullanarak hangi giriş türlerinin kullanılabilir olduğunu inceleyebilirsiniz.
Daha önce gerçekleşen girişleri gözlemleyin
Varsayılan olarak PerformanceObserver
nesneleri, girişleri yalnızca gerçekleştiği sırada gözlemleyebilir. Bu durum, performans analizi kodunuzu daha yüksek öncelikli kaynakları engellememesi için geç yüklemek istiyorsanız sorunlara yol açabilir.
Geçmiş girişleri (gerçekleştikten sonra) almak için observe()
öğesini çağırırken buffered
işaretini true
olarak ayarlayın. Tarayıcı, PerformanceObserver
geri çağırmanız ilk kez çağrıldığında performans girişi arabelleğinden geçmiş girişleri dahil eder.
po.observe({
type: 'some-entry-type',
buffered: true,
});
.
Kaçınılması gereken eski performans API'leri
Performance Observer API'den önce, geliştiriciler performance
nesnesinde tanımlanan aşağıdaki üç yöntemi kullanarak performans girişlerine erişebiliyordu:
Bu API'ler hâlâ desteklense de yeni girişler yayınlandığında dinleme yapmanıza izin vermediğinden kullanımı önerilmez. Ayrıca, birçok yeni API (uzun Görevler gibi) performance
nesnesi üzerinden kullanıma sunulmamıştır, yalnızca PerformanceObserver
üzerinden kullanıma sunulur.
Özellikle Internet Explorer ile uyumluluğa ihtiyacınız olmadığı sürece, kodunuzda bu yöntemlerden kaçınmanız ve gelecekte PerformanceObserver
kullanmanız en iyisidir.
Kullanıcı Zamanlaması API'sı
User Timing API, Measurement API'sini kullanabilirsiniz. Bu seçenek, zaman alabilir ve daha sonra bu işaretler arasındaki süreyi ölçebilirsiniz.
// 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');
Date.now()
veya performance.now()
gibi API'ler size benzer yetenekler sunsa da User Timing API'yi kullanmanın performans araçlarıyla iyi entegre edilmesidir. Örneğin, Chrome Geliştirici Araçları, Performans panelinde kullanıcı zamanlaması ölçümlerini görselleştirir. Ayrıca birçok analiz sağlayıcısı, yaptığınız ölçümleri otomatik olarak izler ve süre verilerini analiz arka uçlarına gönderir.
Kullanıcı Zamanlaması ölçümlerini raporlamak için PerformanceObserver'ı kullanabilir ve measure
türündeki girişleri gözlemlemek üzere kaydedebilirsiniz:
// 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 `measure` entries to be dispatched.
po.observe({type: 'measure', buffered: true});
} catch (e) {
// Do nothing if the browser doesn't support this API.
}
Uzun Görevler API'sı
Long Tasks API, tarayıcının ana iş parçacığının ne zaman kare hızını veya giriş gecikmesini etkileyecek kadar uzun bir süre boyunca engellendiğini bilmek için kullanışlıdır. Bu API, 50 milisaniyeden uzun süren görevleri raporlar.
Pahalı kodlar çalıştırmanız veya büyük komut dosyaları yükleyip yürütmeniz gerektiğinde bu kodun ana iş parçacığını engelleyip engellemediğini izlemek faydalıdır. Aslında birçok üst düzey metrik, Long Tasks API'nin temelini oluşturur (ör. Etkileşime Kalan Süre (TTI) ve Toplam Engelleme Süresi (TBT)).
Uzun görevlerin ne zaman gerçekleşeceğini belirlemek için PerformanceObserver'ı kullanıp longtask
türündeki girişleri gözlemlemek için kayıt yapabilirsiniz:
// 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.
}
Element Timing API'si
Largest Contentful Paint (LCP) metriği, en büyük resmin veya metin bloğunun ne zaman ekrana boyandığını bilmekte faydalıdır ancak bazı durumlarda farklı bir öğenin oluşturma süresini ölçmek isteyebilirsiniz.
Bu durumlarda Element Timing API'yi kullanın. LCP API, aslında Element Timing API'yi temel almakta ve en büyük zengin içerikli öğenin otomatik olarak raporlanmasını ekler. Bununla birlikte, diğer öğeler için açıkça elementtiming
özelliğini ekleyerek ve element
giriş türünü gözlemlemek için bir PerformanceObserver kaydederek diğer öğeler hakkında da rapor oluşturabilirsiniz.
<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>
.
Event Timing API'si
Sonraki Boyamayla Etkileşim (INP) metriği, bir sayfanın kullanım süresi boyunca gerçekleşen tüm tıklama, dokunma ve klavye etkileşimlerini gözlemleyerek genel sayfa duyarlılığını değerlendirir. Bir sayfanın INP'si genellikle kullanıcının etkileşimi başlattığı andan tarayıcının kullanıcı girişinin görsel sonucunu gösteren bir sonraki kareyi boyadığı zamana kadar tamamlanması en uzun süren etkileşimdir.
INP metriği, Event Timing API tarafından kullanılır. Bu API, etkinlik yaşam döngüsü boyunca meydana gelen çeşitli zaman damgalarını gösterir. Örneğin:
startTime
: Tarayıcının etkinliği aldığı zaman.processingStart
: Tarayıcının, etkinlik için etkinlik işleyicileri işlemeye başlayabildiği zaman.processingEnd
: Tarayıcının bu etkinlik için etkinlik işleyicilerden başlatılan tüm eşzamanlı kodları yürütmeyi bitirdiği süre.duration
: Etkinlik işleyicilerden başlatılan tüm eşzamanlı kodun yürütme işlemini bitirdikten sonra tarayıcının etkinliği aldığı andan sonraki kareyi boyayabilene kadar geçen süre (güvenlik nedenleriyle 8 milisaniyeye yuvarlanır).
Aşağıdaki örnekte, özel ölçümler oluşturmak için bu değerlerin nasıl kullanılacağı gösterilmektedir:
// 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) => {
// 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 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 time (ms): ${processingTime}`);
console.log(`Total event duration (ms): ${duration}`);
console.log(`Event type: ${eventType}`);
console.log(target);
});
});
// A durationThreshold of 16ms is necessary to surface more
// interactions, since the default is 104ms. The minimum
// durationThreshold is 16ms.
po.observe({type: 'event', buffered: true, durationThreshold: 16});
} catch (error) {
// Do nothing if the browser doesn't support this API.
}
Resource Timing API'si
Resource Timing API, geliştiricilere belirli bir sayfa için kaynakların nasıl yüklendiği hakkında ayrıntılı bilgi sağlar. API'nin adına rağmen sağladığı bilgiler yalnızca zamanlama verileriyle sınırlı değildir (ancak bu kadar çok şey vardır). Erişebileceğiniz diğer veriler şunlardır:
initiatorType
: Kaynağın nasıl getirildiğidir (ör.<script>
veya<link>
etiketinden ya dafetch()
çağrısından).nextHopProtocol
: kaynağı getirmek için kullanılan protokoldür (ör.h2
veyaquic
).encodedBodySize
/decodedBodySize]: kaynağın kodlanmış veya kodu çözülmüş biçiminde boyutu (sırasıyla)transferSize
: Ağ üzerinden gerçekten aktarılan kaynağın boyutu. Kaynaklar önbellek tarafından karşılandığında, bu değerencodedBodySize
değerinden çok daha küçük olabilir ve bazı durumlarda sıfır olabilir (önbelleğin yeniden doğrulanması gerekmiyorsa).
Bir önbellek isabet oranı metriğini veya toplam önbelleğe alınmış kaynak boyutu metriğini ölçmek için kaynak zamanlaması girişlerinin transferSize
özelliğini kullanabilirsiniz. Bu metrik, kaynak önbelleğe alma stratejinizin tekrar gelen ziyaretçilerin performansını nasıl etkilediğini anlamanıza yardımcı olabilir.
Aşağıdaki örnekte, sayfa tarafından istenen tüm kaynaklar günlüğe kaydedilir ve her bir kaynağın önbellek tarafından karşılanıp karşılanmadığı belirtilir.
// 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()) {
// 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.
}
Gezinme Zamanlama API'si
Gezinme Zamanlama API'si, Resource Timing API'ye benzer ancak yalnızca gezinme isteklerini bildirir. navigation
giriş türü, resource
giriş türüne de benzer ancak yalnızca gezinme isteklerine özel (DOMContentLoaded
ve load
etkinliklerinin etkinleşmesi gibi) bazı ek bilgiler içerir.
Pek çok geliştiricinin sunucu yanıt süresini anlamak için izlediği bir metrik (İlk Bayta Kadar Geçen Süre (TTFB)), Navigation Timing API'yi kullanarak mevcuttur. Özellikle de girişin responseStart
zaman damgası kullanılır.
// 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()) {
// If transferSize is 0, the resource was fulfilled via 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.
}
Service Worker'ı kullanan geliştiricilerin dikkate alabileceği bir diğer metrik, gezinme istekleri için Service Worker başlatma süresidir. Bu, tarayıcının Service Worker iş parçacığının getirme etkinliklerine müdahale etmeye başlamadan önce başlatılması için geçen süredir.
Belirli bir gezinme isteği için hizmet çalışanı başlatma süresi, entry.responseStart
ile entry.workerStart
arasındaki deltadan belirlenebilir.
// 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()) {
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.
}
Server Timing API'si
Server Timing API, isteğe özel zamanlama verilerini sunucunuzdan yanıt başlıkları aracılığıyla tarayıcınıza iletmenizi sağlar. Örneğin, belirli bir istek için veritabanında veri aramanın ne kadar sürdüğünü belirtebilirsiniz. Bu, sunucudaki yavaşlığın neden olduğu performans sorunlarını ayıklama konusunda yararlı olabilir.
Üçüncü taraf analiz sağlayıcıları kullanan geliştiriciler için Server Timing API, sunucu performansı verilerini bu analiz araçlarının ölçebileceği diğer işletme metrikleriyle ilişkilendirmenin tek yoludur.
Yanıtlarınızda sunucu zamanlaması verilerini belirtmek için Server-Timing
yanıt başlığını kullanabilirsiniz. Bir örnekle açıklayalım.
HTTP/1.1 200 OK
Server-Timing: miss, db;dur=53, app;dur=47.2
Ardından, sayfalarınızdan bu verileri Resource Timing ve Navigation Timing API'lerinin resource
veya navigation
girişlerinde okuyabilirsiniz.
// 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()) {
// 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.
}