Pull to refresh

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 не работал. Но здорово, что там эта проблема учтена.

Sign up to leave a comment.