Фрагменты (или Fragments) в GraphQL — это блоки кода, которые позволяют вам повторно использовать определенные группы полей в запросах.
Проблема дублирования в запросах
Предположим, у нас есть схема, представляющая сущности User с полями id, name, email и profilePicture. Допустим, мы хотим получить информацию об авторах постов и комментариев. Запрос может выглядеть так:
query GetPostsAndComments {
posts {
id
title
author {
id
name
email
profilePicture
}
}
comments {
id
text
author {
id
name
email
profilePicture
}
}
}
Обратите внимание, что блок с полями пользователя (author) повторяется дважды.
Это не только выглядит громоздко, но также чревато ошибками: если нам нужно будет добавить или изменить одно из полей, придётся внести исправления во всех соответствующих местах (а попробуй ничего не забыть).
Решение: использование фрагментов
Фрагменты позволяют вынести общую часть в отдельный блок, чтобы повторно использовать её. Вот как можно переписать запрос выше с использованием фрагментов:
query GetPostsAndComments {
posts {
id
title
author {
id
name
email
profilePicture
}
}
comments {
id
text
author {
id
name
email
profilePicture
}
}
}
Красота, не так ли? Фрагмент UserFields определяет список полей, который можно снова и снова использовать в любом запросе или мутации, где фигурирует сущность User.
Синтаксис и структура фрагментов
Фрагмент объявляется с использованием ключевого слова fragment, за которым следует его имя, тип, к которому он относится, и перечень полей:
fragment ИмяФрагмента on Тип {
поле1
поле2
...
}
Чтобы использовать фрагмент внутри запроса, достаточно указать его имя, предшествуя тремя точками (...):
{
entity {
...ИмяФрагмента
}
}
Возьмём другой пример. У нас есть тип Book, который описывает книги:
type Book {
id: ID!
title: String!
author: User!
publishedYear: Int
}
Если запрос касается списка книг и их авторов, мы можем объявить фрагмент для автора:
fragment AuthorFields on User {
name
email
}
query GetBooks {
books {
id
title
author {
...AuthorFields
}
publishedYear
}
}
Таким образом, мы избавляемся от необходимости перечислять поля автора (name, email) в каждом запросе.
Преимущества использования фрагментов
- Снижение дублирования кода
Чем меньше копий одного и того же кода, тем меньше вероятность ошибок и несоответствий. - Удобство поддержки
Обновление или добавление поля в одном фрагменте автоматически влияет на все запросы, где он используется. - Чистота и читаемость кода
Запросы становятся короче и проще для понимания. - Повышение согласованности
Единый фрагмент с определённой структурой полей гарантирует, что все запросы используют одни и те же данные.
Ограничения и советы по работе с фрагментами
Хотя фрагменты полезны, важно понимать их ограничения:
- Фрагменты работают только в рамках одного типа или интерфейса. Если вы хотите использовать фрагмент для разных типов, вам нужно будет определить отдельные фрагменты для каждого из них.
- Слишком много фрагментов могут усложнять понимание структуры схемы. Не стоит фрагментировать всё подряд. Оптимально использовать фрагменты для крупных и часто повторяющихся групп полей.
Практика: Создание и использование фрагментов
Шаг 1: Создадим простую GraphQL-схему
type User {
id: ID!
name: String!
email: String!
}
type Comment {
id: ID!
text: String!
author: User!
}
type Query {
comments: [Comment!]!
}
Шаг 2: Напишем фрагмент для User
fragment UserBasicInfo on User {
id
name
email
}
Шаг 3: Используем фрагмент в запросе
query GetCommentsWithAuthors {
comments {
id
text
author {
...UserBasicInfo
}
}
}
Шаг 4: Добавим новый запрос
Допустим, мы захотели добавить ещё один запрос, показывающий список пользователей. Фрагмент снова оказывается незаменимым:
query GetAllUsers {
users {
...UserBasicInfo
}
}
Полезные инструменты для работы с GraphQL-фрагментами
- GraphQL Playground
Если вы разрабатываете GraphQL API, Playground поможет вам тестировать запросы и фрагменты в удобном интерфейсе. - Apollo Client
Apollo автоматически поддерживает кэширование данных, основанное на фрагментах. Это особенно полезно для фронтенда.
Заключительная практика
Предположим, к типу User добавилось новое поле profilePicture. Нам достаточно обновить фрагмент:
fragment UserBasicInfo on User {
id
name
email
profilePicture
}
Теперь это обновление отразится во всех запросах, где используется фрагмент. Разве это не чудо?
Следующее занятие затронет более сложные и мощные подходы, такие как batch-загрузка (Batch Loading). Но прежде чем двигаться дальше, убедитесь, что фрагменты вам понятны и вы готовы использовать их в реальных проектах!
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