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

aofleejay
aofleejay
Mar 21 · 2 min read

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 แทน
}
}
`

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

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade