ushumpei’s blog

生活で気になったことを随時調べて書いていきます。

Apollo Client 2.0 with React関連のライブラリ整理

Apollo Client 2.0 with React関連のライブラリをざっくり整理して見ます。失敗したらごめんなさい。詳細は Apollo Docs | Apollo Docs に書いてあります。

目次

Apollo Client

サーバーとの間で、クエリ発行、データ取得、キャッシングなどしてくれます。2017/10にバージョン2.0がリリースされて、大幅にコードの分離が行われました。キャッシング、サーバーとの通信部分が分離されたため、apollo-client-presetを使用しない場合は明示的に指定する必要があります。React, Angular, Vue, その他多くのJavaScriptFrameworkで、GraphQLクライアントとして使用できるそうです。

使い方はインスタンス化したのち、呼び出したいクエリを渡して実行してもらいます。 React の場合は react-apollo から提供されているコンポーネントインスタンスを渡し、子コンポーネントとクエリをHOCに入れてクエリ発行したりします(後述)。

import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { HttpLink } from 'apollo-link-http';

const client = new ApolloClient({
  cache: new InMemoryCache(),
  link: new HttpLink({ uri: 'http://localhost:3000' })
});


// クエリの発行
import gql from 'graphql-tag';

client.query({
  query: gql`
    query {
      channels {
        id
        name
      }
    }
  `,
})
  .then(data => console.log(data))
  .catch(error => console.error(error));

Cache関連

apollo-cache-inmemory

Apollo Clientで使用する標準的なインメモリーキャッシュのライブラリ。分離されました。パッケージとしてはApollo Clientと分かれていますが、ソースの管理はapollo-clientリポジトリで行われているのでそこに行くと読めます。

const inMemoryCache = new InMemoryCache({
  dataIdFromObject,
  cacheResolvers: {
    Query: {
      channel: (_, args) => {
        return toIdValue(dataIdFromObject({
          __typename: 'Channel',
          id: args['id'],
        }))
      },
    },
  },
});

Link関連

ネットワークを柔軟に選択することができます。HTTP通信はapollo-link-httpで行えます。

apollo-linkApollo Linkを継承すれば自分でもネットワークを作成することができます。また、httpwsを場合によって切り分けて通信したい場合に、ApolloLink.splitを使って新たなLinkを記述できます。

import { getOperationAST } from 'graphql';

import { WebSocketLink } from 'apollo-link-ws';
import { HttpLink } from "apollo-link-http";
import { ApolloLink } from 'apollo-link';

import { SubscriptionClient } from 'subscriptions-transport-ws';

const wsLink = new WebSocketLink(new SubscriptionClient('ws://localhost:4000/subscriptions', { reconnect: true }));

const httpLink = new HttpLink({ uri: 'http://localhost:4000/graphql' });

const link = ApolloLink.split(
  ({ query, operationName }) => {
    const operationAST = getOperationAST(query, operationName);
    return !!operationAST && operationAST.operation === 'subscription';
  },
  wsLink,
  httpLink,
);

subscriptions-transport-ws

WebSocketのGraphQLエンドポイントに接続するクライアント SubscriptionClient が入っています。

GraphQL関連

graphql-tag

このライブラリから、GraphQLクエリ文字列を、クエリの構文木(GraphQL.js AST format)に変換するgqlテンプレートタグが使用できます。

import gql from 'graphql-tag';

...

export const channelsListQuery = gql`
  query ChannelsListQuery {
    channels {
      id
      name
    }
  }
`;

GraphQL.js

Facebook製のライブラリで、Queryに対してより詳細な処理をしたい時に使ったりします。上の方のLink関連に出てきている、Query内容を調べて処理を分けるといった時に、このライブラリのgetOperationASTを使ってASTから値を読んでいます。

graphql-tools

サーバー側でschemaとresolverを結びつける関数を提供してくれます(schemaは型やクエリ、ミューテーションの仕様を書くもの、resolverは各仕様の実装を書くものです)。

import { makeExecutableSchema } from 'graphql-tools';

const executableSchema = makeExecutableSchema({
  typeDefs,
  resolvers,
});

React関連

react-apollo

Apollo Client向けのReactライブラリです。ApolloProviderコンポーネントgraphql高階コンポーネントを提供してくれます。ApolloProviderはrootコンポーネントをラップして使用し、Apollo Clientのインスタンスをpropに流してくれます。graphql高階コンポーネントはクエリとオプションとコンポーネントを引数に、新しいコンポーネントを生成します。ラップされたコンポーネントpropsdataというプロパティが追加されます。(クエリがMutationのときはmutate?)

graphql(gql`
  {  query... }
`, { options... }
)(Component)

const Component = ({ data }) => (...);

まとめ

書いているうちに未整理なことに気がついてしまいました。GraphQLの話をしているときは、schema、resolverって使っていいのか心配です。Apolloだけだったりする?Relayは触っていないです。。。