Apollo Client のデフォルトで設定されている fetch policy を変更する
はじめに
Apollo Client はクエリーなどでデータを取得した時に、結果を自動でキャッシュするようになっています。その後、再度同じクエリーを実行するとサーバーサイド側にはクエリーを投げず、キャッシュされているデータを返します。
これにより、レスポンスの高速化やサーバーサイド側の負荷を下げるなどのメリットはあるものの、再 fetch されずデータがうまく反映されないなどの問題が発生するリスクが高まります。
特にプロジェクト立ち上げ時などは、パフォーマンスよりもまずは正しく動くことを優先したい!というケースもあると思うので、キャッシュを使用しないのも選択肢の1つかなと思います。(Apollo を使う旨味が減りそうですが...)
キャッシュを使用するか否かは fetch policy によって変更できます。
本記事では、サポートされている fetch policy を見ていき、最終的にはデフォルトの fetch policy を変更します。
筆者は Apollo Client を使い始めてまだ日が浅いので、認識に誤りがあるかもしれないです。その時は優しくコメントいただけると助かります🙏
サポートされている fetch policy を見ていく
cache-first
デフォルトの fetch policy なので、設定を変更していなければ cache-first が設定されているはずです。キャッシュに対してクエリーし、キャッシュがなければサーバーサイド側にクエリーします。名前の通りキャッシュを優先します。
cache-only
先にキャッシュに対してクエリーするところまでは cache-first と同じですが、キャッシュがなかった時に例外を発生させるところが異なります。
初回のクエリー実行時はキャッシュがないので、必ずエラーになってしまうのでは?と思いましたが、nextFetchPolicy を使用することで、初回のクエリー、2回目以降のクエリーでそれぞれ fetch policy を設定できるようです。
cache-and-network
キャッシュとサーバーサイド側の両方に対してクエリーします。キャッシュがあれば瞬時に表示できますし、サーバーサイド側にもクエリーを投げるのでデータの整合性も取れます。ただ、キャッシュの内容とレスポンスの結果が異なっていた場合はキャッシュの内容を表示 → レスポンスの結果を表示と内容が変わるので多少ちらつきます。
network-only
キャッシュに対してクエリーせず、サーバーサイド側に対してクエリーします。また、キャッシュは参照しないものの、クエリー結果はキャッシュします。キャッシュする理由はあまり把握できていないですが、nextFetchPolicy で記載されているサンプルのように cache-only と組み合わせて使いたい場面があるんですかね。network-only は整合性を保てるメリットはあるものの、都度サーバーサイドに対してクエリーするので、キャッシュを使用する場合と比較するとパフォーマンスは悪くなります。
no-cache
キャッシュに対してクエリーせず、サーバーサイド側に対してクエリーするところまでは network-only と同じですが、クエリー結果をキャッシュしないところが異なります。nextFetchPolicy などでキャッシュを使用しないなら network-only ではなく、no-cache を使用するのが良さそうかなと思いました。
standby
先にキャッシュに対してクエリーするところまでは cache-first と同じですが、フィールドが更新された時にサーバーサイド側にクエリーされないところが異なるようです。正直使い所はあまりイメージできていません...
デフォルトの fetch policy を変える
defaultOptions の watchQuery で fetch policty を指定することで、すべてのクエリーに適用できます。
今回は下記のようにキャッシュを無効にしてみました。
export default new ApolloClient({
...
defaultOptions: {
watchQuery: {
fetchPolicy : 'no-cache'
}
}
}
終わりに
今回は安全側に倒してキャッシュを無効にしましたが、これだと Apollo の旨味が減ってしまうので良い方法を模索していきたいなーと思っています。(cache-and-network
は良い落とし所かなとも思ったのですが、どうしてもちらつきが気になり...)
Discussion