GraphQL Fragments: ให้แต่ละ Component เป็นเจ้าของข้อมูลของตัวเอง

ในตอนแรก GraphQL query ดูสะอาดตามาก การส่ง request เพียงครั้งเดียวก็ได้ข้อมูลทั้งหมด แต่เมื่อแอปของคุณเติบโตขึ้น...

Query ของหน้าเพจเริ่มรวบรวม field ต่างๆ สำหรับ child component หลายตัว คุณเพิ่ม field สำหรับ component ใหม่ แต่หกสัปดาห์ต่อมาคุณลบ component นั้นทิ้ง แล้วคุณก็ลืมลบ field ออกจาก query หลัก ผลที่ตามมาคือไม่มีใครรู้ว่ามันปลอดภัยที่จะลบ field นั้นทิ้งหรือไม่ และ query ก็จะใหญ่ขึ้นเรื่อยๆ อย่างไม่มีที่สิ้นสุด

Fragments ช่วยแก้ปัญหานี้ได้ ทีมส่วนใหญ่มักใช้มันเป็นเพียงวิธีในการ copy และ paste field ซึ่งเป็นวิธีที่ผิด Fragments ควรถูกใช้เป็นโมเดลสำหรับการเป็นเจ้าของข้อมูลของ component (component ownership)

Fragment คือกลุ่มของ field ที่มีการตั้งชื่อไว้สำหรับ type ที่เฉพาะเจาะจง

ตัวอย่าง: fragment UserBadge on User { id name avatarUrl }

คุณสามารถ spread fragment นี้เข้าไปใน query ใดก็ได้ที่ต้องการข้อมูล User

คุณค่าที่แท้จริงอยู่ที่ "ที่ที่คุณบันทึก fragment" อย่าเก็บพวกมันไว้ในไฟล์ส่วนกลาง (shared file) แต่ให้เก็บ fragment ไว้ในไฟล์เดียวกับ component ที่ใช้งานมัน

สิ่งนี้เรียกว่า co-location โดยที่แต่ละ component จะประกาศความต้องการข้อมูลของตัวเอง

เมื่อ component ต้องการ field ใหม่ คุณก็แค่เพิ่มมันเข้าไปใน fragment ของ component นั้น แล้ว parent query จะอัปเดตโดยอัตโนมัติ เมื่อคุณลบ component ทิ้ง คุณก็ลบ fragment ของมันไปด้วย ทำให้ query เล็กลง โดยที่ parent component ไม่จำเป็นต้องรับรู้ถึง field ภายในของ child component เลย

Data masking ช่วยให้สิ่งนี้ดียิ่งขึ้นไปอีก เมื่อเปิดใช้งาน masking component จะเห็นเฉพาะ field ที่มันร้องขอผ่าน fragment ของตัวเองเท่านั้น แม้ว่า server จะส่งข้อมูลส่วนเกินมา แต่ component ของคุณก็ไม่สามารถเข้าถึงข้อมูลนั้นได้

สิ่งนี้สร้างข้อตกลง (contract) ที่เข้มงวด

  • TypeScript จะรู้ได้อย่างแม่นยำว่าแต่ละ component มีข้อมูลอะไรบ้าง
  • หากคุณลบ field ออกจาก fragment ตัว TypeScript จะแสดง error ทุกจุดที่เกี่ยวข้อง
  • การ Refactoring จะกลายเป็นการตรวจสอบ type ที่เรียบง่าย แทนที่จะต้องไล่ค้นหาไปทั่วทั้ง codebase

ควรใช้ fragments เมื่อ:

  • มีหลาย component ที่ใช้ type เดียวกัน เช่น User หรือ Product
  • Query ของหน้าเพจยาวเกินไป
  • คุณเผลอทิ้ง field ที่ไม่ได้ใช้งานแล้วไว้ใน query
  • คุณต้องการความปลอดภัยของข้อมูลด้วย TypeScript

เริ่มจากจุดเล็กๆ ลองหา component สักตัวที่รับข้อมูลมาจาก parent query แล้วย้าย field ของมันเข้าไปอยู่ใน fragment จากนั้นให้นำ fragment นั้นไปไว้ในไฟล์ของ component นั้นเลย

Fragments ช่วยให้มั่นใจว่าการดึงข้อมูล (data fetching) ของคุณจะสอดคล้องกับ UI เสมอเมื่อแอปของคุณเติบโตขึ้น

Source: https://dev.to/grimicorn/graphql-fragments-let-each-component-own-its-data-5359