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

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

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

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

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

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

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

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

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

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

Performance Observer API

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

  • Chrome: 52
  • Edge: 79
  • Firefox: 57
  • Safari: 11.

แหล่งที่มา

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

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

หากต้องการสร้าง 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 Load เพื่อไม่ให้บล็อกทรัพยากรที่มีลําดับความสําคัญสูงกว่า

หากต้องการดูรายการที่ผ่านมา (หลังจากที่เกิดขึ้นแล้ว) ให้ตั้งค่า Flag 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 โดยเฉพาะ

User Timing API

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

  • Chrome: 28.
  • Edge: 12.
  • Firefox: 38.
  • Safari: 11.

แหล่งที่มา

User Timing API เป็น 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 จะแสดงภาพการวัดระยะเวลาของผู้ใช้ในแผงประสิทธิภาพ และผู้ให้บริการข้อมูลวิเคราะห์จํานวนมากจะติดตามการวัดที่คุณทําโดยอัตโนมัติและส่งข้อมูลระยะเวลาไปยังแบ็กเอนด์ข้อมูลวิเคราะห์ด้วย

ในการรายงานการวัดระยะเวลาของผู้ใช้ คุณสามารถใช้ 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});

Long Tasks API

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

  • Chrome: 58
  • Edge: 79
  • Firefox: ไม่รองรับ
  • Safari: ไม่รองรับ

แหล่งที่มา

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

เมื่อใดก็ตามที่คุณต้องเรียกใช้โค้ดที่มีราคาแพง หรือโหลดและเรียกใช้สคริปต์ขนาดใหญ่ คุณควรติดตามว่าโค้ดดังกล่าวบล็อกเธรดหลักหรือไม่ อันที่จริงแล้ว เมตริกระดับสูงจำนวนมากสร้างขึ้นจาก Long Tasks API (เช่น Time to Interactive (TTI) และ Total block 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});

Long Animation Frames API

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

  • Chrome: 123
  • Edge: 123
  • Firefox: ไม่รองรับ
  • Safari: ไม่รองรับ

แหล่งที่มา

Long Animation Frames API เป็น 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.
  • Edge: 79
  • Firefox: ไม่สนับสนุน
  • Safari: ไม่รองรับ

แหล่งที่มา

เมตริก Largest Contentful Paint (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>

Event Timing API

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

  • Chrome: 76
  • Edge: 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});

Resource Timing API

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

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

แหล่งที่มา

Resource Timing 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
  • Edge: 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 ก่อนที่จะเริ่มขัดจังหวะเหตุการณ์การดึงข้อมูล

คุณสามารถระบุเวลาเริ่มต้นของ 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});

Server Timing API

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

  • Chrome: 65
  • Edge: 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});