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 แทน
}
}
`
หวังว่าบทความนี้จะมีประโยชน์นะครับ ขอให้สนุกกับการโค้ดดิ้งครับ