เมตริกที่กำหนดเอง

การมีเมตริกที่เน้นผู้ใช้เป็นศูนย์กลางนั้นมีประโยชน์มากมาย ซึ่งคุณสามารถวัดค่าต่างๆ ได้ในทุกเว็บไซต์ เมตริกเหล่านี้ช่วยให้คุณทำสิ่งต่อไปนี้ได้

  • ทำความเข้าใจว่าผู้ใช้จริงได้รับประสบการณ์โดยรวมเว็บอย่างไร
  • เปรียบเทียบเว็บไซต์ของคุณกับของคู่แข่ง
  • ติดตามข้อมูลที่เป็นประโยชน์และนำไปปฏิบัติได้ในเครื่องมือการวิเคราะห์ของคุณโดยไม่ต้องเขียนโค้ดที่กำหนดเอง

เมตริกสากลเป็นเกณฑ์พื้นฐานที่ดี แต่ในหลายกรณี คุณจะต้องวัดมากกว่าเมตริกเหล่านี้เพื่อให้สามารถเก็บประสบการณ์การใช้งานที่สมบูรณ์สำหรับเว็บไซต์หนึ่งๆ ได้

เมตริกที่กำหนดเองช่วยให้คุณวัดแง่มุมต่างๆ ของประสบการณ์การใช้งานเว็บไซต์ที่อาจมีผลกับเว็บไซต์ของคุณเท่านั้น เช่น

  • ระยะเวลาที่แอปแบบหน้าเดียว (SPA) เปลี่ยนจาก "หน้า" 1 หน้า ไปที่อีกแห่งหนึ่ง
  • เวลาที่หน้าเว็บใช้ในการแสดงข้อมูลที่ดึงมาจากฐานข้อมูลสำหรับผู้ใช้ที่เข้าสู่ระบบ
  • ระยะเวลาที่แอปที่แสดงผลฝั่งเซิร์ฟเวอร์ (SSR) ใช้ในการเพิ่มปริมาณ
  • อัตราการพบแคชสำหรับทรัพยากรที่โหลดโดยผู้เข้าชมที่กลับมา
  • เวลาในการตอบสนองของเหตุการณ์ของเหตุการณ์การคลิกหรือแป้นพิมพ์ในเกม

API สำหรับวัดเมตริกที่กำหนดเอง

ที่ผ่านมา นักพัฒนาเว็บไม่ค่อยมี API ระดับต่ำมากนักในการวัดประสิทธิภาพ และด้วยเหตุนี้ พวกเขาจึงต้องหันมาพึ่งการแฮ็กเพื่อวัดว่าเว็บไซต์ทำงานได้ดีหรือไม่

ตัวอย่างเช่น อาจเป็นไปได้ว่าเทรดหลักถูกบล็อกเนื่องจากงาน JavaScript ที่ใช้เวลานานหรือไม่ โดยการเรียกใช้ลูป requestAnimationFrame และคำนวณเดลต้าระหว่างแต่ละเฟรม หากเดลต้ายาวกว่าอัตราเฟรมของจอแสดงผลอย่างมาก คุณก็รายงานว่าเป็นงานที่ใช้เวลานานได้ อย่างไรก็ตาม เราไม่แนะนำให้ทำการแฮ็กดังกล่าว เนื่องจากจริงๆ แล้วการทำเช่นนี้ส่งผลกระทบต่อประสิทธิภาพโดยตรง (เช่น ทำให้แบตเตอรี่หมดเร็ว)

กฎข้อแรกของการวัดประสิทธิภาพที่มีประสิทธิภาพคือการตรวจสอบว่าเทคนิคการวัดประสิทธิภาพของคุณไม่ได้ทำให้เกิดปัญหาด้านประสิทธิภาพ ดังนั้นสำหรับเมตริกที่กำหนดเองที่คุณวัดในเว็บไซต์ เราขอแนะนำให้ใช้ API อย่างใดอย่างหนึ่งต่อไปนี้หากเป็นไปได้

API เครื่องมือสังเกตประสิทธิภาพ

การรองรับเบราว์เซอร์

  • Chrome: 52
  • ขอบ: 79
  • Firefox: 57
  • Safari: 11.

แหล่งที่มา

Performance Observer API คือกลไกที่รวบรวมและแสดงข้อมูลจาก API ด้านประสิทธิภาพอื่นๆ ทั้งหมดที่กล่าวถึงในหน้านี้ การเข้าใจเรื่องนี้จึงสำคัญอย่างยิ่งต่อการได้รับข้อมูลที่ดี

คุณสามารถใช้ PerformanceObserver เพื่อสมัครรับข้อมูลกิจกรรมที่เกี่ยวข้องกับประสิทธิภาพได้แบบไม่ต้องทำอะไร ซึ่งจะทำให้ API Callback เริ่มทำงานในช่วงที่ไม่มีการใช้งาน ซึ่งหมายความว่าโดยปกติแล้วจะไม่รบกวนประสิทธิภาพของหน้าเว็บ

หากต้องการสร้าง PerformanceObserver ให้ส่งผ่าน Callback เพื่อเรียกใช้ทุกครั้งที่มีการส่งรายการด้านประสิทธิภาพใหม่ จากนั้นให้บอกผู้สังเกตการณ์ว่าจะฟังรายการประเภทใดโดยใช้เมธอด 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'});

ส่วนต่อไปนี้จะแสดงรายการประเภทต่างๆ ทั้งหมดที่ดูได้ แต่จะตรวจสอบประเภทรายการที่ใช้ได้ผ่านพร็อพเพอร์ตี้ PerformanceObserver.supportedEntryTypes แบบคงที่ในเบราว์เซอร์รุ่นใหม่

สังเกตรายการที่เกิดขึ้นแล้ว

โดยค่าเริ่มต้น ออบเจ็กต์ PerformanceObserver รายการจะสังเกตการณ์ได้เฉพาะรายการที่เกิดขึ้นเท่านั้น วิธีนี้อาจทำให้เกิดปัญหาในกรณีที่คุณต้องการโหลดโค้ดการวิเคราะห์ประสิทธิภาพแบบ Lazy Loading เพื่อไม่ให้บล็อกทรัพยากรที่มีลำดับความสำคัญสูงกว่า

หากต้องการดูรายการข้อมูลในอดีต (หลังจากเกิดขึ้นแล้ว) ให้ตั้งค่าแฟล็ก buffered เป็น true เมื่อเรียกใช้ observe() เบราว์เซอร์จะรวมรายการที่ผ่านมาจากบัฟเฟอร์รายการประสิทธิภาพในครั้งแรกที่มีการเรียก PerformanceObserver Callback โดยไม่เกินขนาดบัฟเฟอร์สูงสุดสำหรับประเภทนั้น

po.observe({
  type: 'some-entry-type',
  buffered: true,
});

API ประสิทธิภาพเดิมที่ควรหลีกเลี่ยง

ก่อนที่จะใช้ Performance Observer API นักพัฒนาแอปจะเข้าถึงรายการประสิทธิภาพได้โดยใช้ 3 วิธีต่อไปนี้ซึ่งระบุไว้ในออบเจ็กต์ performance

แม้ว่าระบบจะยังรองรับ API เหล่านี้อยู่ แต่เราไม่แนะนำให้ใช้เนื่องจาก API จะไม่อนุญาตให้คุณคอยฟังเมื่อมีการเผยแพร่รายการใหม่ นอกจากนี้ API ใหม่จำนวนมาก (เช่น largest-contentful-paint) ไม่แสดงผ่านออบเจ็กต์ performance แต่จะแสดงผ่าน PerformanceObserver เท่านั้น

คุณควรหลีกเลี่ยงวิธีการเหล่านี้ในโค้ดและใช้ PerformanceObserver นับจากนี้เป็นต้นไป ยกเว้นกรณีที่คุณต้องการความเข้ากันได้กับ Internet Explorer

API ระยะเวลาของผู้ใช้

การรองรับเบราว์เซอร์

  • Chrome: 28
  • ขอบ: 12.
  • Firefox: 38.
  • Safari: 11.

แหล่งที่มา

User Timing API เป็นวัตถุประสงค์ทั่วไป Measurement API สำหรับเมตริกตามเวลา ทำให้คุณสามารถทำเครื่องหมายคะแนนใน แล้ววัดระยะเวลาระหว่างเครื่องหมายเหล่านั้นในภายหลัง

// 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');

