Apollo+GraphQL - 启发式片段手动匹配

Rob*_*ine 3 apollo graphql nuxt.js vue-apollo

我有一个无头 Craft CMS,它通过 Apollo 通过 GraphQL 端点将数据返回到我的 Nuxtjs 应用程序。我有一个可以返回三种不同块类型之一的字段:richTextimagepullQuote

我的 GraphQL 端点如下所示:

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
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它返回数据很好,但是当我尝试在 Nuxt 组件中使用它时出现此错误:

您正在使用简单(启发式)片段匹配器,但您的查询包含联合或接口类型。Apollo 客户端将无法准确映射片段。要消除此错误,请使用IntrospectionFragmentMatcher文档中所述的方法:https ://www.apollographql.com/docs/react/advanced/fragments.html#fragment-matcher

令人气愤的是,该文档导致了 404 错误。我发现了一些其他引用此链接的 GitHub 票证,因此我不确定应该遵循哪些步骤。

我想我需要做的是教Apollo的内存缓存。由于我的回答并不那么复杂,我想我可以手动定义可能的类型

我已经尝试过以下操作,但我认为我不理解如何正确设置:

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
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

任何解决这个问题的帮助都会有很大的帮助。

警告:启发式片段匹配正在进行中!

Tod*_*ick 5

我自己也曾为此苦苦挣扎,但在@mylesthe.dev(上面的回复者)直接与我交谈并提供了出色的支持和一些示例之后,我找到了答案。因此,对于像我一样仍在苦苦挣扎的其他人来说,这里的代码(感谢他的工作)最终让事情为我工作:

首先,在 nuxt.config.js 中设置 apollo 配置:

// 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
  }
},
Run Code Online (Sandbox Code Playgroud)

现在我们创建 apollo 客户端,并使用片段架构文件(我们将在其中创建)进行设置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 }),
    }
}


Run Code Online (Sandbox Code Playgroud)

现在将一个空schema.json文件保存在apollo/client-configs/.

接下来,我们需要设置脚本来查询并生成此架构nuxtServerInit。您需要fs编写架构文件。您可以使用 NPM 安装它npm install --save fs

安装后,返回 nuxt.config 并将 fs 添加到构建中:

build: {
  extend (config, ctx) {
    config.node = {
      fs: 'empty'
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的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

Run Code Online (Sandbox Code Playgroud)

您的架构现在应该在架构文件本地生成,并且该文件将存储在 apollo 缓存中。