Apollo クライアントは、GraphQLクエリの結果を正規化してローカルのメモリ内に保存します。そして、メモリ内のクエリ結果をキャッシュとして利用します。 GraphQLクエリの実行時にクエリ結果がキャッシュにある場合は、ネットワークリクエストを省略して即時に応答できます。
Apollo Clietn のキャッシュの概要
公式ドキュメントのシーケンス図を引用しつつ、具体例を説明します。
GetBook(bookId: "5")
のGraphQLクエリを実行するケースを考えてみましょう。
「Apollo Client」の初回のGetBook(bookId: "5")
のGraphQLクエリ実行時は「InMemoryCache」にBook:5
のデータが存在しないため、「GraphQL Server」にクエリを実行して結果を取得します。そして、クエリ結果を「InMemoryCache」に正規化して保存し、「Apollo Client」にクエリ結果を返します。
その後、2回目以降のGetBook(bookId: "5")
のGraphQLクエリを実行時は、「InMemoryCache」にBook:5
のデータが存在するため、「GraphQL Server」にネットワークリクエストを実施せず、そのままキャッシュの値を「Apollo Client」に返します。
このように、キャッシュを有効に使うことで、アプリケーションは即時に応答することができます。しかし、キャッシュを使うことでメモリとサーバーの状態がずれてバグの温床にもなり得るので注意が必要です。
サポートされているFetch Policy
Apollo Client でサポートされているフェッチポリシーは次の6つになります。キャッシュの挙動に影響を与えるため、どのポリシーを使っているかを理解することが大切です。
ポリシー名 | 説明 |
---|---|
cache-first (デフォルト) |
ネットワークリクエストの数を最小限に抑えることを優先している。 キャッシュに全てのフィールドのデータがあれば返す。なければGraphQLサーバーにクエリをリクエストする。クエリ結果をキャッシュする。 |
cache-and-network |
高速な応答を提供しつつ、サーバーとローカルデータの一貫性を維持できる。 キャッシュとGraphQLサーバーの両方にクエリを実行し、サーバ側のクエリ結果をキャッシュする。 |
network-only |
サーバーとローカルデータの一貫性を常に保てる。 キャッシュを参照せず、GraphQLサーバーに常にリクエストする。クエリ結果はキャッシュする。 |
no-cache |
サーバーとローカルデータの一貫性を常に保つが、キャッシュは更新しない。 キャッシュを参照せず、GraphQLサーバーに常にリクエストする。クエリ結果はキャッシュしない。 |
cache-only |
キャッシュに全てのフィールドのデータがあれば返す。なければ、エラーをスローする。 |
standby |
cache-first と同じロジックだが、フィールドが更新されても自動的に更新しない。 |
Fetch Policyの設定方法
フェッチポリシーの設定方法は、主に次の2つがあります。
new ApolloClient
時にfetchPolicy
を指定useQuery
でfetchPolicy
を指定
「new ApolloClient
時にfetchPolicy
を指定」するとデフォルトのフェッチポリシーを指定することができます。(参考: class Apollo Client)
const client = new ApolloClient({ uri: 'https://flyby-router-demo.herokuapp.com/', cache: new InMemoryCache(), defaultOptions: { query: { fetchPolicy: 'cache-first', }, watchQuery: { fetchPolicy: 'cache-and-network' }, }, });
また、「useQuery
でfetchPolicy
を指定」すると、個別でフェッチポリシーを指定できます。
const { loading, error, data } = useQuery(GET_TODOS, { fetchPolicy: 'network-only', // キャッシュを利用せずGraphQLサーバーに常にリクエスト。クエリ結果はキャッシュする });
Apollo Client のキャッシュを可視化する
ブラウザ拡張の Apollo Client Devtools を利用することで、キャッシュを可視化できます。
また、キャッシュは正規化されて格納されます。How is data stored? でキャッシュの構造について理解を深めることができます。
Apollo Client のキャッシュを操作する
Apollo Client のキャッシュを直接操作することができます。
メソッド | 説明 |
---|---|
readQuery / writeQuery / updateQuery |
GraphQLのクエリ結果を取得・変更できる |
readFragment / writeFragment / updateFragment / useFragment |
フラグメントの値を取得・変更できる |
cache.modify |
キャッシュの値を直接変更できる |
より詳細は Reading and writing data to the cacheを参照ください。