กรณีศึกษานี้อธิบายเวิร์กโฟลว์การแก้ไขข้อบกพร่องและปรับปรุง INP ใน React ที่ Trendyol ใช้โดยใช้ประโยชน์จากเครื่องมือของ Google เช่น PageSpeed Insight (PSI), Chrome DevTools และ scheduler.yield
API
องค์ประกอบสำคัญ 2 ประการของเว็บไซต์อีคอมเมิร์ซคือหน้าข้อมูลผลิตภัณฑ์ (PLP) และหน้ารายละเอียดผลิตภัณฑ์ (PDP) การเข้าชมอีคอมเมิร์ซมักมาจากหน้าข้อมูลผลิตภัณฑ์ที่แสดง ไม่ว่าจะผ่านแคมเปญอีเมล โซเชียลมีเดีย หรือโฆษณา ด้วยเหตุนี้ ประสบการณ์ PLP จึงต้องได้รับการออกแบบอย่างรอบคอบเพื่อลดเวลาในการซื้อ การให้ความสําคัญกับคุณภาพของประสบการณ์ของผู้ใช้เป็นสิ่งจําเป็นต่อความสําเร็จ ผลงานวิจัยต่างๆ เช่น Milliseconds Make Millions ได้แสดงให้เห็นถึงผลกระทบที่สําคัญของประสิทธิภาพเว็บที่มีต่อความเต็มใจของผู้บริโภคที่จะใช้จ่ายเงินและมีส่วนร่วมกับแบรนด์ทางออนไลน์
Trendyol เป็นแพลตฟอร์มอีคอมเมิร์ซที่มีลูกค้าประมาณ 30 ล้านรายและผู้ขาย 240,000 ราย ซึ่งช่วยให้เรากลายเป็นธุรกิจแรกในตุรกีที่มีมูลค่ามากกว่า 10,000 ล้านดอลลาร์สหรัฐ และเป็นหนึ่งในแพลตฟอร์มอีคอมเมิร์ซชั้นนำของโลก
Trendyol มุ่งเน้นที่ Interaction to Next Paint (INP) เป็นเมตริกหลักในการปรับปรุงเพื่อให้บรรลุเป้าหมายในการมอบประสบการณ์การใช้งานที่ดีที่สุดในวงกว้างไปพร้อมกับคงความยืดหยุ่นของเนื้อหาและทำงานร่วมกับ React เวอร์ชันเก่า กรณีศึกษานี้อธิบายเส้นทางการปรับปรุง INP ใน PLP ของ Trendyol ซึ่งส่งผลให้ INP ลดลง 50% และเมตริกธุรกิจผลการค้นหาเพิ่มขึ้น 1%
กระบวนการตรวจสอบ INP ของ Trendyol
INP จะวัดการตอบสนองของเว็บไซต์ต่ออินพุตของผู้ใช้ INP ที่ดีบ่งชี้ว่าเบราว์เซอร์สามารถตอบสนองต่ออินพุตทั้งหมดของผู้ใช้อย่างรวดเร็วและเสถียร รวมถึงวาดหน้าเว็บใหม่ได้ ซึ่งเป็นองค์ประกอบสําคัญของประสบการณ์การใช้งานที่ดี
เส้นทางการปรับปรุง INP ใน PLP ของ Trendyol เริ่มต้นด้วยการวิเคราะห์ประสบการณ์ของผู้ใช้อย่างละเอียดก่อนที่จะทำการปรับปรุง จากรายงาน PSI พบว่าประสบการณ์การใช้งานจริงของ PLP มี INP 963 มิลลิวินาทีบนอุปกรณ์เคลื่อนที่ ดังที่แสดงในรูปภาพถัดไป
เจ้าของเว็บไซต์ควรมุ่งเน้นที่ INP ต่ำกว่าหรือเท่ากับ 200 มิลลิวินาทีเพื่อให้การตอบสนองดี ซึ่งหมายความว่า INP ของ Trendyol อยู่ในระดับ "แย่" ณ ขณะนั้น
แต่โชคดีที่ PSI มีทั้งข้อมูลในช่องสำหรับหน้าเว็บที่รวมอยู่ในรายงานประสบการณ์ของผู้ใช้ Chrome (CrUX) และข้อมูลการวินิจฉัยจากห้องทดลองโดยละเอียด เมื่อดูข้อมูลในแล็บ การตรวจสอบเวลาดำเนินการ JavaScript ของ Lighthouse ชี้ว่าสคริปต์ search-result-v2
ใช้เธรดหลักนานกว่าสคริปต์อื่นๆ ในหน้า
เราใช้แผงประสิทธิภาพใน Chrome DevTools เพื่อแก้ปัญหาเกี่ยวกับประสบการณ์การใช้งาน PLP และระบุแหล่งที่มาของปัญหาเพื่อหาจุดคอขวดในชีวิตจริง การจําลองประสิทธิภาพของอุปกรณ์เคลื่อนที่ด้วยการทําให้ CPU ทำงานช้าลง 4 เท่าในเครื่องมือสําหรับนักพัฒนาซอฟต์แวร์ของ Chrome พบว่ามีงานที่ใช้เวลา 700-900 มิลลิวินาทีในเธรดหลัก หากเธรดหลักไม่ว่างเนื่องจากมีงานอื่นๆ นานกว่า 50 มิลลิวินาที เธรดอาจไม่สามารถตอบสนองต่ออินพุตของผู้ใช้ได้อย่างทันท่วงที ซึ่งส่งผลให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ไม่ดี
งานที่มีระยะเวลานานที่สุดเกิดจากคอลแบ็ก Intersection Observer API ในสคริปต์ผลการค้นหาภายในคอมโพเนนต์ React เมื่อถึงจุดนี้ เราเริ่มพิจารณาการแบ่งงานระยะยาวออกเป็นชิ้นเล็กๆ เพื่อให้เบราว์เซอร์มีโอกาสตอบสนองต่องานที่มีความสำคัญมากกว่าได้มากขึ้น ซึ่งรวมถึงการโต้ตอบของผู้ใช้
ปรากฏว่าการใช้การดำเนินการ setState
ซึ่งทริกเกอร์ React ให้แสดงผลใหม่ภายในการเรียกกลับ Intersection Observer นั้นใช้ทรัพยากรมาก ซึ่งอาจทำให้เกิดปัญหากับอุปกรณ์ระดับล่างเนื่องจากใช้เธรดหลักนานเกินไป
วิธีหนึ่งที่นักพัฒนาซอฟต์แวร์ใช้แบ่งงานออกเป็นงานเล็กๆ คือการใช้ setTimeout
เราใช้เทคนิคนี้เพื่อเลื่อนการดำเนินการเรียกใช้ setState
ไปเป็นงานแยกต่างหาก แม้ว่า setTimeout
จะเลื่อนการเรียกใช้ JavaScript ได้ แต่ก็ไม่ได้ให้การควบคุมลําดับความสําคัญ ด้วยเหตุนี้ เราจึงเข้าร่วมช่วงทดลองใช้จากต้นทางของ scheduler.yield
เพื่อรับประกันการดําเนินการของสคริปต์ต่อไปหลังจากให้สิทธิ์แก่เธรดหลัก
/*
* Yielding method using scheduler.yield, falling back to setTimeout:
*/
async function yieldToMain() {
if('scheduler' in window && 'yield' in scheduler) {
return await scheduler.yield();
}
return new Promise(resolve => {
setTimeout(resolve, 0);
});
}
/*
* Yielding to the main thread before changing the state of the component:
*/
const observer = new IntersectionObserver((entries) => {
entries.forEach(handleIntersection);
const maxNumberOfEntries = Math.max(...this.intersectingEntries);
if (Number.isFinite(maxNumberOfEntries)) {
await this.yieldToMain();
this.setState({ count: maxNumberOfEntries });
}
}, { threshold: 0.5 });
การเพิ่มวิธีการให้ผลลัพธ์นี้ลงในโค้ด PLP ทำให้ INP ดีขึ้น เนื่องจากมีการแยกงานหลักที่ใช้เวลานานออกเป็นชุดงานย่อยๆ ซึ่งช่วยให้งานที่มีลำดับความสำคัญสูงกว่า เช่น การโต้ตอบของผู้ใช้และการเรนเดอร์งานต่อๆ ไป ทำงานได้เร็วขึ้น
โปรดทราบว่า Trendyol ใช้เฟรมเวิร์ก PuzzleJs เพื่อติดตั้งใช้งานสถาปัตยกรรม Micro-Frontend โดยใช้ React v16.9.0 React 18 จะให้ประสิทธิภาพที่เท่าเดิม แต่ Trendyol อัปเกรดไม่ได้ในตอนนี้ด้วยเหตุผลหลายประการ
ผลลัพธ์ทางธุรกิจ
เราได้ทำการทดสอบ A/B เพื่อวัดผลกระทบของการปรับปรุง INP ที่ติดตั้งใช้งาน เพื่อดูว่าเมตริกทางธุรกิจได้รับผลกระทบอย่างไร โดยรวมแล้ว การเปลี่ยนแปลง PLP ของเราส่งผลให้เกิดการเปลี่ยนแปลงที่สำคัญ ซึ่งรวมถึงการลด INP ลง 50% และอัตราการคลิกผ่านจากหน้าข้อมูลไปยังหน้ารายละเอียดผลิตภัณฑ์เพิ่มขึ้น 1% ต่อเซสชันของผู้ใช้ ในรูปภาพต่อไปนี้ คุณจะเห็นว่า INP ปรับปรุงใน PLP อย่างไรเมื่อเวลาผ่านไป
บทสรุป
การเพิ่มประสิทธิภาพ INP เป็นกระบวนการที่ซับซ้อนและต้องทำซ้ำๆ แต่สามารถทําได้ง่ายขึ้นด้วยเวิร์กโฟลว์ที่ชัดเจน แนวทางที่ง่ายในการแก้ไขข้อบกพร่องและปรับปรุง INP ของเว็บไซต์ขึ้นอยู่กับว่าคุณกำลังรวบรวมข้อมูลภาคสนามของคุณเองหรือไม่ หากยังไม่พร้อม PSI และ Lighthouse ก็เป็นจุดเริ่มต้นที่ดี เมื่อพบหน้าเว็บที่มีปัญหาแล้ว คุณสามารถใช้เครื่องมือสำหรับนักพัฒนาเว็บเพื่อเจาะลึกปัญหาและพยายามทําให้เกิดปัญหานั้นขึ้นอีกครั้ง
การให้สิทธิ์แก่เธรดหลักเป็นครั้งคราวเพื่อให้เบราว์เซอร์มีโอกาสทำงานเร่งด่วนมากขึ้นจะทำให้เว็บไซต์ตอบสนองได้ดีขึ้น ซึ่งจะช่วยให้ลูกค้าได้รับประสบการณ์การใช้งานที่ดีขึ้น API การจัดตารางเวลารุ่นใหม่ๆ เช่น scheduler.yield()
ช่วยให้งานนี้ง่ายขึ้น
ขอขอบคุณเป็นพิเศษ Jeremy Wagner, Barry Pollard และ Houssein Djirdeh จาก Google รวมถึงทีมวิศวกรของ Trendyol ที่ให้ความร่วมมือในงานนี้