阿波罗服务器&x2B;Next.js-GraphQL架构未更新

阿波罗服务器&x2B;Next.js-GraphQL架构未更新,graphql,next.js,apollo,apollo-client,apollo-server,Graphql,Next.js,Apollo,Apollo Client,Apollo Server,我有一个Apollo GraphQL/Next.js应用程序。在更改我的graphql架构并导航到位于“”的graphql游乐场之后http://localhost:3000/api/graphql“,旧架构仍在游乐场和我的应用程序中引用 我尝试过清除节点模块,运行npm安装,清除缓存,重新启动所有东西,但我无法理解为什么我的模式没有更新。我是否错过了一些关键的模式更新步骤 这是我对Series和Publisher的模式(请注意,SeriesInput需要Publisher,而不是Publish

我有一个Apollo GraphQL/Next.js应用程序。在更改我的graphql架构并导航到位于“”的graphql游乐场之后http://localhost:3000/api/graphql“,旧架构仍在游乐场和我的应用程序中引用

我尝试过清除节点模块,运行npm安装,清除缓存,重新启动所有东西,但我无法理解为什么我的模式没有更新。我是否错过了一些关键的模式更新步骤

这是我对Series和Publisher的模式(请注意,SeriesInput需要Publisher,而不是PublisherInput):

type Series {
    _id: ID!
    name: String
    altID: String
    publisher: Publisher!
    comics: [Comic]
}

input SeriesInput {
    _id: ID
    name: String!
    altID: String
    publisher: Publisher!
    comics: [Comic]
}

type Mutation {
    addSeries(series: SeriesInput): Series
}

type Query {
    series: [Series]
}

-------------------------

type Publisher {
    _id: ID!
    name: String
    altID: String
    series: [Series]
}

input PublisherInput {
    _id: ID!
    name: String!
    altID: String
    series: [Series]
}

type Mutation {
    addPublisher(publisher: PublisherInput): Publisher
}

type Query {
    publishers: [Publisher]
}

import { ApolloServer } from "apollo-server-micro";
import { mergeResolvers, mergeTypeDefs } from "graphql-tools";
import connectDb from "../../lib/mongoose";

// Mutations and resolvers
import { comicsResolvers } from "../../api/comics/resolvers";
import { comicsMutations } from "../../api/comics/mutations";
import { seriesResolvers } from "../../api/series/resolvers";
import { seriesMutations } from "../../api/series/mutations";
import { publishersResolvers } from "../../api/publishers/resolvers";
import { publishersMutations } from "../../api/publishers/mutations";

// GraphQL Schema
import Publishers from "../../api/publishers/Publishers.graphql";
import Series from "../../api/series/Series.graphql";
import Comics from "../../api/comics/Comics.graphql";

// Merge type resolvers, mutations, and type definitions
const resolvers = mergeResolvers([
    publishersMutations,
    publishersResolvers,
    seriesMutations,
    seriesResolvers,
    comicsMutations,
    comicsResolvers,
]);
const typeDefs = mergeTypeDefs([Publishers, Series, Comics]);

// Create apollo server and connect db
const apolloServer = new ApolloServer({ typeDefs, resolvers });
export const config = {
    api: {
        bodyParser: false,
    },
};
const server = apolloServer.createHandler({ path: "/api/graphql" });
export default connectDb(server);
 * Code copied from Official Next.js documentation to work with Apollo.js
 * https://github.com/vercel/next.js/blob/6e77c071c7285ebe9998b56dbc1c76aaf67b6d2f/examples/with-apollo/lib/apollo.js
 */

import React, { useMemo } from "react";
import Head from "next/head";
import { ApolloProvider } from "@apollo/react-hooks";
import { ApolloClient } from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
import { HttpLink } from "apollo-link-http";
import fetch from "isomorphic-unfetch";

let apolloClient = null;

/**
 * Creates and provides the apolloContext
 * to a next.js PageTree. Use it by wrapping
 * your PageComponent via HOC pattern.
 * @param {Function|Class} PageComponent
 * @param {Object} [config]
 * @param {Boolean} [config.ssr=true]
 */
