Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apollo+GraphQL - Heuristic Fragment Manual Matching

I have a headless Craft CMS that is returning data to my Nuxtjs app through a GraphQL endpoint through Apollo. I have a field that can return one of three different block types: richText, image, and pullQuote.

My GraphQL endpoint looks like this:

query($section:[String], $slug:[String]) {
    entries(section: $section, slug: $slug) {
        id,
        title,
        uri,
        ... on blog_blog_Entry{
            contentEngine{
                __typename,
                ...on contentEngine_richText_BlockType{
                    __typename,
                    id,
                    richText
                    fontColor,
                    backgroundColor
                }
                ...on contentEngine_image_BlockType{
                    __typename,
                    id,
                    backgroundColor,
                    imageWidth,
                    image {
                        id,
                        url
                    }
                }
                ...on contentEngine_pullQuote_BlockType{
                    __typename,
                    id,
                    backgroundColor,
                    fontColor,
                    quote
                }
            }
        }
    }
}

It returns data just fine, but I'm getting this error when trying to use it within my Nuxt component:

You are using the simple (heuristic) fragment matcher, but your queries contain union or interface types. Apollo Client will not be able to accurately map fragments. To make this error go away, use the IntrospectionFragmentMatcher as described in the docs: https://www.apollographql.com/docs/react/advanced/fragments.html#fragment-matcher

The infuriating thing is that this documentation leads to a 404. I've found a few other GitHub tickets that reference this link, so I'm not sure what steps I should be following.

I think what I need to do is to teach Apollo's memory cache. Since my response isn't that complicated, I think I can get away with Defining PossibleTypes manually.

I've tried the following, but I don't think I'm understanding how to set this up properly:

const cache = new InMemoryCache({
    possibleTypes: {
        contentEngine: [
            "contentEngine_richText_BlockType", 
            "contentEngine_pullQuote_BlockType", 
            "contentEngine_image_BlockType"
        ],
    },
});

Any help for getting around this issue would be a huge help.

WARNING: heuristic fragment matching going on!

like image 786
Rob Erskine Avatar asked Nov 17 '25 08:11

Rob Erskine


1 Answers

I struggled with this myself, but after @mylesthe.dev (who responded above) spoke to me directly to provide fantastic support and some examples, I figured it out. So for anyone else still struggling like I was, here's the code (thanks to his work) which finally got things working for me:

First of all, in your nuxt.config.js set up your apollo configs:

// Apollo config and endpoint for graph ql
apollo: {
  includeNodeModules: true,
  clientConfigs: {
    default: '@/apollo/client-configs/default.js' // This is where you'll set up the client and import the possible fragment types
  }
},

Now we create the apollo client set up with the fragment schema file (which we'll create) in apollo/client-configs/default.js

import { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import schema from './schema.json';
const fragmentMatcher = new IntrospectionFragmentMatcher({
    introspectionQueryResultData: schema
  })

export default ({req, app}) => {
    const token = process.env.GRAPHQL_TOKEN
    return {
        httpEndpoint: process.env.API_ENDPOINT,
        getAuth: () => `Bearer ${token}`, // remove if you're using the public schema
        cache: new InMemoryCache({ fragmentMatcher }),
    }
}


Now save an empty schema.json file in apollo/client-configs/.

Next we need to set up the script to query and generate this schema on nuxtServerInit. You'll need fs to write your schema file. You can install it with NPM: npm install --save fs.

Once installed, go back to your nuxt.config and add fs to the build:

build: {
  extend (config, ctx) {
    config.node = {
      fs: 'empty'
    }
  }
}

Then in your store/index.js:

import Vuex from 'vuex';
import fetch from 'node-fetch';
import fs from 'fs';


const createStore = () => {
  return new Vuex.Store({
    actions: {
        async nuxtServerInit({commit}, {app}) {

            // only update fragements locally
            if (process.env.NODE_ENV == 'local') {
                 
                // LOAD FRAGMENT TYPES AND STORE IN FILE
                // APOLLO READS THIS FILE LATER
                fetch(process.env.API_ENDPOINT, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json', authorization: 'Bearer ' + process.env.GRAPHQL_TOKEN, },
                    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.writeFile('./apollo/client-configs/schema.json', JSON.stringify(result.data), err => {
                        if (err) {
                            console.error('Error writing fragmentTypes file', err);
                        }
                    });
                });

            }
            
        },
    }
  });
};

export default createStore

Your schema should now be generated locally to the schema file and that file will be stored in the apollo cache.

like image 149
ToddPadwick Avatar answered Nov 19 '25 10:11

ToddPadwick