【GraphQL】Apollo Clientのキャッシュ制御について【状態管理ライブラリ】
IT技術
はじめに
GraphQLを学ぶにあたって、Apolloの公式チュートリアルが非常に有益でした。このチュートリアルは、GraphQLの基礎についても触れている為、GraphQLとApolloを実務に近い形でセットで学べる点が優れていると感じました。その中でも特に、キャッシュの制御については非常に勉強になった為、要点をまとめていきます。
プロジェクトにApolloを導入検討している方、既に実務で使用している方、キャッシュ戦略を練る方などのお役に立てれば幸いです。いきなり本題読みたい方はこちら
そもそもGraphQLとは?という方はこちらの記事
GraphQLの基本的な操作についてはこちらの記事
Apollo Clientとは
JavaScript用の包括的な状態管理ライブラリで、ローカルとリモート両方のデータをGraphQLで管理できます。アプリケーションのデータのフェッチ(取得)や、キャッシュ、更新を行いながら、UIを自動的に更新できます。(公式参考)
キャッシュの仕組み
GraphQLでフェッチしたデータは、正規化後にインメモリのキャッシュに保存される為、Apollo Clientの初期設定時、cacheにInMemoryCasheを渡しておきましょう。
1import { ApolloClient, InMemoryCache, ApolloProvider } from "@apollo/client";
2
3// Apollo clientの設定
4const client = new ApolloClient({
5 uri: 'http://localhost:4000', // GraphQLサーバーのURL
6 cache: new InMemoryCache(), // キャッシュの設定
7});
Apollo Clientは、クエリ発行後にまずキャッシュを探して、データがある場合はそのまま返し、ない場合はサーバーにリクエストを送ってレスポンスを返す、という仕様になっています。その為、キャッシュにデータが既にある場合は、高速な画面表示が可能となっています。
このデータフローについては、公式の図がわかりやすい為、一度ご覧になって下さい。
キャッシュの制御方法〜fetchPolicy〜
Apollo Clientでは、useQueryを用いてクエリを実行する際に、fetchPolicyというオプションでキャッシュの方法を制御することができます。
1import { useQuery } from '@apollo/client';
2
3const { loading, error, data } = useQuery(MY_QUERY, {
4 fetchPolicy: 'cache-and-network', // fetchPolicy記述例
5});
fetchPolicyオプションは以下の6つの中から、クエリごとのニーズに合わせて適切なものを選択できます。
cache-first
1fetchPolicy: 'cache-first'
キャッシュにデータがあればそれを使用し、キャッシュにデータがなければGraphQLサーバーにクエリを実行し、キャッシュ後にそのデータを返します。クエリのレスポンス時間の短縮を重視したポリシーで、これがデフォルト値となっています。
cache-only
1fetchPolicy: 'cache-only'
サーバーへのリクエストをせず、キャッシュのみにクエリを実行します。キャッシュ内にデータがない場合は、エラーがスローされます。サーバー側の変更は考慮せず、ユーザーに同じ情報を表示させ続けたい場合に使えるようです。
cache-and-network
1fetchPolicy: 'cache-and-network'
クエリ実行後にキャッシュをクライアントに返却した後、同時にサーバーからデータフェッチして、キャッシュを更新します。この時キャッシュに変更があった場合は、更新後のキャッシュデータをクライアントに返します。高速なレスポンスが期待できる点とキャッシュのデータを最新のデータに保つことができる点が良いですね。
network-only
1fetchPolicy: 'network-only'
キャッシュを通さずにGraphQLサーバーに対して直接クエリを実行し、フェッチしたデータでキャッシュを更新してそれを返します。常に最新のデータを表示したい場合などは効果的ですが、キャッシュが利用可能な時と比べるとレスポンス速度で劣ります。
no-cache
1fetchPolicy: 'no-cache'
network-onlyと同じく、サーバーからデータフェッチして最新のデータを返すのみです。network-onlyとは違い、フェッチしたデータはキャッシュを更新もしませんし保存もされません。
standby
1fetchPolicy: 'standby'
キャッシュに対してクエリが行われますが、フィールドの値が変更されても自動更新されません。クエリが待機状態になる為、refetchやuseLazyQueryを使って任意のタイミングでの手動更新ができます。
nextFetchPolicy
クエリにはfetchPolicyだけではなく、nextFetchPolicyも指定することが可能です。これは例えば、最初のクエリはサーバーにリクエストして、2回目以降はキャッシュから読み込み可能、といった設定にもできます。
1const { loading, error, data } = useQuery(MY_QUERY, {
2 fetchPolicy: 'network-only', // 1回目のクエリ
3 nextFetchPolicy: 'cache-first', // 2回目のクエリ
4});
終わりに
今回は、Apollo Clientという、GraphQLを使用してデータを管理するためのJavaScript状態管理ライブラリのキャッシュ制御についてのみ紹介致しましたが、これはApolloの機能のほんの一部に過ぎません。冒頭でも触れた通り、Apollo Clientは状態管理ライブラリであり、海外では記述の冗長なReduxに変わる可能性を秘めた状態管理ライブラリだという声も上がっているようでした。(参考)Apolloは学習コストが高い印象を受けましたが、プロジェクトへの導入を検討されている方やキャッシュ戦略を立てる方のお役に立てると幸いです。ここまで読んで頂きありがとうございました。
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ
小学校教諭、住宅設計等を経て、2021年よりWeb業界に携わっています。 主にWebのフロントエンドとマーケティング分野を経験してきました。 好きなプログラミング言語は、React/Next.jsです。 よろしくお願い致します。