export function withApollo(PageComponent, { ssr = true } = {}) {
    const WithApollo = ({ apolloClient, apolloState, ...pageProps }) => {
        const client = useMemo(() => apolloClient || initApolloClient(apolloState), []);
        return (
            <ApolloProvider client={client}>
                <PageComponent {...pageProps} />
            </ApolloProvider>
        );
    };

    // Set the correct displayName in development
    if (process.env.NODE_ENV !== "production") {
        const displayName = PageComponent.displayName || PageComponent.name || "Component";

        if (displayName === "App") {
            console.warn("This withApollo HOC only works with PageComponents.");
        }

        WithApollo.displayName = `withApollo(${displayName})`;
    }

    if (ssr || PageComponent.getInitialProps) {
        WithApollo.getInitialProps = async (ctx) => {
            const { AppTree } = ctx;

            // Initialize ApolloClient, add it to the ctx object so
            // we can use it in `PageComponent.getInitialProp`.
            const apolloClient = (ctx.apolloClient = initApolloClient());

            // Run wrapped getInitialProps methods
            let pageProps = {};
            if (PageComponent.getInitialProps) {
                pageProps = await PageComponent.getInitialProps(ctx);
            }

            // Only on the server:
            if (typeof window === "undefined") {
                // When redirecting, the response is finished.
                // No point in continuing to render
                if (ctx.res && ctx.res.finished) {
                    return pageProps;
                }

                // Only if ssr is enabled
                if (ssr) {
                    try {
                        // Run all GraphQL queries
                        const { getDataFromTree } = await import("@apollo/react-ssr");
                        await getDataFromTree(
                            <AppTree
                                pageProps={{
                                    ...pageProps,
                                    apolloClient,
                                }}
                            />
                        );
                    } catch (error) {
                        // Prevent Apollo Client GraphQL errors from crashing SSR.
                        // Handle them in components via the data.error prop:
                        // https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-query-data-error
                        console.error("Error while running `getDataFromTree`", error);
                    }

                    // getDataFromTree does not call componentWillUnmount
                    // head side effect therefore need to be cleared manually
                    Head.rewind();
                }
            }

            // Extract query data from the Apollo store
            const apolloState = apolloClient.cache.extract();

            return {
                ...pageProps,
                apolloState,
            };
        };
    }

    return WithApollo;
}

/**
 * Always creates a new apollo client on the server
 * Creates or reuses apollo client in the browser.
 * @param  {Object} initialState
 */
function initApolloClient(initialState) {
    // Make sure to create a new client for every server-side request so that data
    // isn't shared between connections (which would be bad)
    if (typeof window === "undefined") {
        return createApolloClient(initialState);
    }

    // Reuse client on the client-side
    if (!apolloClient) {
        apolloClient = createApolloClient(initialState);
    }

    return apolloClient;
}

/**
 * Creates and configures the ApolloClient
 * @param  {Object} [initialState={}]
 */
function createApolloClient(initialState = {}) {
    // Check out https://github.com/zeit/next.js/pull/4611 if you want to use the AWSAppSyncClient
    return new ApolloClient({
        ssrMode: typeof window === "undefined", // Disables forceFetch on the server (so queries are only run once)
        link: new HttpLink({
            uri: "http://localhost:3000/api/graphql", // Server URL (must be absolute)
            credentials: "same-origin", // Additional fetch() options like `credentials` or `headers`
            fetch,
        }),
        cache: new InMemoryCache().restore(initialState),
    });
}
是我在GraphQL游乐场中收到的错误消息,这是因为旧系列架构需要一个PublisherInput类型,该类型具有一个我没有传递的“Name”必填字段。

这是我的graphql apollo服务器代码,我使用MergeResolver和mergeTypeDefs将所有graphql文件合并到一个模式中:

type Series {
    _id: ID!
    name: String
    altID: String
    publisher: Publisher!
    comics: [Comic]
}

input SeriesInput {
    _id: ID
    name: String!
    altID: String
    publisher: Publisher!
    comics: [Comic]
}

type Mutation {
    addSeries(series: SeriesInput): Series
}

