Как устроены схемы и резолверы в GraphQL
Что проверяют
Понимаете ли вы, как запрос превращается в ответ: схема задаёт контракт, резолверы наполняют его данными. Фронтендеру важно уметь читать схему и говорить с бэкендом о производительности. Следом обычно спрашивают про N+1 и кэш Apollo Client.
Как отвечать
Схема пишется на SDL и описывает типы:
- корневые типы:
Queryдля чтения,Mutationдля изменений,Subscriptionдля потока событий; - скаляры:
Int,Float,String,Boolean,ID, плюс свои вродеDateTime; - модификаторы:
!делает поле ненулевым,[User!]!означает список, который сам не бываетnullи не содержитnull; - составные типы:
inputдля аргументов мутаций,enum,interfaceиunion; - директивы:
@deprecatedв схеме,@includeи@skipв запросе.
Резолвер это функция на поле с четырьмя аргументами: parent (результат родительского поля), args, context (общий на запрос: пользователь, загрузчики данных) и info (AST запроса и схема). Если резолвер не задан, сервер берёт parent[fieldName]. Запрос парсится, валидируется по схеме, затем резолверы вызываются сверху вниз по дереву полей. Поля Query могут выполняться параллельно, верхние поля мутации строго по очереди.
Классика тут N+1: список из 50 постов, у каждого поле author, и резолвер автора ходит в базу 50 раз. Лечится через DataLoader, который собирает ключи за один тик и делает один батч-запрос. Создавать его нужно на каждый запрос в context, иначе кэш утечёт между пользователями.
Со стороны фронтенда стоит упомянуть кодогенерацию типов из схемы (GraphQL Code Generator) и нормализованный кэш Apollo Client, который склеивает объекты по __typename и id.
Где спотыкаются
Не знают, как всплывают ошибки. Если упал резолвер ненулевого поля, null поднимается до ближайшего поля, которое может быть null, а ответ часто приходит со статусом 200 и массивом errors.
Забывают запрашивать id у объектов. Без него Apollo не нормализует кэш, и после мутации список на экране сам не обновится.
Считают, что GraphQL сам решает проблему производительности. Без DataLoader и ограничения глубины и сложности один вложенный запрос способен положить сервер.