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

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

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

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

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

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

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

API ผู้สังเกตการณ์ประสิทธิภาพ

การสนับสนุนเบราว์เซอร์

  • 52
  • 79
  • 57
  • 11

แหล่งที่มา

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

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

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

// 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.
}

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

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

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

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

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

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

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

นอกจากนี้ API ใหม่จำนวนมาก (เช่น งานที่ใช้เวลานาน) จะไม่แสดงโดยออบเจ็กต์ performance แต่มีเพียง PerformanceObserver เท่านั้น ดังนั้น ขอแนะนําให้หลีกเลี่ยงวิธีการเหล่านี้ในโค้ดและใช้ PerformanceObserver นับจากนี้เป็นต้นไป เว้นแต่ว่าคุณจะจําเป็นต้องใช้ความเข้ากันได้ของ Internet Explorer โดยเฉพาะ

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

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 ดังนี้

// 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 ของ Tasks แบบยาว

การสนับสนุนเบราว์เซอร์

  • 58
  • 79
  • x
  • x

แหล่งที่มา

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

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

หากต้องการทราบว่ามีงานที่ใช้เวลานานเกิดขึ้นเมื่อใด ให้ลงทะเบียน PerformanceObserver เพื่อดูรายการประเภท 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.
}

Element Timing API

การสนับสนุนเบราว์เซอร์

  • 77
  • 79
  • x
  • x

แหล่งที่มา

เมตริก 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>
// 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 การจับเวลาเหตุการณ์

เมตริก First Input Delay (FID) จะวัดระยะเวลาตั้งแต่ที่ผู้ใช้โต้ตอบกับหน้าเว็บเป็นครั้งแรกจนถึงเวลาที่เบราว์เซอร์เริ่มประมวลผลตัวแฮนเดิลเหตุการณ์เพื่อตอบสนองต่อการโต้ตอบนั้น อย่างไรก็ตาม ในบางกรณีก็อาจเป็นประโยชน์สำหรับการวัดเวลาประมวลผลเหตุการณ์ด้วย

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

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

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

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

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

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

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

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

// 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.
}

การสนับสนุนเบราว์เซอร์

  • 57
  • 12
  • 58
  • 15

แหล่งที่มา

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

เมตริกหนึ่งที่นักพัฒนาซอฟต์แวร์จำนวนมากติดตามเพื่อทำความเข้าใจเวลาในการตอบกลับของเซิร์ฟเวอร์ ซึ่งก็คือ Time to First Byte (TTFB) จะพร้อมใช้งานผ่านการประทับเวลา responseStart ใน 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.
}

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

เวลาเริ่มต้นของ Service Worker สำหรับคำขอการนำทางที่ระบุอาจกำหนดได้จากเดลต้าระหว่าง entry.responseStart ถึง entry.workerStart ดังนี้

// 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 เวลาของเซิร์ฟเวอร์

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

// 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.
}