type Query {
    series: [Series]
}

-------------------------

type Publisher {
    _id: ID!
    name: String
    altID: String
    series: [Series]
}

input PublisherInput {
    _id: ID!
    name: String!
    altID: String
    series: [Series]
}

type Mutation {
    addPublisher(publisher: PublisherInput): Publisher
}

type Query {
    publishers: [Publisher]
}

import { ApolloServer } from "apollo-server-micro";
import { mergeResolvers, mergeTypeDefs } from "graphql-tools";
import connectDb from "../../lib/mongoose";

// Mutations and resolvers
import { comicsResolvers } from "../../api/comics/resolvers";
import { comicsMutations } from "../../api/comics/mutations";
import { seriesResolvers } from "../../api/series/resolvers";
import { seriesMutations } from "../../api/series/mutations";
import { publishersResolvers } from "../../api/publishers/resolvers";
import { publishersMutations } from "../../api/publishers/mutations";

// GraphQL Schema
import Publishers from "../../api/publishers/Publishers.graphql";
import Series from "../../api/series/Series.graphql";
import Comics from "../../api/comics/Comics.graphql";

// Merge type resolvers, mutations, and type definitions
const resolvers = mergeResolvers([
    publishersMutations,
    publishersResolvers,
    seriesMutations,
    seriesResolvers,
    comicsMutations,
    comicsResolvers,
]);
const typeDefs = mergeTypeDefs([Publishers, Series, Comics]);

// Create apollo server and connect db
const apolloServer = new ApolloServer({ typeDefs, resolvers });
export const config = {
    api: {
        bodyParser: false,
    },
};
const server = apolloServer.createHandler({ path: "/api/graphql" });
export default connectDb(server);
 * Code copied from Official Next.js documentation to work with Apollo.js
 * https://github.com/vercel/next.js/blob/6e77c071c7285ebe9998b56dbc1c76aaf67b6d2f/examples/with-apollo/lib/apollo.js
 */

import React, { useMemo } from "react";
import Head from "next/head";
import { ApolloProvider } from "@apollo/react-hooks";
import { ApolloClient } from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
import { HttpLink } from "apollo-link-http";
import fetch from "isomorphic-unfetch";

let apolloClient = null;

/**
 * Creates and provides the apolloContext
 * to a next.js PageTree. Use it by wrapping
 * your PageComponent via HOC pattern.
 * @param {Function|Class} PageComponent
 * @param {Object} [config]
 * @param {Boolean} [config.ssr=true]
 */
export function withApollo(PageComponent, { ssr = true } = {}) {
    const WithApollo = ({ apolloClient, apolloState, ...pageProps }) => {
        const client = useMemo(() => apolloClient || initApolloClient(apolloState), []);
        return (
            <ApolloProvider client={client}>
                <PageComponent {...pageProps} />
            </ApolloProvider>
        );
    };

    // Set the correct displayName in development
    if (process.env.NODE_ENV !== "production") {
        const displayName = PageComponent.displayName || PageComponent.name || "Component";

        if (displayName === "App") {
            console.warn("This withApollo HOC only works with PageComponents.");
        }

        WithApollo.displayName = `withApollo(${displayName})`;
    }

    if (ssr || PageComponent.getInitialProps) {
        WithApollo.getInitialProps = async (ctx) => {
            const { AppTree } = ctx;

            // Initialize ApolloClient, add it to the ctx object so
            // we can use it in `PageComponent.getInitialProp`.
            const apolloClient = (ctx.apolloClient = initApolloClient());

            // Run wrapped getInitialProps methods
            let pageProps = {};
            if (PageComponent.getInitialProps) {
                pageProps = await PageComponent.getInitialProps(ctx);
            }

            // Only on the server:
            if (typeof window === "undefined") {
                // When redirecting, the response is finished.
                // No point in continuing to render
                if (ctx.res && ctx.res.finished) {
                    return pageProps;
                }

                // Only if ssr is enabled
                if (ssr) {
                    try {
                        // Run all GraphQL queries
                        const { getDataFromTree } = await import("@apollo/react-ssr");
                        await getDataFromTree(
                            <AppTree
                                pageProps={{
                                    ...pageProps,
                                    apolloClient,
                                }}
                            />
                        );
                    } catch (error) {
                        // Prevent Apollo Client GraphQL errors from crashing SSR.
                        // Handle them in components via the data.error prop:
                        // https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-query-data-error
                        console.error("Error while running `getDataFromTree`", error);
                    }

                    // getDataFromTree does not call componentWillUnmount
                    // head side effect therefore need to be cleared manually
                    Head.rewind();
                }
            }

            // Extract query data from the Apollo store
            const apolloState = apolloClient.cache.extract();

            return {
                ...pageProps,
                apolloState,
            };
        };
    }

    return WithApollo;
}

