Создание API GraphQL с помощью Vue.js и Apollo Client

Введение GraphQL [https://graphql.org/learn/] - это графо-ориентированный язык запросов, написанный Facebook. В отличие от REST API, GraphQL представляет функции, которые делают разработку API более эффективной и согласованной с моделями баз данных. Возможности GraphQL * В отличие от REST, есть только одна конечная точка, куда будут отправляться все запросы. Таким образом, вместо того, чтобы запрашивать / users, чтобы получить список пользователей, или / user /: id, чтобы получить конкретного пользователя, конечная точка будет выглядеть как / graphql для всех запросов.

Вступление

GraphQL - это язык запросов с графической ориентацией, написанный Facebook. В отличие от REST API, GraphQL представляет функции, которые делают разработку API более эффективной и согласованной с моделями баз данных.

Возможности GraphQL

  • В отличие от REST , есть только одна конечная точка, куда будут отправляться все запросы. Таким образом, вместо того, чтобы запрашивать /users чтобы получить список пользователей, или /user/:id чтобы получить конкретного пользователя, конечная точка будет выглядеть как /graphql для всех запросов.
  • В GraphQL данные, возвращаемые из ответа, задаются указанной библиотекой запросов, и ее можно настроить для отправки только нескольких свойств данных, поэтому запросы в GraphQL имеют лучшую производительность.
  • Нет необходимости устанавливать глаголы методов в GraphQL. Такие ключевые слова, как запрос или мутация, будут определять, что будет выполнять запрос.
  • Маршруты REST API обычно обрабатываются одним обработчиком маршрута. В GraphQL у вас может быть один запрос, запускающий несколько мутаций и получение составного ответа из нескольких источников.

Запросы

Запрос представляет собой метод GraphQL , что позволяет получить данные из нашего API. Несмотря на то, что он может получать параметры для фильтрации, упорядочивания или просто поиска определенного документа, запрос не может изменять эти данные.

Мутации

Мутации - это все, что не относится к команде GET в обычных API. Обновление, создание или удаление данных из нашего API осуществляется с помощью мутаций.

Подписки

Под подпиской с использованием веб-сокетов понимается соединение между клиентом и сервером.

Сервер постоянно отслеживает изменения или запросы, связанные с конкретной подпиской, и сообщает клиенту о любых изменениях в режиме реального времени. Подписки в основном используются для виджетов / приложений в реальном времени.

Типы и входы

Чтобы наши запросы и мутации могли обрабатывать данные для запроса к базе данных, types работают так же, как модель ORM для баз данных. Установив типы , мы можем определить тип переменной, которую будут возвращать наши преобразователи.

Точно так же нам нужно установить типы ввода, которые будут получать наши распознаватели.

Например, мы определим пару types и inputs :

 type User { 
 id: ID 
 name: String! 
 age: Int! 
 address: Address 
 followers: [ID] 
 } 
 
 type Address { 
 street: String 
 city: String 
 country: String 
 } 
 
 input UserInput { 
 name: String! 
 age: Int! 
 } 
 
 type Query { 
 getAllUsers: [User] 
 } 
 
 type Mutation { 
 createUser(user: UserInput!): ID 
 } 

Свойства могут иметь настраиваемый тип, кроме примитивных, например:

  • Нить
  • Int
  • Плавать
  • Логический
  • Я БЫ

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

Кроме того, обязательный статус свойства может быть установлен с помощью ! , что означает, что свойство должно присутствовать.

Резольверы

Это действия, которые выполняются при вызове запросов и мутаций.

getAllUsers и createUser будут подключены к преобразователю, который будет выполнять фактические вычисления и запросы к базе данных.

Создание нашего проекта

В этом руководстве мы создадим проект Vue.js с использованием Vue CLI 3.0 , который загрузит проект со структурой папок, которая выглядит следующим образом:

{.ezlazyload .img-responsive}

Если вам нужна помощь в настройке проекта, вы можете посмотреть это руководство по интерфейсу командной строки.

Мы можем начать обслуживание нашего приложения с помощью команды:

 $ npm run serve 

Клиент Apollo

Apollo Client предоставляет инструмент для интерфейсной разработки, чтобы упростить запросы / мутации GraphQL. Он действует как HTTP-клиент, который подключается к GraphQL API и обеспечивает кэширование, обработку ошибок и даже возможности управления состоянием.

В этом руководстве будет использоваться Vue-Apollo , интеграция Apollo, специально разработанная для Vue.js.

Конфигурация Apollo

Чтобы начать настройку Apollo, необходимо установить несколько пакетов:

 $ npm install apollo-client apollo-link-http apollo-cache-inmemory vue-apollo graphql graphql-tag 

Внутри /graphql нашего проекта мы создадим apollo.js :

 // apollo.js 
 
 import Vue from 'vue' 
 import { ApolloClient } from 'apollo-client' 
 import { HttpLink } from 'apollo-link-http' 
 import { InMemoryCache } from 'apollo-cache-inmemory' 
 import VueApollo from 'vue-apollo' 
 
 const httpLink = new HttpLink({ 
 uri: process.env.VUE_APP_GRAPHQL_ENDPOINT 
 }) 
 
 // Create the apollo client 
 export const apolloClient = new ApolloClient({ 
 link: httpLink, 
 cache: new InMemoryCache(), 
 connectToDevTools: true 
 }) 
 
 // Install the Vue plugin 
 
 Vue.use(VueApollo) 
 
 export const apolloProvider = new VueApollo({ 
 defaultClient: apolloClient 
 }) 

HttpLink - это объект, которому требуется uri , которое относится к конечной точке GraphQL из используемого API. Пример: localhost:8081/graphql

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

Наконец, мы оборачиваем наш ApolloClient внутри VueApollo чтобы мы могли использовать его хуки внутри наших компонентов Vue.

Обработка глобальных ошибок

Есть способ глобальной обработки ошибок внутри файла конфигурации. Для этого нам нужно установить пакет npm под названием apollo-link-error , который проверяет и управляет ошибками из сети:

 // apollo.js 
 
 import Vue from 'vue' 
 import { ApolloClient } from 'apollo-client' 
 import { HttpLink } from 'apollo-link-http' 
 import { onError } from "apollo-link-error" 
 import { InMemoryCache } from 'apollo-cache-inmemory' 
 import VueApollo from 'vue-apollo' 
 
 const httpLink = new HttpLink({ 
 uri: process.env.VUE_APP_GRAPHQL_ENDPOINT 
 }) 
 
 // Error Handling 
 const errorLink = onError(({ graphQLErrors, networkError }) => { 
 if (graphQLErrors) 
 graphQLErrors.map(({ message, locations, path }) => 
 console.log( 
 `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}` 
 ) 
 ) 
 if (networkError) console.log(`[Network error]: ${networkError}`) 
 }) 
 
 // Create the apollo client 
 export const apolloClient = new ApolloClient({ 
 link: errorLink.concat(httpLink), 
 cache: new InMemoryCache(), 
 connectToDevTools: true 
 }) 
 
 // Install the Vue plugin 
 Vue.use(VueApollo) 
 
 export const apolloProvider = new VueApollo({ 
 defaultClient: apolloClient 
 }) 

После импорта onError из пакета мы можем реализовать ее как своего рода промежуточное программное обеспечение Apollo Client. Он отлавливает любые сетевые ошибки или ошибки GraphQL, давая нам возможность управлять ими глобально.

Обратный вызов вызывается с объектом с некоторыми свойствами всякий раз, когда возникает ошибка:

  • операция : операция, которая инициировала обратный вызов, потому что была обнаружена ошибка.
  • ответ : Результат операции.
  • graphQLErrors : массив ошибок из конечной точки GraphQL
  • networkError : любая ошибка во время выполнения операции или ошибка сервера.
  • вперед : следующая ссылка в цепочке.

Управление состоянием с помощью клиента Apollo

Другой альтернативой использованию Vuex с проектами Vue и при использовании клиента Apollo является использование пакета под названием apollo-link-state .

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

Кроме того, это отличный способ управления кешем для нашего приложения, что делает Apollo Client клиентом HTTP и инструментом управления состоянием / кешем.

Для получения дополнительной информации вы можете проверить официальную документацию для Apollo-link-state .

Создание запросов

Для создания запросов нам нужно настроить тег строкового типа с пакетом graphql-tag . Для поддержания аккуратного и структурированного проекта, мы создадим папку queries внутри graphql папки.

Предполагая, что сервер, получающий запрос, настроен правильно для интерпретации этого запроса, например, мы можем запустить преобразователь с именем getAllUsers :

 import gql from 'graphql-tag' 
 
 export const GET_ALL_USERS_QUERY = gql` 
 query getAllUsers { 
 getAllUsers { 
 // Fields to retrieve 
 name 
 age 
 } 
 } 
 ` 

Операцией по умолчанию в GraphQL является query , поэтому ключевое слово query

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

Использование мутаций

Подобно запросам, мы также можем использовать мутации, создав gql-string .

 import gql from 'graphql-tag' 
 
 export const CREATE_USER_MUTATION = gql` 
 mutation createUser($user: UserInput!) { 
 createUser(user: $user) 
 } 
 ` 

Наша мутация createUser UserInput и, чтобы иметь возможность использовать параметры, переданные Apollo. Сначала мы определим переменную с помощью $ called user . Затем внешняя оболочка передаст переменную createUser , как и ожидалось сервером.

Фрагменты

Чтобы наши gql-type аккуратными и удобочитаемыми, мы можем использовать фрагменты для повторного использования логики запросов.

 fragment UserFragment on User { 
 name: String! 
 age: Int! 
 } 
 
 query getAllUsers { 
 getAllUsers { 
 ...UserFragment 
 } 
 } 

Использование GraphQL в компонентах Vue

Внутри main.js , чтобы настроить Apollo Client, нам нужно импортировать и присоединить клиента к нашему экземпляру.

 // main.js 
 import Vue from 'vue' 
 import { apolloProvider } from './graphql/apollo' 
 
 Vue.config.productionTip = false 
 
 /* eslint-disable no-new */ 
 new Vue({ 
 el: '#app', 
 apolloProvider, 
 render: h => h(App) 
 }) 

Поскольку мы добавили наш ApolloProvider в экземпляр Vue, мы можем получить доступ к клиенту через ключевое слово $apollo

 // GraphQLTest.vue 
 <template> 
 <div class="graphql-test"> 
 <h3 v-if="loading">Loading...</h3> 
 <h4 v-if="!loading">{{ getAllUsers }}</h4> 
 </div> 
 </template> 
 
 <script> 
 import { GET_ALL_USERS_QUERY } from '../graphl/queries/userQueries' 
 export default { 
 name: 'GraphQLTest', 
 data () { 
 return { 
 users: [] 
 } 
 }, 
 async mounted () { 
 this.loading = true 
 this.users = await this.$apollo.query({ query: GET_ALL_USERS_QUERY }) 
 this.loading = false 
 } 
 } 
 </script> 

Если мы хотим создать пользователя, мы можем использовать mutation :

 // GraphQLTest.vue 
 <template> 
 <div class="graphql-test"> 
 <input v-model="user.name" type="text" placeholder="Name" /> 
 <input v-model="user.age" placeholder="Age" /> 
 <button @click="createUser">Create User</button> 
 </div> 
 </template> 
 
 <script> 
 import { CREATE_USER_MUTATION } from '../graphl/queries/userQueries' 
 export default { 
 name: 'GraphQLTest', 
 data() { 
 return { 
 user: { 
 name: null, 
 age: null 
 } 
 } 
 }, 
 methods: { 
 async createUser () { 
 const userCreated = await this.$apollo.mutate({ 
 mutation: CREATE_USER_MUTATION, 
 variables: { 
 user: this.user // this should be the same name as the one the server is expecting 
 } 
 }) 
 // We log the created user ID 
 console.log(userCreated.data.createUser) 
 } 
 } 
 } 
 </script> 

Использование этого подхода позволяет нам управлять на микроуровне, когда и где будут выполняться наши мутации и запросы. Теперь мы увидим некоторые другие способы обработки этих методов, которые дает нам Vue Apollo.

Объект Аполлон

Внутри наших компонентов Vue мы получаем доступ к Apollo , который можно использовать для простого управления нашими запросами и подписками:

 <template> 
 <div class="graphql-test"> 
 {{ getAllUsers }} 
 </div> 
 </template> 
 
 <script> 
 import { GET_ALL_USERS_QUERY } from '../graphl/queries/userQueries' 
 export default { 
 name: 'GraphQL-Test', 
 apollo: { 
 getAllUsers: { 
 query: GET_ALL_USERS_QUERY 
 } 
 } 
 } 
 </script> 
Получение запросов

При определении запроса внутри объекта Apollo можно выполнить повторную выборку этого запроса при вызове мутации или другого запроса с refetch метода refetch или свойства refetchQueries

 <template> 
 <div class="graphql-test"> 
 {{ getAllUsers }} 
 </div> 
 </template> 
 
 <script> 
 import { GET_ALL_USERS_QUERY, CREATE_USER_MUTATION } from '../graphl/queries/userQueries' 
 export default { 
 name: 'GraphQL-Test', 
 apollo: { 
 getAllUsers: { 
 query: GET_ALL_USERS_QUERY 
 } 
 }, 
 methods: { 
 refetch () { 
 this.$apollo.queries.getAllUsers.refetch() 
 }, 
 queryUsers () { 
 const user = { name: Lucas, age: 26 } 
 this.$apollo.mutate({ 
 mutation: CREATE_USER_MUTATION, 
 variables: { 
 user 
 } 
 refetchQueries: [ 
 { query: GET_ALL_USERS_QUERY } 
 ] 
 }) 
 } 
 } 
 } 
 </script> 

Используя Apollo , предоставленный нам Vue-Apollo , нам больше не нужно активно использовать клиентский способ запуска запросов / подписок Apollo, и нам становятся доступны некоторые полезные свойства и параметры.

Свойства объекта Apollo
  • query : это gql относящаяся к запросу, который должен запускаться.
  • переменные : объект, который принимает параметры, передаваемые заданному запросу.
  • fetchPolicy : свойство, определяющее способ взаимодействия запроса с кешем. Возможные варианты: cache-and-network , network-only cache-only , no-cache , standby и по умолчанию - cache-first .
  • pollInterval : время в миллисекундах, определяющее, как часто запрос будет автоматически запускаться.
Специальные опции
  • $ error для обнаружения ошибок в обработчике набора.
  • $ deep внимательно следит за изменениями в запросе.
  • $ skip : отключает все запросы и подписки в данном компоненте.
  • $ skipAllQueries : отключает все запросы от компонента.
  • $ skipAllSubscriptions : отключает все подписки в компоненте.

Компоненты Apollo

Вдохновленный тем, как Apollo Client реализован для React ( React-Apollo ), Vue-Apollo предоставляет нам несколько компонентов, которые мы можем использовать прямо из коробки для управления пользовательским интерфейсом и состоянием наших запросов и изменений с помощью компонента Vue внутри. шаблон.

ApolloQuery

Более простой способ более интуитивного управления нашими запросами:

 <ApolloQuery 
 :query="GET_ALL_USERS_QUERY" 
 > 
 <template slot-scope="{ result: { loading, error, data } }"> 
 <!-- Loading --> 
 <div v-if="loading">Query is loading.</div> 
 
 <!-- Error --> 
 <div v-else-if="error">We got an error!</div> 
 
 <!-- Result --> 
 <div v-else-if="data">{{ data.getAllUsers }}</div> 
 
 <!-- No result (if the query succeed but there's no data) --> 
 <div v-else>No result from the server</div> 
 </template> 
 </ApolloQuery> 
АполлонМутация

Очень похоже на приведенный выше пример, но мы должны вызвать мутацию с помощью вызова функции mutate

 <ApolloMutation 
 :mutation="CREATE_USER_MUTATION" 
 :variables="{ 
 name, 
 age 
 }" 
 @done="mutationFinished" 
 > 
 <template slot-scope="{ mutate, loading, error }"> 
 <!-- Loading --> 
 <h4 v-if="loading">The mutation is loading!</h4> 
 
 <!-- Mutation Trigger --> 
 <button @click="mutate()">Create User</button> 
 
 <!-- Error --> 
 <p v-if="error">An error has occurred!</p> 
 </template> 
 </ApolloMutation> 

Заключение

GraphQL обеспечивает большую гибкость при разработке API, с точки зрения производительности, простоты использования и в целом другой точки зрения на то, как API должен выглядеть и вести себя. Кроме того, ApolloClient и Vue Apollo предоставляют набор инструментов для лучшего управления нашим пользовательским интерфейсом, состоянием и операциями, даже обработкой ошибок и кешированием!

Для получения дополнительной информации о GraphQL и Apollo Client вы можете посетить следующее:

comments powered by Disqus

Содержание