Как стать автором
Обновить

Комментарии 21

Две картинки в этой статье занимают 68кб, а загрузка всей страницы хабра со статьёй потребовала 4700кб (или 1.9мб gzip).

Я тоже старался сэкономить и память и процессор, но этот случай не похож на серьёзный оверхэд, 42кб с учётом токенайзера, парсера, лексера, рабочего основного функционала +всё это явно покрыто тестами и оттестировано со всех сторон. GraphQL — это сейчас сердце многих проектов и очень хорошо что оно стабильно.

Нет, аполло-клиент - это не только система состояний, но и довольно хитрая система кеширования.

1.. Не будет лишних повторных запросов на сервер, если параметры не менялись.

2.. Многоуровневый ответ разбивается в кеш на отдельные объекты, и получив новые данные объектов от сервера, вы получитет апдейт их данных во всех результатах запросов в кеше.

3.. Есть возможность указать перечень объектов-документв в параметрах запроса, чтобы по результату выполнения перезапросились все запросы с такими документами запросов.

4.. Методы типы client.resetStore() и подобные, чтобы сбросить кеш и перезапросить все активные запросы.

5.. Правила замены или "склеивания" результатов.

6.. Маппинг типов данных. К примеру, указать жиэсовский Date для графкульного DateTime. Ведь с сервера в ответах у нас всегда только строки/числа в скалярах прилетают, там объекты сложные отсутствуют. А в тайпскрипте у нас прописано, что такое-то поле - это Объект, а у нас тут строка прилетает... В аполло есть возможность задать так, что уже из кеша объект будет с типизированными полями, а не просто строки.

И еще много-много всего. Просто за год вы не успели проработать достаточно кейсов, чтобы это осознать.
Я ни в коем случае не смеюсь над вами, но со временем вы узнаете больше.

Что-то мне подсказывает - лень не позволила автору внимательно изучить документацию apollo client. Иначе рядом не упомянались бы всякие redux'ы и т.п. Apollo client большая бибилиотека с кучей фишек и особенностей, что бы грамотно использовать нужно потратить на много больше времени в сравненнии с тем же редаксом. Мой личный опыт говорит, что не зря.

Интересно мнение коллег, не кажется ли вам, что Front End, в руки которого попал GraphQL (с query и mutation), по-сути становится fullstack'ом? Бэк особо не нужен, ну, сущности для GQL подготовить, и остальные мелочи. Основная логика работы с БД в этом случае (в отличие от REST) становится полной ответственностью фронтов.

отчасти согласен, немного смещается стэк, и большАя часть логики приложения переезжает на клиента, а gql становится своеобразной "базой данных"

Скажу от себя, как fullstack, который в свое время довольно много работал с базами данных: ваша мысль совершенно верная. Более того, сейчас вполне есть средства для организации работы с базами данных и настройки всего так, что фронт будет очень сильно связан с бэком вплоть до типизации запросов к БД. Вот для примера моя сборка: https://github.com/prisma-cms/nextjs-nexus

1. prisma-2 обеспечивает взаимодействие с БД (MySql, Postrges и другие), в том числе управление структурой базы, миграции и т.п. При этом генерируется API вместе с типизацией. То есть прописал схему, выполнил деплой, получил типизированное бэк-АПИ.

2. nexus-js + nexus-plugin-prisma дают механизмы написания GraphQL-API в связке с типами призмы, то есть с полным соответствием бэк-АПИ.

3. Упомянутый в статье codegen позволяет стянуть Graphql-API-схему, найти все граф-запросы во фронте, провалидировать их на соответствие этой схеме и сгенерировать нужные методы и типы, и весь фронт в итоге так же покрыт типами.

4. react-hook-form + yup позволяют создавать типо-защищенные формы.

5. Все написано на TypeScript

И там еще некоторые мелочи, которые позволяют в итоге вести весь проект в комплексе, как будто это один сплошной фронт. И прям совсем мало есть вещей, которые можно было бы сказать "Вот это точно чистый бэк" (хотя они там конечно же есть, но все же тоже написаны на TypeScript).

Как это все работает можно посмотреть в этом видео: https://www.youtube.com/watch?v=lO29HOY3wNw

Если у вас простое круд приложение, без интеграции и функционала, то да.

Помимо БД есть, например:

  • Аутентификация/авторизация

  • Валидация

  • Интеграция с другими сервисами

  • Отправка сообщений пользователям (сис, имейл и т.п.)

  • Регулярно повторяемые события

  • Экспорт данных

И многое многое другое

К тому же, зачастую привязывать графкл к БД это плохая затея, т.к. уровень связности кода очень высок.

Никто не заставляет использовать в простейших приложениях, где нужна быстрота и лёгкость, аполло вместо обычного клиента в несколько кб типо такого https://github.com/prisma-labs/graphql-request