แม้ว่า API อย่าง Date.now() หรือ performance.now() จะให้ความสามารถที่คล้ายกัน แต่ข้อดีของการใช้ User Timing API คือสามารถผสานรวมกับเครื่องมือด้านประสิทธิภาพได้อย่างดี ตัวอย่างเช่น Chrome DevTools จะแสดงภาพการวัดระยะเวลาของผู้ใช้ในแผงประสิทธิภาพ และผู้ให้บริการวิเคราะห์หลายรายจะติดตามการวัดผลที่คุณสร้างโดยอัตโนมัติและส่งข้อมูลระยะเวลาไปยังแบ็กเอนด์การวิเคราะห์ของตน

ในการรายงานการวัดระยะเวลาของผู้ใช้ คุณสามารถใช้ PerformanceObserver และลงทะเบียนเพื่อสังเกตรายการประเภท 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 ของงานที่ใช้เวลานาน

การรองรับเบราว์เซอร์

  • Chrome: 58
  • ขอบ: 79
  • Firefox: ไม่สนับสนุน
  • Safari: ไม่รองรับ

แหล่งที่มา

Long Tasks API มีประโยชน์ในการช่วยให้ทราบเมื่อเทรดหลักของเบราว์เซอร์ถูกบล็อกเป็นเวลานานพอที่จะส่งผลต่ออัตราเฟรมหรือเวลาในการตอบสนองของอินพุต API จะรายงานงานที่ดำเนินการนานกว่า 50 มิลลิวินาที

เมื่อใดก็ตามที่คุณต้องเรียกใช้โค้ดราคาแพง หรือโหลดและเรียกใช้สคริปต์ขนาดใหญ่ การติดตามว่าโค้ดดังกล่าวจะบล็อกเทรดหลักหรือไม่ อันที่จริงแล้ว เมตริกระดับสูงจำนวนมากสร้างขึ้นจาก Long Tasks API เอง (เช่น Time to Interactive (TTI) และ Total Blocked Time (TBT))

ในการพิจารณาว่าจะมีงานที่ใช้เวลานานเกิดขึ้นเมื่อใด คุณสามารถใช้ PerformanceObserver และลงทะเบียนเพื่อติดตามรายการประเภท 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 เฟรมของภาพเคลื่อนไหวแบบยาว

การรองรับเบราว์เซอร์

  • Chrome: 123
  • ขอบ: 123
  • Firefox: ไม่สนับสนุน
  • Safari: ไม่รองรับ

แหล่งที่มา

Long Animation Frames API เป็นการปรับปรุงใหม่ของ Long Tasks API ซึ่งจะพิจารณาเฟรมขนาดยาว แทนที่จะเป็นงานที่ใช้เวลานานกว่า 50 มิลลิวินาที วิธีการนี้ช่วยแก้ไขข้อบกพร่องบางอย่างของ Long Tasks API ซึ่งรวมถึงการระบุแหล่งที่มาที่ดีขึ้นและขอบเขตที่กว้างขึ้นของความล่าช้าที่อาจเกิดขึ้นได้

ในการพิจารณาว่าเฟรมแบบยาวเกิดขึ้นเมื่อใด คุณสามารถใช้ PerformanceObserver และลงทะเบียนเพื่อสังเกตรายการของประเภท 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});

Element Timing API

การรองรับเบราว์เซอร์

  • Chrome: 77.
  • ขอบ: 79
  • Firefox: ไม่สนับสนุน
  • Safari: ไม่รองรับ

แหล่งที่มา

เมตริกการแสดงผลเนื้อหาขนาดใหญ่ที่สุด (LCP) มีประโยชน์ในการดูว่าเมื่อใดที่ระบายสีรูปภาพหรือบล็อกข้อความขนาดใหญ่ที่สุดไปยังหน้าจอ แต่ในบางกรณีคุณอาจต้องการวัดเวลาการแสดงผลขององค์ประกอบอื่น

