Comments 5
Итого: в результате ресерча мы поняли, что нам не подходит ни Relay, ни Apollo, ни URQL.
const extractOperationName = (query) => {
const { definitions } = query;
const [def] = definitions;
const {
name: { value },
} = def;
return value;
};
Деструктивная секта =) Это же просто
const extractOperationName = (query) => query.definitions[0].name.value
<закончил ворчать>
Спасибо за комментарий! Заценил скриншот ;)
В статье старался прояснить, что затягивание любого из фреймворков влечет за собой изменения в архитектуре фронтенд приложения. А нашей целью было попробовать graphql, не меняя текущего флоу работы.
О том, как переезжали без боли с нашего решения на библиотеку или фреймворк и как отказались от redux, расскажем в следующей охэхэнной истории на Youtube.
Да, согласен, можно было избежать деструктивизации query
, предложенный в статье сниппет решил оставить, чтобы статья была близка к видеоряду. Сейчас наш снипет выглядит так:
const extractOperationName = (query: RequestConfig['query']): string => {
const def = query.definitions[0];
if (def.kind === Kind.OPERATION_DEFINITION) {
if (def.name) {
return def.name.value;
}
}
throw new HttpClientError('unknown operation name')
};
Это влечет за собой две проблемы —
overfetching
иunderfetching
. Проще говоря, либо у нас избыток данных, которые используются в данном рендере, либо их нехватка. Эту беду и призван решить GraphQL.
И ни слова про data duplication.
Напишем запрос:
query Person($id: Int!) {
person(id: $id) {
... on PersonItem {
area {
someField
}
}
}
}
Не, лучше так:
const Area = HARP({
name: Maybe( HARP( {}, String ) )
})
const Person = HARP({
name: Maybe( HARP( {}, String ) )
area: Maybe( Area )
})
const Query = HARP({
person: Maybe( Person )
area: Maybe( Area )
})
Теперь соберём запрос, подставив нужные данные:
const query = Query.build({
person: {
'=': [ ['jin'], ['john'] ],
name: {},
area: {
name: {},
},
},
area: {
'=': [[ 'msk']],
},
})
Теперь загрузим данные:
const data = await ( await fetch( query ) ).json()
При этом на сервер уйдёт такой запрос:
GET /person=jin,john[name;area[name]];area=msk
А вернётся такой ответ:
{
"_query": {
"person=jin,john[area[name]]": {
"reply": [ "person=jin", "person=john" ]
},
"area=msk": {
"reply": [ "area=msk" ]
}
},
"person": {
"jin": {
"name": "Jin",
"area": [ "area=spb" ]
},
"john": {
"name": "John",
"area": [ "area=msk" ]
}
},
"area": {
"spb": {
"name": "Saint-Petersburg"
},
"msk": {
"name": "Moscow"
}
}
}
Который без костылей ложится в кеш.
Согласен, этот недостаток стоит иметь ввиду при выборе graphql.
Фреймворки и библиотеки маскируют умеют работать с этим недостатком, как на клиенте, так и на сервере.
Можно посмотреть эту https://github.com/gajus/graphql-deduplicator реализацию. Она сопровождается статьей на медиуме https://gajus.medium.com/reducing-graphql-response-size-by-a-lot-ff5ba9dcb60
C HARP не работал. Но здорово, что там эта проблема учтена.
......
Внедрение GraphQL на фронтенде без переломов