ดูข้อมูลพื้นฐานของการใช้ Navigation และ Resource Timing API เพื่อประเมินประสิทธิภาพการโหลดภาคสนาม
เผยแพร่เมื่อวันที่ 8 ตุลาคม 2021
หากเคยใช้การควบคุมการเชื่อมต่อในแผงเครือข่ายในเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ของเบราว์เซอร์ (หรือ Lighthouse ใน Chrome) เพื่อประเมินประสิทธิภาพการโหลด คุณทราบว่าเครื่องมือเหล่านั้นช่วยให้ปรับแต่งประสิทธิภาพได้ดีเพียงใด คุณสามารถวัดผลลัพธ์ของการเพิ่มประสิทธิภาพได้อย่างรวดเร็วด้วยความเร็วในการเชื่อมต่อพื้นฐานที่สอดคล้องกันและเสถียร ปัญหาเดียวคือนี่เป็นการทดสอบสังเคราะห์ ซึ่งจะให้ข้อมูลห้องทดลอง ไม่ใช่ข้อมูลภาคสนาม
การทดสอบแบบสังเคราะห์ไม่ได้แย่โดยเนื้อแท้ แต่ไม่ได้แสดงถึงความเร็วในการโหลดเว็บไซต์สำหรับผู้ใช้จริง ซึ่งต้องใช้ข้อมูลภาคสนาม ซึ่งคุณรวบรวมได้จาก Navigation Timing API และ Resource Timing API
API ที่ช่วยคุณประเมินประสิทธิภาพการโหลดในสนาม
การจับเวลาการนำทางและระยะเวลาการใช้ทรัพยากรเป็น API 2 ประเภทที่คล้ายกันซึ่งมีการซ้อนทับกันอย่างมีนัยสำคัญ ซึ่งจะวัด 2 สิ่งที่แตกต่างกันดังนี้
- ระยะเวลาการนำทาง จะวัดความเร็วของคำขอสำหรับเอกสาร HTML (กล่าวคือ คำขอการนำทาง)
- การกำหนดเวลาของทรัพยากรจะวัดความเร็วของคำขอทรัพยากรที่ขึ้นอยู่กับเอกสาร เช่น CSS, JavaScript, รูปภาพ และทรัพยากรประเภทอื่นๆ
API เหล่านี้จะแสดงข้อมูลใน performance entry buffer ซึ่งเข้าถึงได้ในเบราว์เซอร์ด้วย JavaScript การค้นหาบัฟเฟอร์ประสิทธิภาพทำได้หลายวิธี แต่วิธีที่ใช้กันโดยทั่วไปคือการใช้ performance.getEntriesByType
ดังนี้
// Get Navigation Timing entries:
performance.getEntriesByType('navigation');
// Get Resource Timing entries:
performance.getEntriesByType('resource');
performance.getEntriesByType
รับสตริงที่อธิบายประเภทของรายการที่คุณต้องการดึงข้อมูลจากบัฟเฟอร์รายการประสิทธิภาพ 'navigation'
และ 'resource'
จะดึงข้อมูลเวลาสําหรับ Navigation Timing API และ Resource Timing API ตามลําดับ
จำนวนข้อมูลที่ API เหล่านี้ให้อาจดูเยอะเกินกว่าจะรับมือได้ แต่ข้อมูลเหล่านี้เป็นกุญแจสำคัญในการวัดประสิทธิภาพการโหลดในสนาม เนื่องจากคุณสามารถรวบรวมเวลาเหล่านี้จากผู้ใช้ขณะเข้าชมเว็บไซต์
ระยะเวลาและช่วงเวลาของคําขอเครือข่าย
การรวบรวมและวิเคราะห์เวลาในการนําทางและการใช้ทรัพยากรนั้นคล้ายกับโบราณคดีตรงที่คุณจะต้องสร้างใหม่จากสิ่งที่เกิดขึ้นแล้ว ในบางครั้ง เครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ของเบราว์เซอร์ก็ช่วยได้ เนื่องจากการเห็นภาพแนวคิดและจุดที่กังวลเรื่องคำขอเครือข่าย
ระยะเวลาของคำขอเครือข่ายมีระยะที่แตกต่างกัน เช่น การค้นหา DNS, การสร้างการเชื่อมต่อ, การเจรจา TLS และแหล่งที่มาอื่นๆ ของเวลาในการตอบสนอง ช่วงเวลาเหล่านี้จะแสดงเป็น DOMHighResTimestamp
รายละเอียดของช่วงเวลาอาจลดลงถึงไมโครวินาทีหรือปัดเศษขึ้นเป็นมิลลิวินาที ทั้งนี้ขึ้นอยู่กับเบราว์เซอร์ของคุณ คุณควรตรวจสอบระยะเหล่านี้โดยละเอียด และดูว่าระยะเหล่านี้เกี่ยวข้องกับเวลาในการนําทางและเวลาในการตอบสนองของทรัพยากรอย่างไร
การค้นหา DNS
เมื่อผู้ใช้ไปที่ URL ระบบจะค้นหาระบบชื่อโดเมน (DNS) เพื่อแปลงโดเมนเป็นที่อยู่ IP กระบวนการนี้อาจใช้เวลานานพอสมควร ซึ่งคุณอาจต้องวัดผลในสนามด้วย ระยะเวลาในการนําทางและระยะเวลาของทรัพยากรจะแสดงระยะเวลาที่เกี่ยวข้องกับ DNS 2 รายการ ได้แก่
domainLookupStart
คือเวลาที่การค้นหา DNS เริ่มต้นdomainLookupEnd
คือเวลาที่การค้นหา DNS สิ้นสุดลง
การคำนวณเวลาทั้งหมดในการค้นหา DNS ทำได้โดยลบเมตริกเริ่มต้นออกจากเมตริกสิ้นสุด ดังนี้
// Measuring DNS lookup time
const [pageNav] = performance.getEntriesByType('navigation');
const totalLookupTime = pageNav.domainLookupEnd - pageNav.domainLookupStart;
การเจรจาต่อรองการเชื่อมต่อ
ปัจจัยอีกประการหนึ่งที่ส่งผลต่อประสิทธิภาพการโหลดคือการจัดการการเชื่อมต่อ ซึ่งเป็นเวลาในการตอบสนองที่เกิดขึ้นเมื่อเชื่อมต่อกับเว็บเซิร์ฟเวอร์ หากมี HTTPS เกี่ยวข้อง กระบวนการนี้จะรวมเวลาในการเจรจา TLS ด้วย ระยะการเชื่อมต่อประกอบด้วยช่วงเวลา 3 ระยะ ดังนี้
connectStart
คือเวลาที่เบราว์เซอร์เริ่มเปิดการเชื่อมต่อกับเว็บเซิร์ฟเวอร์secureConnectionStart
จะทำเครื่องหมายเมื่อไคลเอ็นต์เริ่มการเจรจา TLSconnectEnd
คือเวลาที่สร้างการเชื่อมต่อกับเว็บเซิร์ฟเวอร์
การวัดเวลาการเชื่อมต่อทั้งหมดจะคล้ายกับการวัดเวลาในการค้นหา DNS ทั้งหมด โดยคุณจะต้องลบเวลาเริ่มต้นออกจากเวลาสิ้นสุด อย่างไรก็ตาม ยังมีพร็อพเพอร์ตี้ secureConnectionStart
เพิ่มเติมที่อาจเป็น 0
หากไม่ได้ใช้ HTTPS หรือหากการเชื่อมต่อเป็นแบบถาวร หากต้องการวัดเวลาในการเจรจา TLS โปรดคำนึงถึงสิ่งต่อไปนี้
// Quantifying total connection time
const [pageNav] = performance.getEntriesByType('navigation');
const connectionTime = pageNav.connectEnd - pageNav.connectStart;
let tlsTime = 0; // <-- Assume 0 to start with
// Was there TLS negotiation?
if (pageNav.secureConnectionStart > 0) {
// Awesome! Calculate it!
tlsTime = pageNav.connectEnd - pageNav.secureConnectionStart;
}
เมื่อการค้นหา DNS และการเจรจาการเชื่อมต่อสิ้นสุดลง เวลาที่เกี่ยวข้องกับการดึงข้อมูลเอกสารและทรัพยากรที่เกี่ยวข้องจะเข้ามามีบทบาท
คำขอและการตอบกลับ
ปัจจัย 2 ประเภทส่งผลต่อประสิทธิภาพในการโหลด ดังนี้
- ปัจจัยภายนอก: ปัจจัยต่างๆ เช่น เวลาในการตอบสนองและแบนด์วิดท์ นอกจากการเลือกบริษัทโฮสติ้งและอาจรวมถึง CDN แล้ว บริษัทเหล่านี้ (ส่วนใหญ่) ไม่มีสิทธิ์ควบคุม เนื่องจากผู้ใช้สามารถเข้าถึงเว็บได้จากทุกที่
- ปัจจัยภายใน: ปัจจัยต่างๆ เช่น สถาปัตยกรรมฝั่งเซิร์ฟเวอร์และฝั่งไคลเอ็นต์ ตลอดจนขนาดทรัพยากรและความสามารถในการเพิ่มประสิทธิภาพเพื่อสิ่งเหล่านั้นซึ่งอยู่ในการควบคุมของเรา
ปัจจัยทั้ง 2 ประเภทส่งผลต่อประสิทธิภาพการโหลด การกำหนดเวลาที่เกี่ยวข้องกับปัจจัยเหล่านี้มีความสำคัญ เนื่องจากจะอธิบายระยะเวลาที่ใช้ในการดาวน์โหลดทรัพยากร ทั้งระยะเวลาในการนําทางและระยะเวลาของทรัพยากรจะอธิบายประสิทธิภาพการโหลดด้วยเมตริกต่อไปนี้
fetchStart
หมายถึงเวลาที่เบราว์เซอร์เริ่มดึงข้อมูลทรัพยากร (เวลาในการตอบสนองของทรัพยากร) หรือดึงข้อมูลเอกสารสําหรับคําขอไปยังส่วนต่างๆ (เวลาในการตอบสนองในการนําทาง) ซึ่งอยู่ก่อนคำขอจริง และเป็นจุดที่เบราว์เซอร์กำลังตรวจสอบแคช (เช่น HTTP และอินสแตนซ์Cache
)workerStart
จะทำเครื่องหมายเมื่อเริ่มจัดการคำขอภายในเครื่องจัดการเหตุการณ์fetch
ของ Service Worker ซึ่งจะเป็น0
เมื่อไม่มี Service Worker กำลังควบคุมหน้าปัจจุบันrequestStart
คือเวลาที่เบราว์เซอร์ส่งคำขอresponseStart
คือเวลาที่ไบต์แรกของการตอบกลับมาถึงresponseEnd
คือเวลาที่ไบต์สุดท้ายของคำตอบมาถึง
ช่วงเวลาเหล่านี้ช่วยให้คุณวัดประสิทธิภาพการโหลดได้หลายด้าน เช่น การค้นหาแคชภายใน Service Worker และเวลาดาวน์โหลด
// Cache seek plus response time of the current document
const [pageNav] = performance.getEntriesByType('navigation');
const fetchTime = pageNav.responseEnd - pageNav.fetchStart;
// Service worker time plus response time
let workerTime = 0;
if (pageNav.workerStart > 0) {
workerTime = pageNav.responseEnd - pageNav.workerStart;
}
นอกจากนี้ คุณยังวัดแง่มุมอื่นๆ ของคำขอและเวลาในการตอบสนองของการตอบกลับได้ด้วย
const [pageNav] = performance.getEntriesByType('navigation');
// Request time only (excluding redirects, DNS, and connection/TLS time)
const requestTime = pageNav.responseStart - pageNav.requestStart;
// Response time only (download)
const responseTime = pageNav.responseEnd - pageNav.responseStart;
// Request + response time
const requestResponseTime = pageNav.responseEnd - pageNav.requestStart;
การวัดผลอื่นๆ ที่คุณสามารถทำได้
การจับเวลาการนำทางและระยะเวลาของทรัพยากรมีประโยชน์มากกว่าสิ่งที่ตัวอย่างก่อนหน้านี้ สถานการณ์อื่นๆ ในช่วงเวลาที่เกี่ยวข้องซึ่งควรค่าแก่การตรวจสอบมีดังนี้
- การเปลี่ยนเส้นทางหน้าเว็บ: การเปลี่ยนเส้นทางเป็นสาเหตุที่อาจทำให้เวลาในการตอบสนองเพิ่มขึ้นที่ถูกมองข้าม โดยเฉพาะห่วงโซ่การเปลี่ยนเส้นทาง เวลาในการตอบสนองจะเพิ่มขึ้นด้วยวิธีต่างๆ เช่น Hop จาก HTTP ไปยัง HTTPs รวมถึงการเปลี่ยนเส้นทาง 302/301 ที่ไม่ได้แคช การกําหนดเวลา
redirectStart
,redirectEnd
และredirectCount
มีประโยชน์ในการประเมินเวลาในการตอบสนองของการเปลี่ยนเส้นทาง - การยกเลิกการโหลดเอกสาร: ในหน้าเว็บที่เรียกใช้โค้ดในเครื่องจัดการเหตุการณ์
unload
เบราว์เซอร์จะต้องเรียกใช้โค้ดนั้นก่อนจึงจะไปยังหน้าถัดไปได้unloadEventStart
และunloadEventEnd
วัดการยกเลิกการโหลดเอกสาร - การประมวลผลเอกสาร: ระยะเวลาในการประมวลผลเอกสารอาจไม่ส่งผลต่อประสิทธิภาพ เว้นแต่ว่าเว็บไซต์จะส่งเพย์โหลด HTML ขนาดใหญ่มาก หากตรงกับสถานการณ์ของคุณ เวลา
domInteractive
,domContentLoadedEventStart
,domContentLoadedEventEnd
และdomComplete
อาจน่าสนใจ
วิธีดูเวลาในโค้ด
ตัวอย่างทั้งหมดที่แสดงจนถึงตอนนี้ใช้ performance.getEntriesByType
แต่ยังมีวิธีอื่นๆ ในการค้นหาบัฟเฟอร์รายการประสิทธิภาพ เช่น performance.getEntriesByName
และ performance.getEntries
คุณสามารถใช้วิธีการเหล่านี้ได้เมื่อต้องใช้การวิเคราะห์เพียงเล็กน้อย อย่างไรก็ตาม ในบางสถานการณ์ การดำเนินการเหล่านี้อาจทำให้เธรดหลักทำงานมากเกินไปด้วยการวนซ้ำรายการจํานวนมาก หรือแม้แต่การเรียกดูบัฟเฟอร์ประสิทธิภาพซ้ำๆ เพื่อค้นหารายการใหม่
แนวทางที่แนะนําสําหรับการเก็บรวบรวมรายการจากบัฟเฟอร์รายการประสิทธิภาพคือการใช้ PerformanceObserver
PerformanceObserver
จะคอยฟังรายการประสิทธิภาพและแสดงรายการเหล่านั้นเมื่อเพิ่มลงในบัฟเฟอร์
// Create the performance observer:
const perfObserver = new PerformanceObserver((observedEntries) => {
// Get all resource entries collected so far:
const entries = observedEntries.getEntries();
// Iterate over entries:
for (let i = 0; i < entries.length; i++) {
// Do the work!
}
});
// Run the observer for Navigation Timing entries:
perfObserver.observe({
type: 'navigation',
buffered: true
});
// Run the observer for Resource Timing entries:
perfObserver.observe({
type: 'resource',
buffered: true
});
วิธีการรวบรวมเวลานี้อาจดูแปลกๆ เมื่อเปรียบเทียบกับการเข้าถึงบัฟเฟอร์รายการประสิทธิภาพโดยตรง แต่วิธีนี้ดีกว่าการผูกเธรดหลักกับงานที่ไม่ได้มีไว้เพื่อวัตถุประสงค์ที่สำคัญและแสดงต่อผู้ใช้
วิธีโทรหาบ้าน
เมื่อรวบรวมช่วงเวลาทั้งหมดที่ต้องการแล้ว คุณจะส่งไปยังปลายทางเพื่อวิเคราะห์เพิ่มเติมได้ ซึ่งทำได้ 2 วิธี ได้แก่ navigator.sendBeacon
หรือ fetch
ที่มีการตั้งค่าตัวเลือก keepalive
ทั้ง 2 วิธีจะส่งคําขอไปยังปลายทางที่ระบุโดยไม่บล็อก และระบบจะจัดคิวคําขอในลักษณะที่ยาวนานกว่าเซสชันหน้าเว็บปัจจุบัน หากจําเป็น
// Check for navigator.sendBeacon support:
if ('sendBeacon' in navigator) {
// Caution: If you have lots of performance entries, don't
// do this. This is an example for illustrative purposes.
const data = JSON.stringify(performance.getEntries());
// Send the data!
navigator.sendBeacon('/analytics', data);
}
ในตัวอย่างนี้ สตริง JSON จะมาถึงในเพย์โหลด POST
ที่คุณถอดรหัส ประมวลผล และจัดเก็บไว้ในแบ็กเอนด์ของแอปพลิเคชันได้ตามต้องการ
บทสรุป
เมื่อรวบรวมเมตริกแล้ว คุณต้องหาวิธีวิเคราะห์ข้อมูลช่องนั้น เมื่อวิเคราะห์ข้อมูลภาคสนาม คุณต้องปฏิบัติตามกฎทั่วไปบางข้อเพื่อให้แน่ใจว่าคุณดึงข้อมูลสรุปที่มีประโยชน์
- หลีกเลี่ยงค่าเฉลี่ย เนื่องจากไม่ได้แสดงถึงประสบการณ์ของผู้ใช้แต่ละราย และอาจบิดเบือนจากค่าที่ผิดปกติ
- อาศัยเปอร์เซ็นไทล์ ในชุดข้อมูลของเมตริกประสิทธิภาพตามเวลา ยิ่งต่ำกว่านั้นก็ยิ่งดี ซึ่งหมายความว่าหากคุณให้ความสำคัญกับช่วงเปอร์เซ็นต์ไทล์ที่ต่ำ คุณจะสนใจเฉพาะประสบการณ์การใช้งานที่เร็วที่สุดเท่านั้น
- ให้ความสำคัญกับค่าหลายด้าน เมื่อคุณจัดลำดับความสำคัญของประสบการณ์ที่เปอร์เซ็นไทล์ที่ 75 ขึ้นไป คุณได้โฟกัสที่สิ่งนั้น ซึ่งก็คือประสบการณ์การใช้งานที่ช้าที่สุด
คู่มือนี้ไม่ได้เป็นเพียงแหล่งข้อมูลที่ครอบคลุมเรื่องการนำทางหรือระยะเวลาที่ใช้ทรัพยากร แต่เป็นจุดเริ่มต้น แหล่งข้อมูลเพิ่มเติมบางส่วนที่อาจเป็นประโยชน์สำหรับคุณมีดังนี้
- ข้อกำหนดด้านเวลาในการนำทาง
- ข้อกําหนดการกําหนดเวลาของทรัพยากร
- ResourceTiming ในทางปฏิบัติ
- Navigation Timing API (MDN)
- Resource Timing API (MDN)
API เหล่านี้และข้อมูลที่ API ระบุจะช่วยให้คุณเข้าใจประสบการณ์ของผู้ใช้จริงเกี่ยวกับประสิทธิภาพการโหลดได้ดียิ่งขึ้น ซึ่งจะช่วยให้คุณมั่นใจมากขึ้นในการวินิจฉัยและแก้ไขปัญหาเกี่ยวกับประสิทธิภาพการโหลดในสนาม