สำหรับกรณีเหล่านี้ ให้ใช้ Element Timing API ที่จริงแล้ว LCP API สร้างขึ้นบน Element Timing API และเพิ่มการรายงานอัตโนมัติสําหรับองค์ประกอบที่มีเนื้อหาขนาดใหญ่ที่สุด แต่คุณยังสามารถรายงานเกี่ยวกับองค์ประกอบอื่นๆ ได้โดยเพิ่มแอตทริบิวต์ elementtiming ลงในองค์ประกอบเหล่านั้นอย่างชัดเจน และลงทะเบียน PerformanceObserver เพื่อดูประเภทรายการ 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 ระยะเวลาเหตุการณ์

การรองรับเบราว์เซอร์

  • Chrome: 76
  • ขอบ: 79
  • Firefox: 89
  • Safari: ไม่รองรับ

แหล่งที่มา

เมตริก Interaction to Next Paint (INP) จะประเมินการตอบสนองของหน้าเว็บโดยรวมโดยสังเกตการโต้ตอบกับการคลิก การแตะ และแป้นพิมพ์ทั้งหมดตลอดอายุของหน้าเว็บ INP ของหน้าเว็บมักเป็นการโต้ตอบที่ใช้เวลาดำเนินการนานที่สุด นับตั้งแต่เวลาที่ผู้ใช้เริ่มการโต้ตอบ ไปจนถึงตอนที่เบราว์เซอร์วาดเฟรมถัดไปซึ่งแสดงผลอินพุตของผู้ใช้แบบเป็นภาพ

เมตริก INP สร้างขึ้นโดย Event Timing API API นี้จะแสดงการประทับเวลาจำนวนหนึ่งที่เกิดขึ้นระหว่างวงจรของเหตุการณ์ ซึ่งรวมถึงเหตุการณ์ต่อไปนี้

  • startTime: เวลาที่เบราว์เซอร์ได้รับเหตุการณ์
  • processingStart: เวลาที่เบราว์เซอร์เริ่มประมวลผลเครื่องจัดการเหตุการณ์ของเหตุการณ์นั้นได้
  • processingEnd: เวลาที่เบราว์เซอร์ดำเนินการโค้ดแบบซิงโครนัสทั้งหมดที่เริ่มต้นจากเครื่องจัดการเหตุการณ์สำหรับเหตุการณ์นี้เสร็จสิ้น
  • duration: เวลา (ปัดเศษเป็น 8 มิลลิวินาทีเพื่อความปลอดภัย) ระหว่างที่เบราว์เซอร์ได้รับเหตุการณ์จนกระทั่งสามารถวาดเฟรมถัดไปหลังจากเรียกใช้โค้ดแบบซิงโครนัสทั้งหมดที่เริ่มต้นจากเครื่องจัดการเหตุการณ์เสร็จแล้ว

ตัวอย่างต่อไปนี้แสดงวิธีใช้ค่าเหล่านี้เพื่อสร้างการวัดที่กําหนดเอง

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 การจับเวลาของทรัพยากร

การรองรับเบราว์เซอร์

  • Chrome: 29
  • ขอบ: 12.
  • Firefox: 35.
  • Safari: 11.

แหล่งที่มา

Resource Timing API ทำให้นักพัฒนาแอปมีข้อมูลเชิงลึกโดยละเอียดว่ามีการโหลดทรัพยากรของหน้าหนึ่งๆ อย่างไร แม้จะมีชื่อ API แล้ว แต่ข้อมูลที่ API ให้นั้นไม่ได้จํากัดเพียงข้อมูลช่วงเวลา (แต่มีข้อมูลจำนวนมาก) ข้อมูลอื่นๆ ที่คุณเข้าถึงได้มีดังนี้

  • initiatorType: วิธีที่ดึงทรัพยากร เช่น จากแท็ก <script> หรือ <link> หรือจากการเรียกใช้ fetch()
  • nextHopProtocol: โปรโตคอลที่ใช้ในการดึงทรัพยากร เช่น h2 หรือ quic
  • encodedBodySize/decodedBodySize]: ขนาดของทรัพยากรในรูปแบบที่เข้ารหัสหรือถอดรหัส (ตามลำดับ)
  • transferSize: ขนาดของทรัพยากรที่โอนผ่านเครือข่ายจริง เมื่อแคชใช้ทรัพยากรแล้ว ค่านี้อาจน้อยกว่า encodedBodySize มาก และในบางกรณีอาจเป็น 0 ได้ (หากไม่มีการตรวจสอบแคชอีกครั้ง)