/**
 * Always creates a new apollo client on the server
 * Creates or reuses apollo client in the browser.
 * @param  {Object} initialState
 */
function initApolloClient(initialState) {
    // Make sure to create a new client for every server-side request so that data
    // isn't shared between connections (which would be bad)
    if (typeof window === "undefined") {
        return createApolloClient(initialState);
    }

    // Reuse client on the client-side
    if (!apolloClient) {
        apolloClient = createApolloClient(initialState);
    }

    return apolloClient;
}

/**
 * Creates and configures the ApolloClient
 * @param  {Object} [initialState={}]
 */
function createApolloClient(initialState = {}) {
    // Check out https://github.com/zeit/next.js/pull/4611 if you want to use the AWSAppSyncClient
    return new ApolloClient({
        ssrMode: typeof window === "undefined", // Disables forceFetch on the server (so queries are only run once)
        link: new HttpLink({
            uri: "http://localhost:3000/api/graphql", // Server URL (must be absolute)
            credentials: "same-origin", // Additional fetch() options like `credentials` or `headers`
            fetch,
        }),
        cache: new InMemoryCache().restore(initialState),
    });
}
这是我从Vercel文档中使用的apollo/next.js代码:

type Series {
    _id: ID!
    name: String
    altID: String
    publisher: Publisher!
    comics: [Comic]
}

input SeriesInput {
    _id: ID
    name: String!
    altID: String
    publisher: Publisher!
    comics: [Comic]
}

type Mutation {
    addSeries(series: SeriesInput): Series
}

type Query {
    series: [Series]
}

-------------------------

type Publisher {
    _id: ID!
    name: String
    altID: String
    series: [Series]
}

input PublisherInput {
    _id: ID!
    name: String!
    altID: String
    series: [Series]
}

type Mutation {
    addPublisher(publisher: PublisherInput): Publisher
}

type Query {
    publishers: [Publisher]
}

import { ApolloServer } from "apollo-server-micro";
import { mergeResolvers, mergeTypeDefs } from "graphql-tools";
import connectDb from "../../lib/mongoose";

// Mutations and resolvers
import { comicsResolvers } from "../../api/comics/resolvers";
import { comicsMutations } from "../../api/comics/mutations";
import { seriesResolvers } from "../../api/series/resolvers";
import { seriesMutations } from "../../api/series/mutations";
import { publishersResolvers } from "../../api/publishers/resolvers";
import { publishersMutations } from "../../api/publishers/mutations";

// GraphQL Schema
import Publishers from "../../api/publishers/Publishers.graphql";
import Series from "../../api/series/Series.graphql";
import Comics from "../../api/comics/Comics.graphql";

// Merge type resolvers, mutations, and type definitions
const resolvers = mergeResolvers([
    publishersMutations,
    publishersResolvers,
    seriesMutations,
    seriesResolvers,
    comicsMutations,
    comicsResolvers,
]);
const typeDefs = mergeTypeDefs([Publishers, Series, Comics]);

// Create apollo server and connect db
const apolloServer = new ApolloServer({ typeDefs, resolvers });
export const config = {
    api: {
        bodyParser: false,
    },
};
const server = apolloServer.createHandler({ path: "/api/graphql" });
export default connectDb(server);
 * Code copied from Official Next.js documentation to work with Apollo.js
 * https://github.com/vercel/next.js/blob/6e77c071c7285ebe9998b56dbc1c76aaf67b6d2f/examples/with-apollo/lib/apollo.js
 */

