Heuristic Fragment matcher warning! How to fix it?

Cover Image for Heuristic Fragment matcher warning! How to fix it?

Apollo client is widely used for managing data fetched via GraphQL and caching is one of the main features it offers. If you are using Unions or Fragments in GraphQL , by default the apollo client uses Heuristic Fragment matcher to map the fields(fragments).

Why do you see it?

Before you freak out why this warning occurs, understand the fact that Apollo Client doesn’t know our GraphQL schema and hence it cannot accurately map the fragments. So this will end with the following warning on your console:

“You are using the simple (heuristic) fragment matcher, but your queries contain union or interface types. “

Should you worry about this?

Heuristic fragment matcher works fine in some cases but Apollo Client will not verify the server response i.e., it doesn’t stop you from manually writing an invalid data into the store using writeQuery or updateQuery. So, it’s not ideal to ignore the warnings.

Thano’s Snap! Make the warning disappear:

So, for this warning to go away, you can query the schema to get the required information about unions and interfaces. Thereafter, provide this knowledge to the InMemeoryCache of apollo client using the IntrospectionFragmentMatcher as described in the docs.

Step by step guide – using IntrospectionFragmentMatcher

Let’s see how we can make apollo client accurately map the fragments (unions & interfaces) and validate them before writing it to the store.

Step 1: Create the schemaQuery file

As the initial step, go to the project ‘src’ folder and create a file named schemaQuery.js and add the following code:

const fetch = require('node-fetch');
const fs = require('fs');

fetch(`https://api.example.com/graphql`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
variables: {},
query: `
{
__schema {
types {
kind
name
possibleTypes {
name
}
}
}
}
`,
}),
})
.then(result => result.json())
.then(result => {
// here we're filtering out any type information unrelated to unions or interfaces
const filteredData = result.data.__schema.types.filter(
type => type.possibleTypes !== null,
);
result.data.__schema.types = filteredData;
fs.writeFileSync('./src/fragmentTypes.json', JSON.stringify(result.data), err => {
if (err) {
console.error('Error writing fragmentTypes file', err);
} else {
console.log('Fragment types successfully extracted!');
}
});
});

The above code, will query your schema and store it in fragmentTypes.json (This json file is created automatically, you don’t have to create it). However, you can change the creation path of the fragmentTypes.json file. Finally, remember to replace the api.example.com with your actual API server.

Step 2: Pass the fragmentTypes to InMemoryCache

Go to the file where you initialise apollo client cache and type in the following code :

import {IntrospectionFragmentMatcher} from 'apollo-cache-inmemory';
import introspectionQueryResultData from '../../../src/fragmentTypes.json';
const fragmentMatcher = new IntrospectionFragmentMatcher({introspectionQueryResultData});

Note: The path for fragmentTypes.json file needs to be the same as step 1.

Now, pass the fragmentMatcher with schema data to Apollo’s InMemoryCache as follows:

cache: new InMemoryCache({fragmentMatcher})

After you have added all the above code, your file should look something like this :

Step 3: Build and fetch the Schema object into fragmentTypes.json

Using node, in package.json set up a build script for querying the schema and writing it in fragmentTypes.json file. For example:

 "build-fragment” : “node src/schemaQuery.js”

Run “npm run build-fragment” and let the magic happen!

The fragmentTypes.json file gets created and all your schema information related to unions and interfaces are stored as an object.

Optional step : Set the schemaQuery.js script to run at build time

To introspect the server every time we build the project, it is recommended to run a parallel node thread for your “start” script in package.json as follows :

“start”: “ npm-run-all -p start-server build-fragment”,
“start-server”: “node server.js”,
“build-fragment”: “node src/schemaQuery.js”

Now, running “npm run start” will trigger both your node server and the schemaQuery script that we just added.

Watch the video below on How to Fix this Warning.

Conclusion

Hope you found this article helpful in getting rid of the heuristic fragment matcher warning. Checkout Educatly (student platform to explore over 1,50,000 study-abroad opportunities worldwide), where we used the IntrospectionFragmentMatcher to deal with heuristic fragment warnings caused by caching unions and interfaces.