сколько пытался понять так и не понял зачем графкл нужен если есть рест

Представим ситуацию: нам на фронте нужно отобразить имя пользователя и список его заказов. Есть 2 способа:

  • Сделать апи для загрузки юзера по ИД, и отдельно списка заказов по ИД

  • Сделать неуниверсальный метод на бэке, который будет отдавать толстый ДТО, содержащий и имя пользователя и список заказов

Первый способ хорош тем, что на бэке не требуется лишней работы. Но дважды дергать сервер и потом всё это склеивать не очень удобно

Второй способ упрощает работу на фронте. Но тогда бэкендеры должны писать кучу скучных маппингов. А фронты ждать нового деплоя. И весь этот код нужно мейнтейнить

Графкл соответственно решает эти проблемы: фронтенд сам решает, что им нужно. И одним запросом на сервер клиент получает необходимые данные. А бэкендеры в этом даже не участвуют (только на изначальном этапе, когда проектируется схема и реализуется загрузка данных для неё)

Кроме того, графкл это ещё и удобная спецификация из коробки, где каждый может видеть, какие поля и типы существуют. И если добавить сверху typescript, получается ещё и с проверкой на компиляции.

У нас, например, фронтенд был мега-счастлив, когда мы им добавили графкл. При том что раньше мы им отдавали толстые ДТО, т.е. у них работы не сильно убавилось. Главное это независимость и контроль над тем, что они делают.

в чем разница между

"проектируется схема и реализуется загрузка данных для неё " и

"Сделать неуниверсальный метод на бэке, который будет отдавать толстый ДТО, содержащий и имя пользователя и список заказов" ?

сместился уровень схемы чуть дальше в бек, теперь мы понимаем что нам нужно не из названия метода API через REST а из схемы GraphQL дальше то все равно ничего не меняется. Кто-то должен понять что фронту надо, дальше должен кто-то написать SQL запрос для получения этих данных в базу данных.

Если рассматривать гибкую, но непроизводительную реализацию графкл:

Для загрузки пользователей с заказами делаются 2 независимых загрузчика:

  • Загрузка пользователей (по ИД например)

  • Загрузка заказов, зная пользователей

Когда клиент запрашивает данные, !графкл движок сам! может вызывать или не вызывать эти загрузчики, в зависимости от того что запросил клиент. Например, если запросили только пользователей, то заказы никак не загружаются.

А в РЕСТе пришлось бы реализовывать новый метод.

А теперь представьте, что в некоторых случаях нужна ещё информация по продуктам. Тогда для графкл нужно добавить один загрузчик (продукта по заказам) и всё, дальше умный движок сам будет использовать то что нужно.

А для реста придется добавлять продукты в каждый эндпоинт отдельно.

Как я отметил выше, это может быть неоптимально, т.к. делается несколько запросов в БД (по одному запросу на каждый уровень). Но это не сильно критично в плане производительности и в больших приложениях писать кастомный СКЛ на каждый эндпоинт такое себе удовольствие. Если это так хочется, то есть трансформеры из графкл в скл. Тогда у вас будет ещё меньше работы.

НО у этого обсуждения производительности есть один большой нюанс: графкл это ни разу ни про БД, а про запросы к данным. В общем случае у вас для заказов и продуктов могут быть свои сервисы. БД может быть ноуСКЛ. А какие то данные могут вычисляться на лету. И тогда у вас будет выбор: для РЕСТа каждый раз это загружать вручную и склеивать. Или для графкл написать пару загрузчиков данных (по одному на каждый тип), которые покроют 10-20 разных сценариев.

ПС извините если криво объяснил. Для меня графкл тоже был непонятно зачем, пока не появилась необходимость склеивать данные из разных сервисов.

да я понял, просто Вы говорите, для GraphQL пару обработчиков, типа ну тут ничего трудного. а для REST это новый эндпоинт, как будто это прям проблема проблем.

ну ок. как Вам такой вариант?

site.ru/api/getUser?id=123&orders=true

в этом же endpoint'е мы смотрим, нужен ли клиенту список заказов? или нет, если нужен добавляем его в результирующий JSON.

Я к тому что, не то же ли это самое? только в профиль. поменяли описание запроса, все остальное то никуда не девается. тот же запрос только описанный в схеме.

а для REST это новый эндпоинт, как будто это прям проблема проблем

В худшем случае это не один эндпоинт, а набор всевозможных комбинаций под разные экраны на фронте.

У нас количество эндпоинтов, для среднего проекта, около сотни. И большинство из них очень похожи, но отличаются парой лишних связанных полей. Соответственно этот зоопарк постепенно заменим на графкл. Где будет максимум 20 загрузчиков

