เรื่องราวการสร้าง Tech Stack ของ Facebook ขึ้นใหม่
(engineering.fb.com)Facebook ที่เริ่มต้นจาก PHP แบบเรียบง่าย ได้ปรับเปลี่ยนไปสู่ React + Relay(GraphQL) ให้สอดรับกับดีไซน์ใหม่ครั้งนี้อย่างไร พร้อมบทเรียนที่ได้รับ
นำหลักการพื้นฐานสำหรับแอปที่รวดเร็วไปใช้กับ CSS, JS, Data, Navigation แต่ละส่วน
-
ส่งเฉพาะทรัพยากรที่จำเป็นให้เร็วที่สุดเท่าที่จะทำได้
-
ประสบการณ์ด้านวิศวกรรมเพื่อประสบการณ์ผู้ใช้ที่ดี
CSS
-
ลด CSS ลง 80% ด้วย Atomic CSS และปรับให้ไม่ต้องดาวน์โหลด CSS ที่ไม่จำเป็น
-
ใช้ rems เพื่อการเข้าถึง และเพื่อ ลดบั๊กจากการแปลง px → rems ด้วยมือ จึงให้ build tool แปลงให้อัตโนมัติ
-
ใช้ตัวแปร CSS สำหรับ Theming (Dark Mode)
-
ใช้ Inline SVG เพื่อป้องกันอาการกะพริบ (แทนการใส่ไฟล์ SVG ใน img) ทำให้สามารถเปลี่ยนสีได้ขณะรันไทม์ด้วย
JS
- ส่ง JS ที่ทำ Code-splitting แบบ 3 ขั้นเป็นลำดับ
Tier 1. เลย์เอาต์พื้นฐานเพื่อให้ UI Skeleton แสดงได้อย่างรวดเร็วระหว่างโหลด
Tier 2. JS สำหรับเรนเดอร์คอนเทนต์ทั้งหมดที่มองเห็นบนหน้าจอให้สมบูรณ์ ต้องใช้งานได้เต็มรูปแบบ และแม้โค้ดจะโหลดหลัง Tier 2 แล้ว โครงหน้าจอก็ต้องไม่เปลี่ยน
Tier 3. ทุกสิ่งที่จำเป็นหลังจากแสดงหน้าจอแล้ว เช่น โค้ด logging, การ subscribe อัปเดตแบบเรียลไทม์ เป็นต้น
-
แบ่ง JS ขนาด 500KB ออกเป็น 50KB สำหรับ Tier 1, 150KB สำหรับ Tier 2, 300KB สำหรับ Tier 3 → ส่งผลให้การโหลดและการแสดงผลหน้าจอเสร็จเร็วมาก
-
ด้วยการแยกส่วน ทำให้ตอนทำ A/B test ก็สามารถตั้งค่าให้แต่ละฝั่งรับเฉพาะโค้ดที่จำเป็นได้
-
ใช้ความสามารถของ Relay ที่ช่วยสร้างแอป React แบบ Data-Driven ทำให้โหลดเฉพาะคอมโพเนนต์ที่จำเป็นตามข้อมูลที่จะดึงมา
-
นำระบบ JS Budget ต่อ Product มาใช้ โดยตั้งงบประมาณตามเป้าหมายด้านประสิทธิภาพ ข้อจำกัดทางเทคนิค และปัจจัยของผลิตภัณฑ์ เพื่อป้องกันไม่ให้โค้ดพอกเพิ่มขึ้นเมื่อเวลาผ่านไป
Data
-
ใช้ Relay เพื่อทำให้การดึงข้อมูลทั้งหมดเป็นมาตรฐานเดียวกันด้วย GraphQL
-
ด้วย Relay จึงสามารถดาวน์โหลดข้อมูลที่จำเป็นก่อนแบบขนานกันตั้งแต่ขั้นตอน request หน้า ทำให้แสดงผลบนหน้าจอได้รวดเร็ว
-
ใช้ @stream ซึ่งเป็นส่วนขยายภายในของ GraphQL เพื่อส่งข้อมูลอย่างต่อเนื่องใน query เดียวโดยไม่ต้องทำหลายรอบทริป เหมาะกับสิ่งอย่าง News Feed
-
ใช้ @defer + React Suspense เพื่อเลื่อนการโหลดข้อมูลที่ยังไม่จำเป็นในทันทีไปไว้ภายหลัง
Navigation
-
สำหรับการนำทางแบบ SPA ได้จัดทำ Route Map เพื่อลดเวลาโหลดทรัพยากรและจำนวนรอบทริประหว่างการโหลดหน้าใหม่
-
โหลดข้อมูล Route เข้าใน Route Map แบบแยกส่วนให้เร็วที่สุดเมื่อจำเป็น
-
ทำ prefetch ทรัพยากรล่วงหน้าให้เร็วที่สุดเท่าที่จะทำได้ (prefetch ตอน hover, ดึงโค้ดและข้อมูลตอน mouse down, แล้วเมื่อเกิดการคลิกจึงเปลี่ยนสถานะของ React)
-
แทนที่จะแสดงหน้าจอว่างระหว่างการนำทาง ใช้ React Suspense transition เพื่อคง Route เดิมไว้ก่อนจนกว่าจะดึง Route ใหม่มาได้
-
ใช้ EntryPoints (ไฟล์ขนาดเล็กที่ห่อจุดแยกโค้ดและ data query ไว้) เพื่อทำให้การดาวน์โหลดโค้ดและข้อมูลเป็นแบบขนาน
2 ความคิดเห็น
สิ่งที่ได้รู้จาก CSS ของดีไซน์ใหม่ของ Facebook https://th.news.hada.io/topic?id=1819
แนะนำให้อ่านบทความนี้ประกอบไปด้วย
Relay - ไคลเอนต์ GraphQL สำหรับ React ที่พร้อมใช้งานในโปรดักชัน https://relay.dev/