import React, { useMemo } from "react";
import Head from "next/head";
import { ApolloProvider } from "@apollo/react-hooks";
import { ApolloClient } from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
import { HttpLink } from "apollo-link-http";
import fetch from "isomorphic-unfetch";

let apolloClient = null;

/**
 * Creates and provides the apolloContext
 * to a next.js PageTree. Use it by wrapping
 * your PageComponent via HOC pattern.
 * @param {Function|Class} PageComponent
 * @param {Object} [config]
 * @param {Boolean} [config.ssr=true]
 */
export function withApollo(PageComponent, { ssr = true } = {}) {
    const WithApollo = ({ apolloClient, apolloState, ...pageProps }) => {
        const client = useMemo(() => apolloClient || initApolloClient(apolloState), []);
        return (
            <ApolloProvider client={client}>
                <PageComponent {...pageProps} />
            </ApolloProvider>
        );
    };

    // Set the correct displayName in development
    if (process.env.NODE_ENV !== "production") {
        const displayName = PageComponent.displayName || PageComponent.name || "Component";

        if (displayName === "App") {
            console.warn("This withApollo HOC only works with PageComponents.");
        }

        WithApollo.displayName = `withApollo(${displayName})`;
    }

    if (ssr || PageComponent.getInitialProps) {
        WithApollo.getInitialProps = async (ctx) => {
            const { AppTree } = ctx;

            // Initialize ApolloClient, add it to the ctx object so
            // we can use it in `PageComponent.getInitialProp`.
            const apolloClient = (ctx.apolloClient = initApolloClient());

            // Run wrapped getInitialProps methods
            let pageProps = {};
            if (PageComponent.getInitialProps) {
                pageProps = await PageComponent.getInitialProps(ctx);
            }

            // Only on the server:
            if (typeof window === "undefined") {
                // When redirecting, the response is finished.
                // No point in continuing to render
                if (ctx.res && ctx.res.finished) {
                    return pageProps;
                }

                // Only if ssr is enabled
                if (ssr) {
                    try {
                        // Run all GraphQL queries
                        const { getDataFromTree } = await import("@apollo/react-ssr");
                        await getDataFromTree(
                            <AppTree
                                pageProps={{
                                    ...pageProps,
                                    apolloClient,
                                }}
                            />
                        );
                    } catch (error) {
                        // Prevent Apollo Client GraphQL errors from crashing SSR.
                        // Handle them in components via the data.error prop:
                        // https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-query-data-error
                        console.error("Error while running `getDataFromTree`", error);
                    }

                    // getDataFromTree does not call componentWillUnmount
                    // head side effect therefore need to be cleared manually
                    Head.rewind();
                }
            }

            // Extract query data from the Apollo store
            const apolloState = apolloClient.cache.extract();

            return {
                ...pageProps,
                apolloState,
            };
        };
    }

    return WithApollo;
}

/**
 * Always creates a new apollo client on the server
 * Creates or reuses apollo client in the browser.
 * @param  {Object} initialState
 */
function initApolloClient(initialState) {
    // Make sure to create a new client for every server-side request so that data
    // isn't shared between connections (which would be bad)
    if (typeof window === "undefined") {
        return createApolloClient(initialState);
    }

    // Reuse client on the client-side
    if (!apolloClient) {
        apolloClient = createApolloClient(initialState);
    }

    return apolloClient;
}

/**
 * Creates and configures the ApolloClient
 * @param  {Object} [initialState={}]
 */