คุณสามารถใช้พร็อพเพอร์ตี้ transferSize ของรายการเวลาของทรัพยากรเพื่อวัดเมตริกอัตรา Hit ของแคชหรือเมตริกขนาดทรัพยากรที่แคชไว้ทั้งหมด ซึ่งอาจเป็นประโยชน์ในการทำความเข้าใจว่ากลยุทธ์การแคชทรัพยากรมีผลต่อประสิทธิภาพสำหรับผู้เข้าชมซ้ำอย่างไร

ตัวอย่างต่อไปนี้จะบันทึกทรัพยากรทั้งหมดที่หน้าเว็บขอ และระบุว่าทรัพยากรแต่ละรายการได้ดำเนินการโดยแคชหรือไม่

// 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});

การรองรับเบราว์เซอร์

  • Chrome: 57
  • ขอบ: 12.
  • Firefox: 58
  • Safari: 15.

แหล่งที่มา

Navigation Timing API คล้ายกับ Resource Timing API แต่จะรายงานเฉพาะคำขอการนำทางเท่านั้น ประเภทรายการ navigation ยังคล้ายกับประเภทรายการ resource เช่นกัน แต่จะมีข้อมูลเพิ่มเติมเฉพาะสำหรับคำขอการนำทางเท่านั้น (เช่น เมื่อเหตุการณ์ DOMContentLoaded และ load เริ่มทำงาน)

เมตริกหนึ่งที่นักพัฒนาซอฟต์แวร์จำนวนมากติดตามเพื่อทำความเข้าใจเวลาตอบสนองของเซิร์ฟเวอร์ (Time to First Byte (TTFB)) มีให้ใช้งานโดยใช้ Navigation Timing API หรือก็คือการประทับเวลา responseStart ของรายการ

// 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});

อีกเมตริกหนึ่งที่นักพัฒนาซอฟต์แวร์ที่ใช้ Service Worker อาจคำนึงถึงคือเวลาเริ่มต้นของ Service Worker สำหรับคำขอการนำทาง นี่คือระยะเวลาที่เบราว์เซอร์ใช้ในการเริ่มชุดข้อความของ Service Worker ก่อนที่จะเริ่มดักจับเหตุการณ์การดึงข้อมูล

เวลาเริ่มต้นของโปรแกรมทำงานของบริการสำหรับคำขอการนำทางหนึ่งๆ สามารถระบุได้จากเดลต้าระหว่าง entry.responseStart ถึง 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 ระยะเวลาของเซิร์ฟเวอร์

การรองรับเบราว์เซอร์

  • Chrome: 65
  • ขอบ: 79
  • Firefox: 61
  • Safari: 16.4

แหล่งที่มา

Server Timing API ช่วยให้คุณส่งข้อมูลเวลาที่เจาะจงของคำขอจากเซิร์ฟเวอร์ไปยังเบราว์เซอร์ผ่านส่วนหัวการตอบกลับได้ เช่น คุณระบุระยะเวลาที่ใช้ในการค้นหาข้อมูลในฐานข้อมูลสำหรับคำขอหนึ่งๆ ได้ ซึ่งจะเป็นประโยชน์ในการแก้ไขข้อบกพร่องด้านประสิทธิภาพเนื่องจากเซิร์ฟเวอร์ทำงานช้า

สำหรับนักพัฒนาซอฟต์แวร์ที่ใช้ผู้ให้บริการวิเคราะห์บุคคลที่สาม Server Timing API เป็นวิธีเดียวในการเชื่อมโยงข้อมูลประสิทธิภาพของเซิร์ฟเวอร์กับเมตริกทางธุรกิจอื่นๆ ที่เครื่องมือวิเคราะห์เหล่านี้อาจกำลังวัดผลอยู่

หากต้องการระบุข้อมูลเวลาของเซิร์ฟเวอร์ในการตอบสนอง คุณสามารถใช้ส่วนหัวการตอบกลับ Server-Timing ได้ ตัวอย่างมีดังนี้

HTTP/1.1 200 OK

Server-Timing: miss, db;dur=53, app;dur=47.2

จากนั้น คุณจะอ่านข้อมูลนี้ได้ทั้งในหน้าเว็บ resource หรือ navigation จาก Resource Timing และ Navigation Timing API

// 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});