Apollo Clientのキャッシュ機能は便利で特に設定をせずにそのまま使えてたのですが、UnionやInterfaceを利用する際に工夫が必要だったのでご紹介します。
問題
Apollo ClientでUnionやInterfaceを含んだクエリを扱うと以下のようなWarningが出ました。
これはFragment MatcherというApollo Clientのキャッシュ機構に使われているもので、デフォルトのものだとInterfaceやUnionには対応できないため警告がでています。
これを解決するためにはサーバーで定義されたスキーマに対応したFragment Matcherを用意する必要があります。
解決策
Fragment Matcherの設定を行うにはまず、GraphQL Code Generatorというツールを使います。
@graphql-codegen/cli
と @graphql-codegen/fragment-matcher
のインストールが必要です。
yarn add -D @graphql-codegen/cli @graphql-codegen/fragment-matcher
次にGraphQL Code Generatorの設定ファイルを用意します。
# codegen.yml
schema: [YOUR_API]
overwrite: true
generates:
./fragmentTypes.json:
plugins:
- fragment-matcher
このような設定になります。schema
オプションにGraphQLサーバーのエンドポイント、またはスキーマ情報が書かれたjsonファイルなどが入ると思います。
設定が完了したら、以下コマンドを実行してください。
$ yarn run gql-gen
#or
$ npm run gql-gen
実行後、fragmentTypes.jsonというファイルが生成されます。
これはGraphQLのスキーマ情報であるIntrospection Resultを自動で出力されたものです。
例えば
union Animal
= Dog | Cat | Bear
のようなスキーマが定義されていたとすると、fragmentTypes.jsonは以下のようなものが出力されるはずです。
{
"__schema": {
"types": [
{
"kind": "UNION",
"name": "Animal",
"possibleTypes": [
{
"name": "Dog"
},
{
"name": "Cat"
},
{
"name": "Bear"
}
]
}
]
}
}
あとはこの生成されたfragmentTypes.jsonをApollo Clientインスタンス作成時に読み込むことでWarningを解消することができます。
import { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'
import { ApolloClient } from 'apollo-client'
import introspectionQueryResultData from '../fragmentTypes.json'
// IntrospectionFragmentMatcher
const fragmentMatcher = new IntrospectionFragmentMatcher({
introspectionQueryResultData
})
// InMemoryCache
const cache = new InMemoryCache({ fragmentMatcher })
const apolloClient = new ApolloClient({
cache,
...省略
})
最後に
今回はGraphQL Code Generatorを利用してIntrospection Resultを出力しましたが、手動でスクリプトを書いてサーバーからのレスポンスで出力する方法もありますので、ドキュメントを参考にしてみてください。
ドキュメント: Using fragments