[Разработка веб-сайтов, API] Как мы использовали GraphQL в разработке на примере интернет-каталога
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
В этой статье мы делимся опытом реального применения GraphQL при создании интернет-каталога. Рассказываем о том, какие достоинства и недостатки этого языка запросов мы нашли при использовании стека GraphQL + Apollo Client, Next JS (SSR) + TypeScript.
Дисклеймер: мы не описываем подробно «магическую суть» и историю возникновения инструмента (об этом уже рассказано немало). Надеемся, что тем, кто уже знаком с GraphQL, окажется полезен наш практический опыт.
Недавно мы приняли участие в создании интернет-каталога светотехнического оборудования. Для создания рекламных страниц администраторы сайта могли воспользоваться конструктором: выбрать нужные блоки (например, баннеры или списки), заполнить их данными, определить порядок отображения и другие настройки. При этом приложение рендерило компоненты, заранее сверстанные для каждого типа блоков.
В каждой категории интернет-каталога выводились карточки различных товарных групп, и при наведении на карточку отображался список свойств для вложенных товаров.
Нам нужно было выводить свойства товаров в древовидной структуре и обеспечить достаточно высокую скорость обработки запросов.
Мы выбрали следующий порядок работы с запросами:
- Запросить все товарные группы для определенной категории (как правило, около 50 групп).
- Запросить список товаров для каждой группы.
- Запросить список свойств для каждого товара.
Поскольку мы разрабатывали приложение на базе GraphQL, мы были готовы к тому, что часть данных будет иметь достаточно сложную вложенную структуру. Хотя для backend-разработки ветвление этой структуры было логичным, на фронте нужно было писать некоторую «лишнюю» логику, чтобы обработать данные и вывести их в компонент, согласно дизайну.
Из-за особенностей конструктора GraphQL мы приняли решение осуществлять сбор свойств и уникальных значений не на бэке, а на фронте, а затем рендерить их в определенном порядке. Однако, обработка запроса происходила слишком медленно – до 20 секунд, что нас, конечно, не устраивало.
По этой причине мы стали делить каждый запрос на мелкие подзапросы и загружать данные порционно. В результате приложение заметно выиграло в скорости – запросы занимали не более 2 секунд. Хотя количество запросов стало больше, нагрузка на систему снизилась, исчезла необходимость подгружать неиспользуемые данные.
Далее расскажем подробнее непосредственно о работе с GraphQL.
Особенности работы с GraphQL
Согласно требованиям к продукту, нам следовало использовать язык запросов GraphQL, разработанный Facebook. По этой причине мы не стали пускаться в бесконечные споры, что лучше, GraphQL или REST – вместо этого мы решили использовать нужную технологию наиболее эффективным способом, учитывая все ее сильные стороны.
Мы учитывали, что GraphQL был разработан для упрощения разработки и поддержки API, прежде всего, за счет наличия единственной конечной точки.
GET /news
GET /posts
POST /news
POST /post
GraphQL имеет единственную конечную точку. Это означает, что для получения данных из двух разных ресурсов нам не нужно делать два отдельных запроса. GraphQL объединяет все запросы и мутации в одной конечной точке и делает её доступной для обращения, а также позволяет уйти от версионирования, свойственного REST API.
GraphQL обеспечивает возможность оптимизировать производительность и получать именно те данные, которые необходимы в данный момент, с помощью особого синтаксиса запросов: требуемые поля следует перечислить в запросе.
const FETCH_USER_DATA = gql`
query FetchUserData {
user {
firstName
lastName
date
}
}
`;
GraphQL использует строго типизированные сущности и схему типов, что, в свою очередь, удобно в связке с TypeScript и генерацией типов на фронте.
Многие из перечисленных особенностей, безусловно, можно реализовать и на REST API, однако, GraphQL предоставляет их «из коробки».
Для взаимодействия клиента с GraphQL мы выбрали наиболее популярное решение с хорошей документацией – библиотеку Apollo Client, которая позволяет получать, кэшировать и модифицировать данные приложения. Apollo Client дает возможность использовать хуки для запросов и мутаций и инструменты для удобного отслеживания состояния загрузки/ошибки.
Также на фронте мы использовали фреймворк NextJS, выбранный с учетом следующих факторов: пре-рендеринг (NextJS предоставляет очень простой механизм реализации статической генерации и SSR “из коробки”), поддержка всех существующих css-in-js решений, динамический роутинг, поддержка статических файлов (например, изображений) в React-компонентах.
Наконец, когда технологии выбраны, перейдем к разработке. На первый взгляд, все смотрится неплохо: современные библиотеки, хорошая документация, много различных кейсов использования. Каждая из технологий по отдельности призвана способствовать комфортной и быстрой разработке. Создавая бойлерплейт, без которого было не обойтись, и верстая UI-компоненты, мы постепенно приблизились к этапу эффективного взаимодействия наших библиотек. Здесь началось все самое интересное.
Заглянув поглубже в механизмы NextJS, мы видим, что он использует две формы пререндера: статическую генерацию и SSR. Обе эти стратегии реализуются с помощью специальных функций предзагрузки данных:
`getInitialProps` (SSR) – при первой загрузке запускается на сервере, запрашивает данные и затем передает их в компонент в качестве props.
function Component ({data}) {
...
}
Component.getInitialProps = async (ctx) => {
const res = await fetch('https://...')
const json = await res.json()
return { data: json.data }
}
`getStaticProps` (Static Generation) – запускается на build-этапе. NextJS производит пре-рендер страницы с использованием props, вернувшихся из данной функции.
export async function getStaticProps(context) {
return {
props: {}, // передает данные в компонент в качестве props
}
}
`getServerSideProps` (Server Side Rendering) – NextJS производит пре-рендер страницы при каждом запросе, используя данные, вернувшиеся из данной функции в качестве props.
export async function getServerSideProps(context) {
return {
props: {}, // передает данные в компонент в качестве props
}
}
Таким образом, все перечисленные функции объявляются вне компонента, получают некоторые данные и передают в компонент. Отсюда вытекает одна из проблем взаимодействия с Apollo Client. Библиотека предоставляет такие механизмы запросов, как хук `useQuery` и компонент `Query`, при этом ни один из предложенных способов невозможно использовать вне компонента. С учетом этого в нашем проекте мы решили использовать библиотеку next-with-apollo и в итоге остались довольны результатом.
Еще одна известная проблема Apollo Client, с которой нам также довелось столкнуться – это возможность появления бесконечного цикла запросов из хука `useQuery`. Суть проблемы заключается в том, что Apollo Client продолжает бесконечно отправлять запросы до тех пор, пока успешно не получит данные. Это может привести к ситуации, когда компонент “повиснет” в бесконечном запросе, если сервер по какой-либо причине не может вернуть данные.
В нашем случае одной из причин служило изменение схемы на бэке. Apollo самостоятельно генерирует типы, поэтому при написании запросов на фронте мы должны были следовать сгенерированным типам, чтобы избежать ошибок. Например, у нас был рабочий запрос, без каких-либо проблем с типами. Однако, при изменении схемы на бэке одновременно менялись типы, из-за чего рабочий запрос мог перестать функционировать. Учитывая это, оптимально сразу внедрять логирование и четкую систему обработки ошибок, чтобы сэкономить нервы и время команды.
Достаточно полезным, на наш взгляд, оказалось то, что в graphql-запросах можно точно указать, какие данные следует получать. При отправке большого количества запросов это позволяет избежать обработки излишних данных. В свою очередь, это может существенно повлиять на производительность, когда растет количество данных.
Стоит отметить, что одним из преимуществ GraphQL считается удобство разработки и поддержки API, но это свойство более значимо для backend-разработки и, по нашим наблюдениям, не оказывает значительного влияния на фронт. Из-за генерации типов при каждом изменении схемы на бэке мы переписывали все затронутые запросы. Бэку также приходилось дорабатывать схему, если нам на фронте нужно было получить что-то, что еще не было реализовано. При этом генерация типов при использовании TypeScript позволяла отлавливать многие ошибки еще на стадии написания кода.
Подводя итоги
По нашим наблюдениям, GraphQL достаточно широко востребован в различных типах IT-решений и обеспечивает определенные преимущества для команды разработки. Суммируем основные особенности GraphQL, с которыми мы встретились при разработке проекта:
- Генерация типов. Генерация типов graphql позволяет экономить время при написании запросов, идеально подходит для использования TypeScript и помогает отлавливать неприятные ошибки на раннем этапе разработки.
- Быстрота обновления данных. С GraphQL в нашем случае можно было быстро обновить данные в фронтэнд-части приложения. У разработчиков была возможность вносить изменения на стороне клиента, не вмешиваясь в работу сервера (при наличии необходимых полей на бекэнде, конечно). При этом у graphql есть так называемая «песочница» для запросов, в которой можно протестировать запросы с разными параметрами
- Обработка только нужных данных. В graphql-запросах можно точно указать, какие данные следует получать. При отправке большого количества запросов это позволяет избежать обработки излишних данных.
- Масштабируемость. GraphQL делает удобнее работу с масштабируемыми системами, поскольку облегчает объединение данных из нескольких сервисов в один.
Спасибо за внимание! Надеемся, что этот пример был вам полезен.
===========
Источник:
habr.com
===========
Похожие новости:
- [Управление разработкой, Разработка для интернета вещей, Производство и разработка электроники, Дизайн, Электроника для начинающих] Кухня промдизайна #1: почти идеальная разработка корпуса модуля IRRIOT
- [Виртуализация, Облачные сервисы, Производство и разработка электроники] Привет, Habr! Давай знакомиться — мы Getmobit и мы здесь новенькие
- [JavaScript, Node.JS] Nested Sets для Javascript
- [IT-эмиграция, Изучение языков, Программирование] Как российский разработчик уехал в Австралию. История Юрия Галустова
- [Ненормальное программирование, Киберпанк, Биотехнологии, Биографии гиков] Эта музыка будет вечной или генетическое программирование
- [JavaScript, Разработка веб-сайтов] Основы настройки Webpack
- [JavaScript, Программирование, Разработка веб-сайтов] JavaScript: парочка задач на знание рекурсии
- [Разработка мобильных приложений, Изучение языков] Когда имеет смысл писать кроссплатформенные приложения: появление и исчезновение React Native в Lingualeo
- [Читальный зал, Робототехника, Научно-популярное] Любовь, смерть и роботы: рассматриваем рассказы Азимова глазами разработчика
- [Производство и разработка электроники, Гаджеты, Умный дом] Первая сотня российских электронных устройств
Теги для поиска: #_razrabotka_vebsajtov (Разработка веб-сайтов), #_api, #_graphql, #_razrabotka (разработка), #_api, #_programmirovanie (программирование), #_javascript, #_react, #_blog_kompanii_simbirsoft (
Блог компании SimbirSoft
), #_razrabotka_vebsajtov (
Разработка веб-сайтов
), #_api
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 12:44
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
В этой статье мы делимся опытом реального применения GraphQL при создании интернет-каталога. Рассказываем о том, какие достоинства и недостатки этого языка запросов мы нашли при использовании стека GraphQL + Apollo Client, Next JS (SSR) + TypeScript. Дисклеймер: мы не описываем подробно «магическую суть» и историю возникновения инструмента (об этом уже рассказано немало). Надеемся, что тем, кто уже знаком с GraphQL, окажется полезен наш практический опыт. Недавно мы приняли участие в создании интернет-каталога светотехнического оборудования. Для создания рекламных страниц администраторы сайта могли воспользоваться конструктором: выбрать нужные блоки (например, баннеры или списки), заполнить их данными, определить порядок отображения и другие настройки. При этом приложение рендерило компоненты, заранее сверстанные для каждого типа блоков. В каждой категории интернет-каталога выводились карточки различных товарных групп, и при наведении на карточку отображался список свойств для вложенных товаров. Нам нужно было выводить свойства товаров в древовидной структуре и обеспечить достаточно высокую скорость обработки запросов. Мы выбрали следующий порядок работы с запросами:
Поскольку мы разрабатывали приложение на базе GraphQL, мы были готовы к тому, что часть данных будет иметь достаточно сложную вложенную структуру. Хотя для backend-разработки ветвление этой структуры было логичным, на фронте нужно было писать некоторую «лишнюю» логику, чтобы обработать данные и вывести их в компонент, согласно дизайну. Из-за особенностей конструктора GraphQL мы приняли решение осуществлять сбор свойств и уникальных значений не на бэке, а на фронте, а затем рендерить их в определенном порядке. Однако, обработка запроса происходила слишком медленно – до 20 секунд, что нас, конечно, не устраивало. По этой причине мы стали делить каждый запрос на мелкие подзапросы и загружать данные порционно. В результате приложение заметно выиграло в скорости – запросы занимали не более 2 секунд. Хотя количество запросов стало больше, нагрузка на систему снизилась, исчезла необходимость подгружать неиспользуемые данные. Далее расскажем подробнее непосредственно о работе с GraphQL. Особенности работы с GraphQL Согласно требованиям к продукту, нам следовало использовать язык запросов GraphQL, разработанный Facebook. По этой причине мы не стали пускаться в бесконечные споры, что лучше, GraphQL или REST – вместо этого мы решили использовать нужную технологию наиболее эффективным способом, учитывая все ее сильные стороны. Мы учитывали, что GraphQL был разработан для упрощения разработки и поддержки API, прежде всего, за счет наличия единственной конечной точки. GET /news
GET /posts POST /news POST /post GraphQL имеет единственную конечную точку. Это означает, что для получения данных из двух разных ресурсов нам не нужно делать два отдельных запроса. GraphQL объединяет все запросы и мутации в одной конечной точке и делает её доступной для обращения, а также позволяет уйти от версионирования, свойственного REST API. GraphQL обеспечивает возможность оптимизировать производительность и получать именно те данные, которые необходимы в данный момент, с помощью особого синтаксиса запросов: требуемые поля следует перечислить в запросе. const FETCH_USER_DATA = gql`
query FetchUserData { user { firstName lastName date } } `; GraphQL использует строго типизированные сущности и схему типов, что, в свою очередь, удобно в связке с TypeScript и генерацией типов на фронте. Многие из перечисленных особенностей, безусловно, можно реализовать и на REST API, однако, GraphQL предоставляет их «из коробки». Для взаимодействия клиента с GraphQL мы выбрали наиболее популярное решение с хорошей документацией – библиотеку Apollo Client, которая позволяет получать, кэшировать и модифицировать данные приложения. Apollo Client дает возможность использовать хуки для запросов и мутаций и инструменты для удобного отслеживания состояния загрузки/ошибки. Также на фронте мы использовали фреймворк NextJS, выбранный с учетом следующих факторов: пре-рендеринг (NextJS предоставляет очень простой механизм реализации статической генерации и SSR “из коробки”), поддержка всех существующих css-in-js решений, динамический роутинг, поддержка статических файлов (например, изображений) в React-компонентах. Наконец, когда технологии выбраны, перейдем к разработке. На первый взгляд, все смотрится неплохо: современные библиотеки, хорошая документация, много различных кейсов использования. Каждая из технологий по отдельности призвана способствовать комфортной и быстрой разработке. Создавая бойлерплейт, без которого было не обойтись, и верстая UI-компоненты, мы постепенно приблизились к этапу эффективного взаимодействия наших библиотек. Здесь началось все самое интересное. Заглянув поглубже в механизмы NextJS, мы видим, что он использует две формы пререндера: статическую генерацию и SSR. Обе эти стратегии реализуются с помощью специальных функций предзагрузки данных: `getInitialProps` (SSR) – при первой загрузке запускается на сервере, запрашивает данные и затем передает их в компонент в качестве props. function Component ({data}) {
... } Component.getInitialProps = async (ctx) => { const res = await fetch('https://...') const json = await res.json() return { data: json.data } } `getStaticProps` (Static Generation) – запускается на build-этапе. NextJS производит пре-рендер страницы с использованием props, вернувшихся из данной функции. export async function getStaticProps(context) {
return { props: {}, // передает данные в компонент в качестве props } } `getServerSideProps` (Server Side Rendering) – NextJS производит пре-рендер страницы при каждом запросе, используя данные, вернувшиеся из данной функции в качестве props. export async function getServerSideProps(context) {
return { props: {}, // передает данные в компонент в качестве props } } Таким образом, все перечисленные функции объявляются вне компонента, получают некоторые данные и передают в компонент. Отсюда вытекает одна из проблем взаимодействия с Apollo Client. Библиотека предоставляет такие механизмы запросов, как хук `useQuery` и компонент `Query`, при этом ни один из предложенных способов невозможно использовать вне компонента. С учетом этого в нашем проекте мы решили использовать библиотеку next-with-apollo и в итоге остались довольны результатом. Еще одна известная проблема Apollo Client, с которой нам также довелось столкнуться – это возможность появления бесконечного цикла запросов из хука `useQuery`. Суть проблемы заключается в том, что Apollo Client продолжает бесконечно отправлять запросы до тех пор, пока успешно не получит данные. Это может привести к ситуации, когда компонент “повиснет” в бесконечном запросе, если сервер по какой-либо причине не может вернуть данные. В нашем случае одной из причин служило изменение схемы на бэке. Apollo самостоятельно генерирует типы, поэтому при написании запросов на фронте мы должны были следовать сгенерированным типам, чтобы избежать ошибок. Например, у нас был рабочий запрос, без каких-либо проблем с типами. Однако, при изменении схемы на бэке одновременно менялись типы, из-за чего рабочий запрос мог перестать функционировать. Учитывая это, оптимально сразу внедрять логирование и четкую систему обработки ошибок, чтобы сэкономить нервы и время команды. Достаточно полезным, на наш взгляд, оказалось то, что в graphql-запросах можно точно указать, какие данные следует получать. При отправке большого количества запросов это позволяет избежать обработки излишних данных. В свою очередь, это может существенно повлиять на производительность, когда растет количество данных. Стоит отметить, что одним из преимуществ GraphQL считается удобство разработки и поддержки API, но это свойство более значимо для backend-разработки и, по нашим наблюдениям, не оказывает значительного влияния на фронт. Из-за генерации типов при каждом изменении схемы на бэке мы переписывали все затронутые запросы. Бэку также приходилось дорабатывать схему, если нам на фронте нужно было получить что-то, что еще не было реализовано. При этом генерация типов при использовании TypeScript позволяла отлавливать многие ошибки еще на стадии написания кода. Подводя итоги По нашим наблюдениям, GraphQL достаточно широко востребован в различных типах IT-решений и обеспечивает определенные преимущества для команды разработки. Суммируем основные особенности GraphQL, с которыми мы встретились при разработке проекта:
Спасибо за внимание! Надеемся, что этот пример был вам полезен. =========== Источник: habr.com =========== Похожие новости:
Блог компании SimbirSoft ), #_razrabotka_vebsajtov ( Разработка веб-сайтов ), #_api |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 12:44
Часовой пояс: UTC + 5