И добавить не проблема, но меинтейнить (если во внутренних сущностях меняются поля), становится гораздо сложнее

site.ru/api/getUser?id=123&orders=true

Да, это сильно упрощенный вариант графкл, и если этого достаточно, то почему бы и нет. И если таких эндпоинтов несколько штук, то не проблема склеивать всё вручную в каждом эндпоинте.

Но графкл сверху добавляет ещё:

  • возможность загружать только необходимые поля (тем самым уменьшая трафик и время загрузки)

  • шареную спецификацию из коробки

  • удобное версионирование: не обязательно вводить новую версию, можно просто добавлять новые поля когда нужно, а старые удалять, если они не используются

  • неограниченный уровень вложенности данных (orders=true&order.products=true&order.products.availability=true)

  • графкл это стандартизированный язык запросов. В то время как предложенный рест вариант это личный велосипед, который сложнее изучить для сложных случаев

В общем, ИМХО, если проект небольшой и у команды с десяток эндпоинтов, при 1-2 связанных сервисах, то скорее всего графкл не нужен и рест будет быстрее.

Если проект покрупнее и вы постоянно занимаетесь склейкой данных для фронта (или других сервисов), то вполне вероятно, что графкл облегчит вам жизнь. Зачастую, кстати, сами фронты и делают промежуточный API gateway сервис, который собирает данные с разных бэкендов и отдаёт их в виде графкл на фронт.

а зачем нужен рест если есть хттп?
и зачем нужен хттп если есть ти-си-пи?

ответ во всех случаях будет один: стандартизация и упрощение кода.

По сути когда бэк предоставляет graphql то фронт напрямую работает с логическими объектами бэка.
Благодаря универсальным методам доступа приходится намного меньше модифицировать бэк для нужд фронта. Для бэка и фронта появляется универсальный понятный метод того как будут формироваться апи, не нужны эти бесконечные обсуждения как и какой апи делать.

Ну в общем на в команде очень понравилось.

Да, по сути, в отличие от REST значительно ускоряется скорость разработки (не надо ждать бэков). Но и требование к фронтам становится другое. И сейчас в такой схеме очень ценится, если ты фронт, но у тебя есть опыт fullstack за плечами. То есть не надо учить тому, что такое БД, и как оно там вообще работает.

GraphQL так же необычен после SQL, как Vue после jQuery.
Сначала дико и непонятно.
Потом проникаешься, за полгода, а там другой мир.

Очень характерный вопрос. Многие этого не понимают. Можете размещать в любом порядке по важности
1) Самодокументируемость — Ваша документация никогда неразойдется с кодом. Сейчас для RESTAPI похожую функциональность дает Nest.js и Fastify.js. Также естьсведения что на Pythonпоявился самодокументирвоанный фреймворк
2) Фронтенд запрашивает только нужные ему поя объектов и с нужным уровнем вложенности без необзодимости согласовывать это с бэкендом
3) Фронтенд может одним запросом запросить нескоолько разнородных объектов и не вызывать 10 API ожидая их завершения
4) На самом деле можно назвать первым. Graphql — это строго регламентирвоанная система, в то время когда RESTAPI это свод банальных правил, намприер таких https://restapitutorial.ru/lessons/httpmethods.html, которые ничего не говорят о том что делат в лучаях более слродных чем todoapp

Подумайте только, мы добавили 42kB рантайма 

Если смотреть не min+gzip, а просто min - цифры будут ещё больше)
Gzip как я понимаю тоже не панацея, где-то неправильно настроено, где-то не поддерживается, плюс создаёт свой собственный оверхед.

польза этого самого кэширования нивелируется тем, что полученные данные мы так или иначе кладем в каком-нибудь виде в стейт-менеджер

Именно этого и не нужно делать. Любой стейт-менеджмент вносит элемет императивного подхода в приложение. Хотя если приложение разрабатывается на React, особенно после появления React-router v4, оно по своему подходу декларативно.


Испольщование Apollo позволяет уйти от стейт-менеджмента и сделать полностью декларативное приложение например на React. См. сообщение наа Хабре:


https://habr.com/ru/post/358292/ Apollo graphql client — разработка приложений на react.js без redux

Ну если не нравится вам использовать клиентские библиотеки то дергайте graphql просто через fetch. В чем проблема то? Мы у себя в проекте так и делаем. graphql это же просто строка посланная через HTTP POST.

Всегда удивляет то, что практически никто не говорит про одну из крутейших фишек графа - Subscriptions (подписки). "Попробовав раз - ем и сейчас!", как говорится.

Ну и вопрос, "зачем граф, когда есть рест?" отпадет сразу, как только попробуешь граф в более-менее сложной системе.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории