ลด Query ซ้ำ ด้วย GraphQL Fragment

ลด Query ซ้ำ ด้วย GraphQL Fragment
21/03/19   |   3.3k

Fragment คือส่วนหนึ่งของ query ที่เราแยกออกมา เพื่อเอาไปใช้ซ้ำตามจุดต่าง ๆ ได้ครับ ถ้าใครนึกไม่ออกลองดูสถานการณ์ด้านล่างเลยครับ

ยกตัวอย่างเว็บไซต์หนึ่ง ในหน้าหลักเราอยากแสดงผลบทความสามแบบ คือ บทความยอดนิยม, บทความแนะนำ และบทความสั้น ถ้าเขียน query แบบง่าย ๆ จะได้หน้าตาประมาณนี้

query fetchBlogs {
    topBlogs: blogs(sortBy: "likeCount") {
        id
        title
        subTitle
        content
        previewImage
        category
        wordCount
        recommend
        readingTime
        likeCount
        viewCount
        updatedAt
        createdAt
        author
    }
    recommendedBlogs: blogs(recommend: true) {
        id
        title
        subTitle
        content
        previewImage
        category
        wordCount
        recommend
        readingTime
        likeCount
        viewCount
        updatedAt
        createdAt
        author
    }
    shortBlogs: blogs(maxWord: 100) {
        id
        title
        subTitle
        content
        previewImage
        category
        wordCount
        recommend
        readingTime
        likeCount
        viewCount
        updatedAt
        createdAt
        author
    }
}

จากด้านบนเห็นได้ชัดเจนว่าโค้ดซ้ำ ก่อให้เกิดปัญหาตามมาอย่างเช่น เวลาจะแก้โค้ดก็ต้องแก้หลายจุด, มีความเสี่ยงที่จะแก้ไขไม่ครบ เป็นต้น

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

Content-Length: 814

แก้ปัญหาด้วย Fragment

เราสามารถใช้ fragment ในการแยกโค้ดที่ซ้ำกัน ออกมาไว้ที่เดียวได้ แบบนี้ครับ

fragment Blog on BlogType {
    id
    title
    subTitle
    content
    previewImage
    category
    wordCount
    recommend
    readingTime
    likeCount
    viewCount
    updatedAt
    createdAt
    author
}

จากตัวอย่างข้างต้น เราสร้าง fragment ชื่อ Blog เพื่อเอาไปใช้ซ้ำกับหลาย ๆ จุดได้ โดยกำกับไว้ว่าเราสามารถใช้ได้กับ type ที่ชื่อว่า BlogType

แล้ว BlogType มาจากไหน ? ก็มาจาก Object Type ที่เราสร้างเอาไว้ เช่น บนเซิร์ฟเวอร์นั่นเอง

type BlogType {
    id
    title
    subTitle
    content
    previewImage
    category
    wordCount
    recommend
    readingTime
    likeCount
    viewCount
    updatedAt
    createdAt
    author
}

ตอนใช้งานก็จัดการ spread เจ้า fragment เข้าได้ไปเลย ลองดูโค้ดเต็ม ๆ ด้านล่างเลยครับ

query fetchBlogs {
    topBlogs: blogs(sortBy: "likeCount") {
        ...Blog
    }
    recommendedBlogs: blogs(recommend: true) {
        ...Blog
    }
    shortBlogs: blogs(maxWord: 100) {
        ...Blog
    }
}

fragment Blog on BlogType {
    id
    title
    subTitle
    content
    previewImage
    category
    wordCount
    recommend
    readingTime
    likeCount
    viewCount
    updatedAt
    createdAt
    author
}

จะเห็นว่าเราสามารถลดโค้ดซ้ำลงไปได้ และขนาดของเน็ตเวิร์ครีเควสก็จะน้อยลง

Content-Length: 465

ใช้ Fragment แทน Template literals

สำหรับชาว JavaScript ถึงแม้ว่าเราจะมีฟีจเจอร์อย่าง Template literals แต่นั่นช่วยได้แค่ลดโค้ดซ้ำ แต่ไม่ได้ช่วยลดขนาดของเน็ตเวิร์ครีเควสนะครับ เพราะสุดท้ายแล้วก็จะได้ query ที่มีขนาดเท่าเดิมอยู่ดีครับ

# วิธีนี้ไม่แนะนำ ให้ไปใช้ fragment แทนนะครับ

import gql from 'graphql-tag'

const blog = `
    id
    title
    subTitle
    content
    previewImage
    category
    wordCount
    recommend
    readingTime
    likeCount
    viewCount
    updatedAt
    createdAt
    author
`

const query = gql`
    query fetchBlogs {
        topBlogs: blogs(sortBy: "likeCount") {
            ${blog} // ไปใช้ fragment แทน
        }
        recommendedBlogs: blogs(recommend: true) {
            ${blog} // ไปใช้ fragment แทน
        }
        shortBlogs: blogs(maxWord: 100) {
            ${blog} // ไปใช้ fragment แทน
        }
    }
`

หวังว่าบทความนี้จะมีประโยชน์นะครับ ขอให้สนุกกับการโค้ดดิ้งครับ

tags : graphql fragment



ติดตามข่าวสารและเรื่องราวดีๆ ทาง Email