ใน Chrome 102 คุณจะเห็นแผงทดลองใหม่ชื่อข้อมูลเชิงลึกเกี่ยวกับประสิทธิภาพในเครื่องมือสำหรับนักพัฒนาเว็บ ในโพสต์นี้ เราจะพูดถึงไม่เพียงแต่เหตุผลที่เราได้พัฒนาแผงควบคุมใหม่ แต่ยังรวมถึงความท้าทายทางเทคนิคที่เราเผชิญและสิ่งที่ตัดสินใจไปตลอดเส้นทางนี้ด้วย
ทำไมต้องสร้างแผงอื่น
(หากยังไม่เคยเห็น เราได้โพสต์วิดีโอเกี่ยวกับเหตุผลในการสร้างแผงข้อมูลเชิงลึกด้านประสิทธิภาพและวิธีรับข้อมูลเชิงลึกที่นำไปใช้ได้จริงเกี่ยวกับประสิทธิภาพของเว็บไซต์ด้วยแผงนี้)
แผงประสิทธิภาพที่มีอยู่เป็นแหล่งข้อมูลที่ยอดเยี่ยมหากคุณต้องการดูข้อมูลทั้งหมดของเว็บไซต์ในที่เดียว แต่เราคิดว่าอาจจะดูยากไปสักหน่อย หากคุณไม่ใช่ผู้เชี่ยวชาญด้านประสิทธิภาพ ก็อาจยากที่จะทราบว่าควรดูอะไรและส่วนใดของการบันทึกที่เกี่ยวข้อง
เข้าสู่แผงข้อมูลเชิงลึก ซึ่งคุณยังคงดูไทม์ไลน์ของการติดตามและตรวจสอบข้อมูลได้ แต่ยังได้รับรายการที่มีประโยชน์เกี่ยวกับสิ่งที่ DevTools ถือว่าเป็น "ข้อมูลเชิงลึก" หลักที่ควรเจาะลึกด้วย ข้อมูลเชิงลึกจะระบุปัญหาต่างๆ เช่น คำขอที่บล็อกการแสดงผล การเปลี่ยนเลย์เอาต์ และงานที่ใช้เวลานาน เป็นต้น ซึ่งทั้งหมดนี้อาจส่งผลเสียต่อประสิทธิภาพการโหลดหน้าเว็บของเว็บไซต์ และโดยเฉพาะคะแนน Core Web Vitals (CWV) ของเว็บไซต์ นอกเหนือจากการแจ้งปัญหาแล้ว ข้อมูลเชิงลึกด้านประสิทธิภาพยังจะให้คำแนะนำที่นำไปใช้ได้จริงเพื่อปรับปรุงคะแนน CWV รวมถึงลิงก์ไปยังแหล่งข้อมูลและเอกสารเพิ่มเติม
แผงนี้อยู่ระหว่างการทดลอง และเราอยากทราบความคิดเห็นจากคุณ โปรดแจ้งให้เราทราบหากพบข้อบกพร่อง หรือมีคำขอฟีเจอร์ที่คุณคิดว่าจะช่วยคุณได้เมื่อทำงานเกี่ยวกับประสิทธิภาพของเว็บไซต์
วิธีที่เราสร้างข้อมูลเชิงลึกเกี่ยวกับประสิทธิภาพ
เราสร้างข้อมูลเชิงลึกด้านประสิทธิภาพใน TypeScript และใช้คอมโพเนนต์เว็บที่ขับเคลื่อนโดย lit-html เพื่อสร้างอินเทอร์เฟซผู้ใช้ เช่นเดียวกับส่วนอื่นๆ ของ DevTools สิ่งที่แตกต่างกันในข้อมูลเชิงลึกด้านประสิทธิภาพคืออินเทอร์เฟซ UI หลักเป็นองค์ประกอบ canvas
ของ HTML และไทม์ไลน์จะวาดลงใน Canvas นี้ ความซับซ้อนส่วนใหญ่มาจากการจัดการ Canvas นี้ ไม่ใช่แค่การวาดรายละเอียดที่ถูกต้องในตำแหน่งที่ถูกต้อง แต่ยังรวมถึงการจัดการเหตุการณ์ของเมาส์ (เช่น ผู้ใช้คลิกที่ใดบน Canvas) ผู้ใช้คลิกเหตุการณ์ที่เราวาดหรือไม่) และตรวจสอบว่าเราแสดงผล Canvas อีกครั้งได้อย่างมีประสิทธิภาพ
หลายแทร็กในแคนวาสเดียว
สำหรับเว็บไซต์หนึ่งๆ จะมี "แทร็ก" หลายรายการที่เราต้องการแสดงผล โดยแต่ละรายการแสดงถึงหมวดหมู่ข้อมูลที่แตกต่างกัน ตัวอย่างเช่น แผงข้อมูลเชิงลึกจะแสดง 3 แทร็กโดยค่าเริ่มต้น ดังนี้
และเมื่อเราเปิดตัวฟีเจอร์ต่างๆ ในแผงต่อไป เราคาดว่าจะมีแทร็กเพิ่มขึ้น
แนวคิดแรกของเราคือให้แต่ละแทร็กแสดงผล <canvas>
ของตัวเอง เพื่อให้มุมมองหลักกลายเป็นองค์ประกอบ Canvas หลายรายการที่ซ้อนกันในแนวตั้ง วิธีนี้จะช่วยลดความซับซ้อนในการแสดงผลในระดับแทร็ก เนื่องจากแต่ละแทร็กสามารถแสดงผลแยกกันได้ และจะไม่มีความเสี่ยงที่แทร็กจะแสดงผลนอกขอบเขตของตัวเอง แต่โชคไม่ดีที่วิธีนี้มีปัญหาหลัก 2 ประการ ได้แก่
องค์ประกอบ canvas
มีค่าใช้จ่ายสูงในการ (แสดงผลซ้ำ) การมี Canvas หลายรายการมีค่าใช้จ่ายสูงกว่า Canvas รายการเดียว แม้ว่า Canvas นั้นจะมีขนาดใหญ่กว่าก็ตาม
การแสดงภาพซ้อนทับที่ข้ามแทร็กหลายรายการ (เช่น เส้นแนวตั้งเพื่อทำเครื่องหมายเหตุการณ์ต่างๆ เช่น เวลา FCP) จะมีความซับซ้อนมากขึ้น เนื่องจากเราต้องแสดงผลบน Canvas หลายรายการและตรวจสอบว่าได้แสดงผลทั้งหมดพร้อมกันและจัดแนวอย่างถูกต้อง
การใช้ canvas
เดียวสำหรับ UI ทั้งหมดหมายความว่าเราต้องหาวิธีตรวจสอบว่าแต่ละแทร็กแสดงผลที่พิกัดที่ถูกต้องและไม่ล้นไปยังแทร็กอื่น เช่น หากแทร็กหนึ่งสูง 100 พิกเซล เราจะแสดงผลสิ่งที่สูง 120 พิกเซลและทำให้ล้นไปยังแทร็กที่อยู่ด้านล่างไม่ได้ เราสามารถใช้ clip
เพื่อแก้ไขปัญหานี้ได้ ก่อนที่จะแสดงแต่ละแทร็ก เราจะวาดสี่เหลี่ยมผืนผ้าที่แสดงหน้าต่างแทร็กที่มองเห็นได้ ซึ่งจะช่วยให้มั่นใจได้ว่า Canvas จะตัดเส้นทางที่วาดนอกขอบเขตเหล่านี้
canvasContext.beginPath();
canvasContext.rect(
trackVisibleWindow.x, trackVisibleWindow.y, trackVisibleWindow.width, trackVisibleWindow.height);
canvasContext.clip();
นอกจากนี้ เรายังไม่ต้องการให้แต่ละแทร็กต้องทราบตำแหน่งในแนวตั้งของตัวเองด้วย โดยแต่ละแทร็กควรแสดงผลตัวเองราวกับว่ากำลังแสดงผลที่ (0, 0) และเรามีคอมโพเนนต์ระดับสูงกว่า (ซึ่งเราเรียกว่า TrackManager
) เพื่อจัดการตำแหน่งแทร็กโดยรวม ซึ่งทำได้ด้วย translate
ซึ่งจะแปลผืนผ้าใบตามตำแหน่ง (x, y) ที่กำหนด เช่น
canvasContext.translate(0, 10); // Translate by 10px in the y direction
canvasContext.rect(0, 0, 10, 10); // draw a rectangle at (0, 0) that’s 10px high and wide
แม้ว่าrect
การตั้งค่ารหัส0, 0
เป็นตำแหน่ง แต่การแปลโดยรวมที่ใช้จะทำให้สี่เหลี่ยมผืนผ้าแสดงผลที่0, 10
ซึ่งช่วยให้เราทำงานในระดับแทร็กได้ราวกับว่ากำลังเรนเดอร์ที่ (0, 0) และให้ตัวจัดการแทร็กแปลขณะเรนเดอร์แต่ละแทร็กเพื่อให้มั่นใจว่าแต่ละแทร็กได้รับการเรนเดอร์อย่างถูกต้องใต้แทร็กก่อนหน้า
Canvas นอกหน้าจอสำหรับแทร็กและไฮไลต์
การแสดงผล Canvas มีค่าใช้จ่ายค่อนข้างสูง และเราต้องการให้แผงข้อมูลเชิงลึกทำงานได้อย่างราบรื่นและตอบสนองได้ดีขณะที่คุณใช้งาน บางครั้งคุณก็หลีกเลี่ยงการแสดงผล Canvas ทั้งหมดซ้ำไม่ได้ เช่น หากเปลี่ยนระดับการซูม เราจะต้องเริ่มใหม่และแสดงผลทุกอย่างซ้ำ การแสดงผล Canvas อีกครั้งมีค่าใช้จ่ายสูงเป็นพิเศษเนื่องจากคุณไม่สามารถแสดงผลเพียงส่วนเล็กๆ ของ Canvas อีกครั้งได้ คุณต้องล้าง Canvas ทั้งหมดและวาดใหม่ ซึ่งแตกต่างจากการแสดงผล DOM อีกครั้งที่เครื่องมือสามารถคำนวณงานขั้นต่ำที่จำเป็นและไม่นำทุกอย่างออกแล้วเริ่มต้นใหม่
ปัญหาด้านภาพที่เราพบคือการไฮไลต์ เมื่อวางเมาส์เหนือเมตริกในแผง เราจะไฮไลต์เมตริกนั้นในไทม์ไลน์ และในทำนองเดียวกัน หากวางเมาส์เหนือข้อมูลเชิงลึกสำหรับเหตุการณ์หนึ่งๆ เราจะวาดเส้นขอบสีน้ำเงินรอบเหตุการณ์นั้น
ฟีเจอร์นี้ได้รับการติดตั้งใช้งานครั้งแรกโดยการตรวจจับการเลื่อนเมาส์เหนือองค์ประกอบที่ทริกเกอร์การไฮไลต์ จากนั้นจึงวาดไฮไลต์นั้นลงใน Canvas หลักโดยตรง ปัญหาเกิดขึ้นเมื่อเราต้องนำไฮไลต์ออก เนื่องจากตัวเลือกเดียวที่มีคือการวาดใหม่ทั้งหมด การวาดพื้นที่ที่มีการไฮไลต์ใหม่เพียงอย่างเดียวเป็นไปไม่ได้ (หากไม่มีการเปลี่ยนแปลงสถาปัตยกรรมครั้งใหญ่) แต่การวาดผืนผ้าใบทั้งหมดใหม่เพียงเพราะต้องการนำเส้นขอบสีน้ำเงินรอบๆ รายการหนึ่งออกก็ดูเหมือนจะมากเกินไป นอกจากนี้ ยังอาจเกิดความล่าช้าทางภาพหากคุณเลื่อนเมาส์อย่างรวดเร็วไปเหนือรายการต่างๆ เพื่อไฮไลต์หลายรายการติดต่อกันอย่างรวดเร็ว
เราจึงแบ่ง UI ออกเป็น 2 Canvas นอกหน้าจอเพื่อแก้ไขปัญหานี้ ได้แก่ Canvas "หลัก" ซึ่งเป็นที่ที่แทร็กแสดงผล และ Canvas "ไฮไลต์" ซึ่งเป็นที่ที่วาดไฮไลต์ จากนั้นเราจะแสดงผลโดยการคัดลอก Canvas เหล่านั้นไปยัง Canvas เดียวที่ผู้ใช้มองเห็นบนหน้าจอ เราสามารถใช้วิธี drawImage
ในบริบท Canvas ซึ่งสามารถใช้ Canvas อื่นเป็นแหล่งที่มาได้
การทำเช่นนี้หมายความว่าการนำไฮไลต์ออกจะไม่ทำให้ระบบวาดผืนผ้าใบหลักใหม่ แต่เราจะล้างผืนผ้าใบบนหน้าจอ แล้วคัดลอกผืนผ้าใบหลักไปยังผืนผ้าใบที่มองเห็นแทน การคัดลอก Canvas นั้นไม่แพง แต่การวาดภาพนั้นแพง ดังนั้นการย้ายไฮไลต์ไปยัง Canvas แยกต่างหากจะช่วยให้เราไม่ต้องเสียค่าใช้จ่ายดังกล่าวเมื่อเปิดและปิดไฮไลต์
การแยกวิเคราะห์การติดตามที่ผ่านการทดสอบอย่างครอบคลุม
ข้อดีอย่างหนึ่งของการสร้างฟีเจอร์ใหม่ตั้งแต่ต้นคือคุณสามารถพิจารณาตัวเลือกทางเทคนิคที่เลือกไว้ก่อนหน้านี้และทำการปรับปรุงได้ สิ่งหนึ่งที่เราต้องการปรับปรุงคือการแยกโค้ดออกเป็น 2 ส่วนอย่างชัดเจน ซึ่งแทบจะแยกกันโดยสิ้นเชิง
แยกวิเคราะห์ไฟล์การติดตามและดึงข้อมูลที่จำเป็นออกมา แสดงผลชุดแทร็ก
การแยกการแยกวิเคราะห์ (ส่วนที่ 1) ออกจากงาน UI (ส่วนที่ 2) ช่วยให้เราสร้างระบบการแยกวิเคราะห์ที่แข็งแกร่งได้ โดยการติดตามแต่ละรายการจะผ่านชุดตัวแฮนเดิลซึ่งรับผิดชอบในเรื่องต่างๆ ได้แก่ LayoutShiftHandler
คำนวณข้อมูลทั้งหมดที่เราต้องการสำหรับการเปลี่ยนแปลงเลย์เอาต์ และ NetworkRequestsHandler
จัดการกับการดึงคำขอเครือข่ายโดยเฉพาะ การมีขั้นตอนการแยกวิเคราะห์ที่ชัดเจนนี้ ซึ่งเรามีแฮนเดิลเลอร์ที่แตกต่างกันซึ่งรับผิดชอบส่วนต่างๆ ของการติดตามก็เป็นประโยชน์เช่นกัน เนื่องจากอาจมีการแยกวิเคราะห์การติดตามที่ซับซ้อนมาก และการมุ่งเน้นที่ปัญหาหนึ่งๆ ในแต่ละครั้งก็ช่วยได้
นอกจากนี้ เรายังทดสอบการแยกวิเคราะห์ร่องรอยได้อย่างครอบคลุมด้วยการบันทึกในเครื่องมือสำหรับนักพัฒนาเว็บ บันทึกไว้ แล้วโหลดเป็นส่วนหนึ่งของชุดการทดสอบ ซึ่งเป็นเรื่องดีเพราะเราสามารถทดสอบด้วยการติดตามจริงได้ และไม่ต้องสร้างข้อมูลการติดตามปลอมจำนวนมากที่อาจล้าสมัย
การทดสอบภาพหน้าจอสำหรับ UI ของ Canvas
เมื่อพูดถึงเรื่องการทดสอบ เรามักจะทดสอบคอมโพเนนต์ส่วนหน้าโดยการแสดงผลในเบราว์เซอร์และตรวจสอบว่าคอมโพเนนต์ทำงานตามที่คาดไว้ เราสามารถส่งเหตุการณ์คลิกเพื่อทริกเกอร์การอัปเดต และยืนยันว่า DOM ที่คอมโพเนนต์สร้างขึ้นนั้นถูกต้อง แนวทางนี้ใช้ได้ผลดีสำหรับเรา แต่ใช้ไม่ได้เมื่อพิจารณาการแสดงผลใน Canvas เนื่องจากไม่มีวิธีตรวจสอบ Canvas และพิจารณาว่ามีการวาดอะไรในนั้น ดังนั้นแนวทางปกติของเราในการแสดงผลแล้วจึงค้นหาจึงไม่เหมาะสม
เราจึงหันมาใช้การทดสอบภาพหน้าจอเพื่อให้มีการทดสอบบางส่วน การทดสอบแต่ละครั้งจะเปิด Canvas, แสดงแทร็กที่เราต้องการทดสอบ แล้วจึงจับภาพหน้าจอขององค์ประกอบ Canvas จากนั้นระบบจะจัดเก็บภาพหน้าจอนี้ไว้ในโค้ดเบส และการทดสอบในอนาคตจะเปรียบเทียบภาพหน้าจอที่จัดเก็บไว้กับภาพหน้าจอที่สร้างขึ้น หากภาพหน้าจอแตกต่างกัน การทดสอบจะไม่สำเร็จ นอกจากนี้ เรายังมีแฟล็กสำหรับเรียกใช้การทดสอบและบังคับให้อัปเดตภาพหน้าจอเมื่อเราจงใจเปลี่ยนการแสดงผลและจำเป็นต้องอัปเดตการทดสอบ
การทดสอบภาพหน้าจอไม่ได้สมบูรณ์แบบและค่อนข้างตรงไปตรงมา คุณทดสอบได้เพียงว่าคอมโพเนนต์ทั้งหมดแสดงผลตามที่คาดไว้ ไม่ใช่การยืนยันที่เฉพาะเจาะจงมากขึ้น และในตอนแรกเราก็ใช้การทดสอบนี้มากเกินไปเพื่อให้แน่ใจว่าคอมโพเนนต์ทุกรายการ (HTML หรือ Canvas) แสดงผลอย่างถูกต้อง ซึ่งทำให้ชุดการทดสอบของเราช้าลงอย่างมาก และทำให้เกิดปัญหาที่การปรับแต่ง UI เล็กๆ น้อยๆ ที่แทบจะไม่เกี่ยวข้อง (เช่น การเปลี่ยนสีเล็กน้อย หรือการเพิ่มระยะขอบระหว่างรายการ) ทำให้ภาพหน้าจอหลายภาพล้มเหลวและต้องอัปเดต ตอนนี้เราได้ลดการใช้ภาพหน้าจอลง และใช้เฉพาะกับคอมโพเนนต์ที่อิงตาม Canvas เท่านั้น ซึ่งการปรับสมดุลนี้ได้ผลดีสำหรับเราจนถึงตอนนี้
บทสรุป
การสร้างแผงข้อมูลเชิงลึกเกี่ยวกับประสิทธิภาพใหม่เป็นประสบการณ์ที่สนุกและให้ความรู้แก่ทีมของเราเป็นอย่างมาก เราได้เรียนรู้มากมายเกี่ยวกับไฟล์การติดตาม การทำงานกับ Canvas และอื่นๆ อีกมากมาย เราหวังว่าคุณจะสนุกกับการใช้แผงใหม่นี้ และรอฟังความคิดเห็นจากคุณ
ดูข้อมูลเพิ่มเติมเกี่ยวกับแผงข้อมูลเชิงลึกเกี่ยวกับประสิทธิภาพได้ที่ข้อมูลเชิงลึกเกี่ยวกับประสิทธิภาพ: รับข้อมูลเชิงลึกที่นําไปใช้ได้จริงเกี่ยวกับประสิทธิภาพของเว็บไซต์
ดาวน์โหลดช่องตัวอย่าง
ลองใช้ Chrome Canary, Dev หรือ Beta เป็นเบราว์เซอร์เริ่มต้นสำหรับการพัฒนา ช่องตัวอย่างเหล่านี้ช่วยให้คุณเข้าถึงฟีเจอร์ล่าสุดของ DevTools ทดสอบ API ของแพลตฟอร์มเว็บที่ล้ำสมัย และช่วยคุณค้นหาปัญหาในเว็บไซต์ก่อนที่ผู้ใช้จะพบ
ติดต่อทีมเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome
ใช้ตัวเลือกต่อไปนี้เพื่อพูดคุยเกี่ยวกับฟีเจอร์ใหม่ การอัปเดต หรือสิ่งอื่นๆ ที่เกี่ยวข้องกับเครื่องมือสำหรับนักพัฒนาเว็บ
- ส่งความคิดเห็นและคำขอฟีเจอร์มาให้เราที่ crbug.com
- รายงานปัญหาเกี่ยวกับเครื่องมือสำหรับนักพัฒนาเว็บโดยใช้ ตัวเลือกเพิ่มเติม > ความช่วยเหลือ > รายงานปัญหาเกี่ยวกับเครื่องมือสำหรับนักพัฒนาเว็บในเครื่องมือสำหรับนักพัฒนาเว็บ
- ทวีตถึง @ChromeDevTools
- แสดงความคิดเห็นในวิดีโอ YouTube เกี่ยวกับฟีเจอร์ใหม่ในเครื่องมือสำหรับนักพัฒนาเว็บหรือวิดีโอ YouTube เกี่ยวกับเคล็ดลับเครื่องมือสำหรับนักพัฒนาเว็บ