Что такое GraphQL?
GraphQL - это язык запросов для API-интерфейсов и среда, в которой они выполняются. С помощью GraphQL можно получить данные из API и передать их в приложение (от сервера к клиенту). У них есть официальная документация, которая расположена по адреу https://graphql.org/learn/.
Данный язык был придуман компанией Facebook чтобы, якобы, исправить ошибки REST API.
Facebook видели в REST API следующие недостатки, которые они решили исправить создав GraphQL:
- Избыточность данных. REST запросы всегда возвращают статичный набор данных, а это значит что REST запрос всегда будет возвращать МАКСИМАЛЬНЫЙ набор данных, который только может вернуть. GraphQL же в свою очередь дает гибкость, так как при построении запроса клиент сам выбирает набор данных, который должен будет вернуть сервер.
- Проблемы оптимизации. Исходя из пункта выше можно догадаться, что если REST всегда будет отдавать максимальное количество данных, то он постоянно будет делать лишние запросы к базе, собирать разные коллекции, приводить их к нужному виду и так далее. Например, ты хочешь узнать только имя, фамилию и email пользователя, а он тебе выдает все прочие данные, а также связанные по типу аватара, ролей, подразделение к которому он назначен, его последний заход и прочие ненужные тебе данные, на которые потратятся ресурсы сервера. В случае с GraphQL как и в пункте выше работает логика - что запросил, то и получил.
- Проблемы с расширяемостью. В REST очень много эндпоинтов и к ним еще добавляется 5 базовых HTTP методов (POST, GET, PUT, PATCH, DELETE). Разбираться с этим даже с документацией может быть проблематично и на это затрачивается дополнительное время разработчика. Плюс REST еще имеет версионность, что значит, что обращение ко всем этим эндпоинтам нужно еще и поддерживать. GraphQL же работает через один эндпоинт (как правило GraphQL) и все варианты составления запроса представлены в одной схеме.
- Проблемы с документацией. Все кто хотя бы пару раз писал OpenAPI (Swagger, Redoc и тд) документацию для REST API понимают эту боль. Ты либо расписываешь к каждому эндпоинту PHP аннотации, которые могут занимать больше места чем сам код, либо ведешь отдельный yml или json файл где все еще проблематичнее. А кто-то еще умудряется не тратить время и на это и жить вовсе без документации или же с каким нибудь docx документом. В этом варианте GraphQL является самодокументируемым. То есть пока ты пишешь схему и комментарии к ней все итак становится понятно. Ты описал схему пользователя и всех его полей. Описал в схеме метод на получение/создание пользователя и уже и метод готов и документация к нему.
- 1 запрос = 1 действие. В REST если нужно получить пользователей, то за 1 запрос можно только получить пользователей. Другого сделать не получится. В GraphQL можно в рамках одного запроса отправить несколько схем и сервер выполнит их в параллель и вернет ответ. Правда касаемо мутаций (это все что кроме получения), то тут будет аналогично REST. Распараллеливания не будет и все запросы пойдут 1 за 1. Просто это будет красивее выглядить.
Если вы понимаете, что в вашей организации присутствуют данные проблемы, то можете попробовать создать один из новых проектов на GraphQL и, возможно, будет вам счастье. Но на практике GraphQL мало кто использует так как:
- Разнообразие кодов ответов у REST. В REST используются 200-е коды ответов в случае успеха, 400-е в случае ошибок с клиентской стороны, 500-е тоже умудряются использовать, хоть это почти всегда является багом. В GraphQL по сути нету кода ответа как понятия, но так как HTTP без котов ответа не может, то мы получаем либо 200 либо 500. Из-за этого приходится самому, на клиентской стороне, обрабатывать вывод каждого ответа. Если у тебя нет доступа? А если просто пользователь не найден? А может быть ошибка валидации? Сиди и обрабатывай ответ, а не код.
- Разнообразие HTTP методов. Что Facebook считает минусом для многих может оказаться плюсом, ну или просто привычным действием. В REST имеется, к примеру, эндпоинт api/users и все CRUD операции над ним будут крутится вокруг HTTP методов. Хочешь создать пользователя - отправляешь POST api/users. Хочешь получить список - отправляешь GET api/users и так далее. В GraphQL придется на все слать схемы по типу GetUsers, CreateUsers, DeteleUsers и так далее. Разница небольшая, но тут скорее дело в удобстве.
- Такая гибкость не всем нужна. GraphQL позволяет гибко получать данные. Сейчас нужно одно - забери это. Теперь нужно другое - получай. Но в большинстве случаев оно и не нужно. Оно может пригодится, возможно, если у вас таблица, где вы выбираете отображаемые колонки, но в случае обычных страниц вы как правило все равно будете запрашивать одно и то же. При открытии статьи вы не будете спрашивать пользователя: "а показать тебе автора?" или "нужна тебе дата публикации статьи?". Вы просто получите все нужные данные и при каждом открытии статьи будете получать этот же набор данных. И для чего тогда нужна динамика?
- Одной схемы почти всегда недостаточно. Да, какую-то часть запросов можно строить прямо в схеме и не писать никакой код. Описал схему пользователя. Затем сделал Query под названием GetUser(id: Int!). Добавил прямо в схему валидацию. Добавил что вернется тип User и, казалось бы, вот тебе счастье. Не нужно писать код и сервер сам все сделает. Но в большинстве случаев логика нужных нам методов довольно сложна, чтобы это как-то можно было унифицировать. И по итогу приходится писать кастомный Resolver (он же обработчик метода), к нему может понадобится кастомный валидатор. А в резолвере нужно вручную обрабатывать те случаи когда запрашиваются разные данные и когда в контексте запроса, а когда в контексте подзапроса. И по итогу мы не ускорили, а только усложнили себе разработку. И такое будет происходить довольно часто
- Практически отсутствует работа с файлами. Представим, что нам нужен метод, который обработает переданный файл и вернет его же на скачивание. Если попробовать в Postman составить любой GraphQL запрос, то мы увидем, что слева колонка для самого запроса. Справа колонка для переменных этого запроса. В заголовках мы все также как и в REST можем передавать токены авторизации. А теперь попробуйте отправить там файл. Через тот же Postman это не выйдет так как для GraphQL это считается нестандартной ситуацией. В целом можно закрыть на это глаза и составить запрос через FormData и туда передать файл, а со стороны сервера просто знать, что в таком-то поле придет файл и обрабатывать его, но теперь нужно разобраться как его вернуть. Вернуть также файл через GraphQL не получится. Значит придется обработанный файл сохранять на сервер и уже в ответе отдавать публичную ссылку на скачивание этого файла, что с какой стороны не посмотри, выглядит неудобно.
- GraphQL - это про типизацию. Это нельзя назвать минусом, скорее плюсом, но для некоторых это может стать поводом оставаться на REST. Речь идет про то, что все вводимые и выводимые данные должны быть типизированы. Если, к примеру, основная часть вашего API занимается что-то типо "давая я скину тебе XML, а ты переведи мне его в JSON", то тут сразу мимо. В GraphQL конечно тоже есть тип ответа JSON, но это, как по мне, будет издевательством над стандартом. И в случае самого запроса также. Если этот же метод на перевод XML в JSON может принимать как файл, так и строку, то тут тоже придется изиваться.
- Сообщество не поймет. Все привыкли к REST. Большинство Web проектов и API сервисов на REST. Если вы начнете что-то интегрировать в проект, например графики, подстановку инн и адресов, интеграции с CRM системами и таблицами, то почти всегда упретесь в REST. И все к этому привыкли. Если вы сделаете API сервис на GraphQL, то большинству ваших пользователей придется выбрать аналоги на REST по разным причинам:
1. У кого-то фреймворк не поддерживает GraphQL и придется изворачиваться
2. Кто-то не знаком с GraphQL и нужно будет втягиваться и понять что это прежде чем интегрироваться с вами
3. Кто-то будет испытывать сложности при формировании запроса и переводе ответа
и так далее.
Вывод
Хоть Facebook и предполагали, что сделают язык запросов, который заменит REST по всем параметрам, но тем не менее большая часть Web проектов и API cервисов все-таки висит на REST. Кому-то не нужны все эти плюшки, кто-то просто привык, кто-то следует за сообществом. Но лично я не считаю GraphQL ни как огромным прорывом, который мог бы заменить REST ни как что-то плохое. И то и то имеет место быть просто нужно смотреть на сам проект. В проекте будет много табличных данных, гибкости выбора данных со стороны клиента, то, пожалуйста, выбирайте GraphQL и бонусом получите плюс к оптимизации и самодокументирование. Если набор данных всегда стандартный и никакой гибкости не подразумевается, то лучше не ставить себе палки в колеса и следовать за сообществом.
К примеру в том же Laravel вам придется для GraphQL установить сторонние библиотеки (как правило Lighthouse), втянутся как это все дело работает, понять как прикрутить туда свои гуарды авторизации, понять где лежат резолверы и что это вообще такое, создать нужные схемы, написать реализацию. А все привыкли, что в Laravel ты из под капота через artisan команды создаешь апи ресурс и контроллер, наполняешь его и все готово.
Так что решать каждому по своему. Кому что симпотизирует и кому что нужно в какой ситуации. GraphQL ничем не хуже и ничем не лучше REST. Это две малосвязанных сущности. Тем более когда одна - это язык запросов, а вторая - стандарт.