ทำความเข้าใจเว็บแอป
เว็บแอปพลิเคชันที่มีประสิทธิภาพสูงเป็นสิ่งสําคัญอย่างยิ่งต่อประสบการณ์การใช้งานที่ยอดเยี่ยม เนื่องจากเว็บแอปพลิเคชันมีความซับซ้อนมากขึ้นเรื่อยๆ การทำความเข้าใจผลกระทบด้านประสิทธิภาพจึงมีความสำคัญต่อการสร้างประสบการณ์การใช้งานที่น่าสนใจ ในช่วง 2-3 ปีที่ผ่านมา API ต่างๆ จำนวนมากได้ปรากฏขึ้นในเบราว์เซอร์เพื่อช่วยวิเคราะห์ประสิทธิภาพของเครือข่าย เวลาในการโหลด ฯลฯ แต่ API เหล่านี้ไม่จำเป็นต้องให้รายละเอียดที่ละเอียดมากและมีความยืดหยุ่นเพียงพอในการค้นหาสิ่งที่ทำให้แอปพลิเคชันทำงานช้าลง ป้อน User Timing API ซึ่งให้กลไกที่คุณสามารถใช้เพื่อติดตั้งใช้งานเว็บแอปพลิเคชันเพื่อระบุตําแหน่งที่แอปพลิเคชันใช้เวลา บทความนี้จะอธิบายเกี่ยวกับ API พร้อมตัวอย่างวิธีใช้
คุณไม่สามารถเพิ่มประสิทธิภาพสิ่งที่วัดไม่ได้
ขั้นตอนแรกในการเร่งความเร็วเว็บแอปพลิเคชันที่ทำงานช้าคือการหาจุดที่ใช้เวลา การวัดผลกระทบด้านเวลาของพื้นที่โค้ด JavaScript เป็นวิธีที่เหมาะสมในการระบุจุดที่มีการใช้งานมาก ซึ่งเป็นขั้นตอนแรกในการค้นหาวิธีปรับปรุงประสิทธิภาพ แต่โชคดีที่ User Timing API มีวิธีที่คุณสามารถแทรกการเรียก API ในส่วนต่างๆ ของ JavaScript แล้วดึงข้อมูลการวัดเวลาโดยละเอียดที่สามารถใช้เพื่อช่วยในการเพิ่มประสิทธิภาพ
เวลาและ now()
ความละเอียดสูง
ความแม่นยำเป็นส่วนสําคัญของการวัดเวลาที่แม่นยำ สมัยก่อนเราใช้การวัดเวลาแบบมิลลิวินาที ซึ่งก็ใช้ได้ แต่การสร้างเว็บไซต์ที่ราบรื่น 60 FPS หมายความว่าแต่ละเฟรมต้องวาดใน 16 มิลลิวินาที ดังนั้นเมื่อมีความแม่นยำเพียงมิลลิวินาที ก็จะขาดความแม่นยำที่จําเป็นสําหรับการวิเคราะห์ที่ดี ป้อนเวลาความละเอียดสูง ซึ่งเป็นประเภทการจับเวลาแบบใหม่ที่ฝังอยู่ในเบราว์เซอร์สมัยใหม่ เวลาความละเอียดสูงจะให้การประทับเวลาทศนิยมที่มีความแม่นยำถึงระดับไมโครวินาที ซึ่งดีกว่าก่อนหน้านี้หลายพันเท่า
หากต้องการทราบเวลาปัจจุบันในเว็บแอปพลิเคชัน ให้เรียกใช้เมธอด now()
ซึ่งจะสร้างส่วนขยายของอินเทอร์เฟซ Performance โค้ดต่อไปนี้แสดงวิธีดำเนินการ
var myTime = window.performance.now();
นอกจากนี้ยังมีอินเทอร์เฟซอื่นที่เรียกว่า PerformanceTiming ซึ่งแสดงเวลาต่างๆ ที่เกี่ยวข้องกับวิธีโหลดเว็บแอปพลิเคชัน เมธอด now()
จะแสดงเวลาผ่านไปนับตั้งแต่เวลาที่ navigationStart
ใน PerformanceTiming เกิดขึ้น
ประเภท DOMHighResTimeStamp
เมื่อพยายามวัดเวลาของเว็บแอปพลิเคชันที่ผ่านมา คุณอาจใช้ Date.now()
ซึ่งจะแสดงผล DOMTimeStamp DOMTimeStamp จะแสดงผลค่าเป็นจำนวนเต็มของมิลลิวินาที เราได้เปิดตัวประเภทใหม่ชื่อ DOMHighResTimeStamp เพื่อเพิ่มความแม่นยำที่จำเป็นสำหรับเวลาความละเอียดสูง ประเภทนี้เป็นค่าตัวเลขทศนิยมที่แสดงผลเวลาเป็นมิลลิวินาทีด้วย แต่เนื่องจากเป็นทศนิยม ค่าจึงแสดงมิลลิวินาทีแบบเศษทศนิยมได้ จึงให้ค่าที่แม่นยำถึง 1 ในพันมิลลิวินาที
อินเทอร์เฟซระยะเวลาของผู้ใช้
เมื่อเรามีการประทับเวลาที่มีความละเอียดสูงแล้ว เรามาลองใช้อินเทอร์เฟซการวัดเวลาของผู้ใช้เพื่อดึงข้อมูลการวัดเวลากัน
อินเทอร์เฟซการวัดเวลาของผู้ใช้มีฟังก์ชันที่ช่วยให้เราเรียกใช้เมธอดในตําแหน่งต่างๆ ในแอปพลิเคชัน ซึ่งสามารถระบุร่องรอยเบรดครัมบ์สไตล์ Hansel และ Gretel เพื่อให้เราติดตามได้ว่าผู้ใช้ใช้เวลาไปกับส่วนใด
กำลังใช้ mark()
วิธี mark()
เป็นเครื่องมือหลักในชุดเครื่องมือการวิเคราะห์ช่วงเวลา สิ่งที่ mark()
ทําคือจัดเก็บการประทับเวลาให้เรา สิ่งที่มีประโยชน์อย่างยิ่งเกี่ยวกับ mark()
คือเราสามารถตั้งชื่อการประทับเวลาได้ และ API จะจดจำชื่อและการประทับเวลาเป็นหน่วยเดียว
การเรียกใช้ mark()
ในตําแหน่งต่างๆ ของแอปพลิเคชันจะช่วยให้คุณทราบจํานวนเวลาที่ใช้ในการเข้าถึง "เครื่องหมาย" นั้นในเว็บแอปพลิเคชัน
ข้อกำหนดระบุชื่อที่แนะนำสำหรับเครื่องหมายที่อาจน่าสนใจและสื่อความหมายในตัว เช่น mark_fully_loaded
, mark_fully_visible
,mark_above_the_fold
เป็นต้น
ตัวอย่างเช่น เราอาจทำเครื่องหมายเมื่อแอปพลิเคชันโหลดเสร็จแล้วโดยใช้โค้ดต่อไปนี้
window.performance.mark('mark_fully_loaded');
การตั้งเครื่องหมายที่มีชื่อทั่วทั้งเว็บแอปพลิเคชันช่วยให้เรารวบรวมข้อมูลการวัดเวลาจำนวนมากและวิเคราะห์ข้อมูลดังกล่าวได้ทุกเมื่อเพื่อดูว่าแอปพลิเคชันกำลังทําอะไรอยู่และเมื่อใด
การคำนวณการวัดด้วย measure()
เมื่อตั้งเครื่องหมายเวลาไว้แล้ว คุณจะต้องดูเวลาผ่านไประหว่างเครื่องหมายเหล่านั้น คุณใช้เมธอด measure()
เพื่อทำเช่นนั้น
เมธอด measure()
จะคํานวณเวลาผ่านไประหว่างเครื่องหมาย และวัดเวลาระหว่างเครื่องหมายกับชื่อเหตุการณ์ที่รู้จักกันดีในอินเทอร์เฟซ PerformanceTiming ได้ด้วย
เช่น คุณอาจคำนวณเวลาตั้งแต่ DOM เสร็จสมบูรณ์จนกว่าสถานะแอปพลิเคชันจะโหลดจนเต็มได้โดยใช้โค้ด เช่น
window.performance.measure('measure_load_from_dom', 'domComplete', 'mark_fully_loaded');
เมื่อเรียกใช้ measure()
ระบบจะจัดเก็บผลลัพธ์โดยไม่ขึ้นอยู่กับเครื่องหมายที่คุณตั้งไว้ เพื่อให้คุณเรียกดูผลลัพธ์ในภายหลังได้ การเก็บเวลาไว้ขณะที่แอปพลิเคชันทำงานอยู่จะทำให้แอปพลิเคชันยังคงตอบสนองได้ และคุณสามารถถ่ายโอนข้อมูลทั้งหมดออกหลังจากที่แอปพลิเคชันทำงานเสร็จแล้วเพื่อวิเคราะห์ในภายหลัง
การทิ้งเครื่องหมายด้วย clearMarks()
บางครั้งการลบเครื่องหมายจำนวนมากที่ตั้งไว้อาจมีประโยชน์ เช่น คุณอาจเรียกใช้แบบเป็นกลุ่มในเว็บแอปพลิเคชัน จึงต้องการเริ่มต้นใหม่ทุกครั้งที่เรียกใช้
คุณนำเครื่องหมายที่ตั้งไว้ออกได้ง่ายๆ โดยการเรียกใช้ clearMarks()
ดังนั้นโค้ดตัวอย่างด้านล่างจะลบเครื่องหมายที่มีอยู่ทั้งหมดเพื่อให้คุณตั้งค่าการเรียกใช้การจับเวลาอีกครั้งได้หากต้องการ
window.performance.clearMarks();
แน่นอนว่ามีบางสถานการณ์ที่คุณอาจไม่ต้องการล้างเครื่องหมายทั้งหมด ดังนั้นหากต้องการนำเครื่องหมายที่เฉพาะเจาะจงออก คุณก็เพียงแค่ส่งชื่อเครื่องหมายที่ต้องการนำออก เช่น โค้ดด้านล่าง
window.performance.clearMarks('mark_fully_loaded');
จะนำเครื่องหมายที่เราตั้งไว้ในตัวอย่างแรกออก โดยไม่เปลี่ยนแปลงเครื่องหมายอื่นๆ ที่เราตั้งไว้
คุณอาจต้องการนำมาตรการที่คุณสร้างขึ้นออกด้วย และก็มีวิธีการที่เกี่ยวข้องซึ่งเรียกว่า clearMeasures()
ซึ่งจะทำงานเหมือนกับ clearMarks()
ทุกประการ แต่จะใช้กับค่าการวัดที่คุณทำการวัดไว้ เช่น โค้ด
window.performance.clearMeasures('measure_load_from_dom');
จะนําการวัดที่เราทําในตัวอย่าง measure()
ด้านบนออก หากต้องการนําการวัดทั้งหมดออก การดำเนินการนี้จะทํางานเหมือนกับ clearMarks()
นั่นคือคุณเพียงเรียกใช้ clearMeasures()
โดยไม่ต้องใช้อาร์กิวเมนต์
การแสดงข้อมูลการจับเวลา
การตั้งเครื่องหมายและวัดช่วงเวลานั้นเป็นเรื่องที่ดี แต่บางครั้งคุณก็อาจต้องการดูข้อมูลการวัดเวลาดังกล่าวเพื่อทําการวิเคราะห์ ซึ่งก็ทําได้ง่ายๆ เพียงใช้อินเทอร์เฟซ PerformanceTimeline
เช่น เมธอด getEntriesByType()
ช่วยให้เรารับเวลาการทําเครื่องหมายทั้งหมดหรือเวลาการวัดทั้งหมดเป็นรายการเพื่อให้เราวนซ้ำและประมวลผลข้อมูลได้ สิ่งที่ดีคือระบบจะแสดงรายการตามลําดับเวลา คุณจึงเห็นเครื่องหมายตามลําดับที่ปรากฏในเว็บแอปพลิเคชัน
โค้ดด้านล่าง
var items = window.performance.getEntriesByType('mark');
แสดงรายการเครื่องหมายทั้งหมดที่มีการเรียกใช้ในเว็บแอปพลิเคชันของเรา ขณะที่โค้ดจะทําดังนี้
var items = window.performance.getEntriesByType('measure');
แสดงรายการการวัดผลทั้งหมดที่เราทํา
นอกจากนี้ คุณยังดูรายการรายการต่างๆ อีกครั้งได้โดยใช้ชื่อที่เฉพาะเจาะจงที่คุณตั้งไว้ ตัวอย่างเช่น โค้ด
var items = window.performance.getEntriesByName('mark_fully_loaded');
จะแสดงรายการที่มี 1 รายการซึ่งมีการประทับเวลา "mark_fully_loaded" ในพร็อพเพอร์ตี้ startTime
การกำหนดเวลาคำขอ XHR (ตัวอย่าง)
ตอนนี้เรามีภาพรวมที่ชัดเจนของ User Timing API แล้ว เราจึงใช้ API นี้เพื่อวิเคราะห์ระยะเวลาที่ XMLHttpRequests ทั้งหมดใช้ในการเรียกใช้เว็บแอปพลิเคชันได้
ก่อนอื่น เราจะแก้ไขคําขอ send()
ทั้งหมดเพื่อออกคําเรียกฟังก์ชันที่ตั้งเครื่องหมาย และในเวลาเดียวกันก็เปลี่ยนการเรียกกลับสําเร็จด้วยคําเรียกฟังก์ชันที่ตั้งเครื่องหมายอื่น จากนั้นสร้างการวัดระยะเวลาที่ใช้ในการส่งคําขอ
ดังนั้นโดยปกติแล้ว XMLHttpRequest จะมีลักษณะดังนี้
var myReq = new XMLHttpRequest();
myReq.open('GET', url, true);
myReq.onload = function(e) {
do_something(e.responseText);
}
myReq.send();
ในตัวอย่างนี้ เราจะเพิ่มตัวนับส่วนกลางเพื่อติดตามจํานวนคําขอ รวมถึงใช้ตัวนับดังกล่าวเพื่อจัดเก็บการวัดผลสําหรับคําขอแต่ละรายการที่ส่ง โค้ดสําหรับดําเนินการนี้จะมีลักษณะดังนี้
var reqCnt = 0;
var myReq = new XMLHttpRequest();
myReq.open('GET', url, true);
myReq.onload = function(e) {
window.performance.mark('mark_end_xhr');
reqCnt++;
window.performance.measure('measure_xhr_' + reqCnt, 'mark_start_xhr', 'mark_end_xhr');
do_something(e.responseText);
}
window.performance.mark('mark_start_xhr');
myReq.send();
โค้ดด้านบนจะสร้างการวัดที่มีค่าชื่อที่ไม่ซ้ำกันสําหรับ XMLHttpRequest ทั้งหมดที่เราส่ง เราสมมติว่าคําขอทํางานตามลําดับ โค้ดสําหรับคําขอแบบขนานจะต้องมีความซับซ้อนมากขึ้นเล็กน้อยเพื่อจัดการคําขอที่แสดงผลไม่เป็นลําดับ เราจะไม่อธิบายเรื่องนี้เพื่อมอบหมายให้ผู้อ่านลองทํา
เมื่อเว็บแอปพลิเคชันส่งคําขอจํานวนมากแล้ว เราอาจส่งออกคําขอทั้งหมดไปยังคอนโซลได้โดยใช้โค้ดด้านล่างนี้
var items = window.performance.getEntriesByType('measure');
for (var i = 0; i < items.length; ++i) {
var req = items[i];
console.log('XHR ' + req.name + ' took ' + req.duration + 'ms');
}
บทสรุป
User Timing API มีเครื่องมือที่ยอดเยี่ยมมากมายให้คุณนำไปใช้กับทุกแง่มุมของเว็บแอปพลิเคชัน การจํากัดขอบเขตฮอตสปอตในแอปพลิเคชันให้แคบลงทําได้ง่ายๆ โดยการเรียกใช้ API ทั่วทั้งเว็บแอปพลิเคชันและประมวลผลข้อมูลเวลาที่เกิดขึ้นในภายหลังเพื่อสร้างภาพรวมที่ชัดเจนว่าเวลาส่วนใหญ่หมดไปกับที่ใด แต่จะเกิดอะไรขึ้นหากเบราว์เซอร์ของคุณไม่รองรับ API นี้ ไม่มีปัญหา คุณสามารถดูโพลีฟีลที่ยอดเยี่ยมได้ที่นี่ ซึ่งจําลอง API ได้อย่างยอดเยี่ยมและทํางานร่วมกับ webpagetest.org ได้เป็นอย่างดี จะมัวรอช้าอยู่ทำไม ลองใช้ User Timing API ในแอปพลิเคชันของคุณเลย คุณจะได้หาวิธีเพิ่มความเร็วให้แอปพลิเคชันและผู้ใช้จะขอบคุณคุณที่ทำให้ประสบการณ์การใช้งานดีขึ้นมาก