GraphQL клиенты

GraphQL представляет собой мощный инструмент для работы с данными, позволяя клиенту запрашивать ровно те поля, которые необходимы, и получать их в одном запросе. Во Vue.js интеграция с GraphQL обычно осуществляется через специальные клиенты, такие как Apollo Client, который обеспечивает удобное связывание с компонентами Vue и управление состоянием данных.


Установка и настройка Apollo Client

Для начала необходимо установить пакет @apollo/client и интеграцию с Vue через @vue/apollo-composable:

npm install @apollo/client graphql @vue/apollo-composable

После установки создаётся клиент Apollo:

import { ApolloClient, InMemoryCache } from '@apollo/client/core';

const apolloClient = new ApolloClient({
  uri: 'https://example.com/graphql',
  cache: new InMemoryCache(),
});

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

Для интеграции с Vue 3 используется провайдер:

import { createApp, h, provide } from 'vue';
import { DefaultApolloClient } from '@vue/apollo-composable';
import App from './App.vue';

const app = createApp({
  setup() {
    provide(DefaultApolloClient, apolloClient);
  },
  render: () => h(App),
});

app.mount('#app');

Запросы данных с useQuery

useQuery — основная функция для выполнения GraphQL-запросов внутри компонентов Vue. Она возвращает реактивные объекты result, loading и error, что упрощает управление состоянием запроса.

import { useQuery, gql } from '@vue/apollo-composable';

const GET_USERS = gql`
  query GetUsers {
    users {
      id
      name
      email
    }
  }
`;

export default {
  setup() {
    const { result, loading, error } = useQuery(GET_USERS);

    return { result, loading, error };
  },
};

Особенности работы с useQuery:

  • result — реактивный объект, содержащий данные, обновляющийся автоматически при изменении ответа сервера.
  • loading — булево значение, показывающее, выполняется ли запрос.
  • error — объект ошибки при неудачном запросе, который можно использовать для отображения уведомлений или логирования.

Мутации с useMutation

Для изменения данных на сервере используется useMutation. Мутации возвращают функцию для вызова запроса и объекты состояния.

import { useMutation, gql } from '@vue/apollo-composable';

const ADD_USER = gql`
  mutation AddUser($name: String!, $email: String!) {
    addUser(name: $name, email: $email) {
      id
      name
      email
    }
  }
`;

export default {
  setup() {
    const { mutate, loading, error } = useMutation(ADD_USER);

    const addUser = () => {
      mutate({ name: 'John Doe', email: 'john@example.com' });
    };

    return { addUser, loading, error };
  },
};

Ключевые моменты:

  • Мутации не выполняются автоматически, их нужно вызвать через mutate.
  • Поддерживается передача переменных запроса.
  • С помощью Apollo Client можно настроить автоматическое обновление кэша после мутации.

Работа с локальным кэшем

Apollo Client предоставляет возможности для локального управления состоянием, что позволяет создавать реактивные данные без обращения к серверу. Это удобно для реализации фильтров, модальных окон и других интерфейсных состояний.

import { reactive } from 'vue';
import { useApolloClient, gql } from '@vue/apollo-composable';

export default {
  setup() {
    const client = useApolloClient().client;

    const updateCache = () => {
      const data = client.readQuery({ query: GET_USERS });
      client.writeQuery({
        query: GET_USERS,
        data: {
          users: [...data.users, { id: 4, name: 'Alice', email: 'alice@example.com' }],
        },
      });
    };

    return { updateCache };
  },
};

Принципы работы с кэшем:

  • readQuery позволяет получить текущее состояние данных из кэша.
  • writeQuery позволяет изменять кэш вручную, синхронизируя интерфейс с локальными изменениями.
  • Автоматическое обновление кэша можно настроить через опцию refetchQueries после мутации.

Подписки на события с useSubscription

GraphQL поддерживает подписки для работы с потоками данных в реальном времени. В Vue.js это реализуется через useSubscription.

import { useSubscription, gql } from '@vue/apollo-composable';

const USER_ADDED = gql`
  subscription OnUserAdded {
    userAdded {
      id
      name
      email
    }
  }
`;

export default {
  setup() {
    const { result, loading, error } = useSubscription(USER_ADDED);

    return { result, loading, error };
  },
};

Особенности подписок:

  • Подписки автоматически обновляют result при поступлении новых данных.
  • Требуется WebSocket-соединение, которое настраивается в Apollo Client через split и WebSocketLink.
  • Позволяют создавать динамические интерфейсы с обновлением данных в реальном времени без дополнительных запросов.

Оптимизация производительности

Для больших приложений важно минимизировать количество сетевых запросов и правильно использовать кэш:

  • Fragment — позволяет переиспользовать части запросов, избегая дублирования.
  • Lazy queries (useLazyQuery) — выполняются только по вызову функции, а не автоматически при монтировании компонента.
  • Pagination и fetchMore — для работы с большими массивами данных.
  • Error policies — настройка обработки ошибок, например ignore или all, чтобы приложение продолжало работать при частичных сбоях.

Интеграция с Vuex

Хотя Apollo Client имеет собственный кэш, иногда требуется объединение с Vuex:

import { useQuery, gql } from '@vue/apollo-composable';
import { useStore } from 'vuex';

const GET_POSTS = gql`
  query GetPosts {
    posts {
      id
      title
      content
    }
  }
`;

export default {
  setup() {
    const store = useStore();
    const { result } = useQuery(GET_POSTS, {}, { fetchPolicy: 'network-only' });

    result.watch((newVal) => {
      store.commit('setPosts', newVal.posts);
    });

    return {};
  },
};

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


Резюме

Vue.js вместе с Apollo Client предоставляет гибкую систему работы с GraphQL, включающую запросы, мутации, подписки и локальный кэш. Возможность реактивного связывания данных с компонентами, поддержка кэша и интеграция с Vuex делают разработку динамичных приложений удобной и масштабируемой. Оптимизация запросов и правильное использование инструментов Apollo существенно повышает производительность и упрощает управление состоянием.