function createApolloClient(initialState = {}) {
    // Check out https://github.com/zeit/next.js/pull/4611 if you want to use the AWSAppSyncClient
    return new ApolloClient({
        ssrMode: typeof window === "undefined", // Disables forceFetch on the server (so queries are only run once)
        link: new HttpLink({
            uri: "http://localhost:3000/api/graphql", // Server URL (must be absolute)
            credentials: "same-origin", // Additional fetch() options like `credentials` or `headers`
            fetch,
        }),
        cache: new InMemoryCache().restore(initialState),
    });
}
*从官方Next.js文档复制的代码,用于Apollo.js
* https://github.com/vercel/next.js/blob/6e77c071c7285ebe9998b56dbc1c76aaf67b6d2f/examples/with-apollo/lib/apollo.js
*/
从“React”导入React,{usemo};
从“下一个/Head”导入Head;
从“@apollo/react hooks”导入{apollo provider}”;
从“apollo客户端”导入{apollo客户端};
从“apollo缓存inmemory”导入{InMemoryCache};
从“阿波罗链接http”导入{HttpLink};
从“同构取消蚀刻”导入提取;
让客户端=null;
/**
*创建并提供上下文
*转到下一个.js页面树。用包装的方式使用
*通过HOC模式创建页面组件。
*@param{Function | Class}PageComponent
*@param{Object}[config]
*@param{Boolean}[config.ssr=true]
*/
使用Apollo导出函数(PageComponent,{ssr=true}={}){
const with Apollo=({apolloClient,apolloState,…pageProps})=>{
const client=useMemo(()=>apolloClient | | initApolloClient(apolloState),[]);
返回(
);
};
//在开发中设置正确的displayName
if(process.env.NODE_env!=“生产”){
const displayName=PageComponent.displayName | | | PageComponent.name | | |“Component”;
如果(displayName==“应用程序”){
console.warn(“此withApollo HOC仅适用于PageComponents”);
}
WithApollo.displayName=`WithApollo(${displayName})`;
}
if(ssr | | PageComponent.getInitialProps){
WithApollo.getInitialProps=async(ctx)=>{
const{AppTree}=ctx;
//初始化Apollo客户端,将其添加到ctx对象,以便
//我们可以在“PageComponent.getInitialProp”中使用它。
const apolloClient=(ctx.apolloClient=initApolloClient());
//运行包装的getInitialProps方法
让pageProps={};
if(PageComponent.getInitialProps){
pageProps=等待PageComponent.getInitialProps(ctx);
}
//仅在服务器上:
如果(窗口类型==“未定义”){
//重定向时,响应完成。
//继续渲染没有意义
如果(ctx.res&&ctx.res.finished){
返回页面道具;
}
//仅当启用ssr时
if(ssr){
试一试{
//运行所有GraphQL查询
const{getDataFromTree}=wait import(“@apollo/react ssr”);
等待getDataFromTree(
);
}捕获(错误){
//防止Apollo客户端GraphQL错误导致SSR崩溃。
//通过data.error prop在组件中处理它们:
// https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-查询数据错误
console.error(“运行`getDataFromTree`'时出错,错误”);
}
//getDataFromTree不调用componentWillUnmount
//因此,需要手动清除头部副作用
头。倒带();
}
}
//从Apollo存储中提取查询数据
const apolloState=apolloClient.cache.extract();
返回{
…页面道具,
阿波罗州,
};
};
}
与阿波罗一起返回;
}
/**
*始终在服务器上创建新的apollo客户端
*在浏览器中创建或重用apollo客户端。
*@param{Object}initialState
*/
函数初始化客户端(initialState){
//确保为每个服务器端请求创建一个新的客户端,以便
//未在连接之间共享(这将很糟糕)
如果(窗口类型==“未定义”){
返回客户端(初始状态);
}
//在客户端重用客户端
如果(!客户端){
apolloClient=createApolloClient(初始状态);
}
返回客户;
}
/**
*创建和配置客户端
*@param{Object}[initialState={}]
*/
函数createApollopClient(initialState={}){
//退房https://github.com/zeit/next.js/pull/4611 如果要使用AWSAPSyncClient
返回新客户端({
ssrMode:typeof window==“undefined”//在服务器上禁用forceFetch(因此查询只运行一次)
链接:新的HttpLink({
uri:“http://localhost:3000/api/graphql“,//服务器URL(必须是绝对的)
凭据:“同一来源”//附加的fetch()选项,如'credentials'或'headers'`
取来
}),
缓存:新建InMemoryCache().restore(初始状态),