Apollo GraphQl:GraphQlwSlink(订阅)麻烦。无法让WebSocket实现与Next.js一起工作

发布于 2025-01-26 06:28:18 字数 1961 浏览 2 评论 0原文

因此,我在Go中写了一个GraphQl Server,跟随 。我将前端写为next.js应用程序,目前,我正在尝试创建一个客户端以连接到我的服务器,甚至遵循订阅文档 to t,我似乎无法使其工作。提供的示例如何不包括websocketimpl

如果我不提供websocketimpl,我会得到:

Error: WebSocket implementation missing; on Node you can `import WebSocket from 'ws';` and pass `webSocketImpl: WebSocket` to `createClient`

websocket}从“ ws”; ';

const wsLink = new GraphQLWsLink(
    createClient({
        webSocketImpl: WebSocket,
        url: "ws://localhost:8080/subscriptions",
    })
);

因此,自然而然地,i import {

error - ./node_modules/node-gyp-build/index.js:1:0
Module not found: Can't resolve 'fs'

这是完整的代码,基本上我需要的只是创建一个apolloclient并导出以在我的React代码中使用。

import { ApolloClient, HttpLink, InMemoryCache, split } from "@apollo/client";
import { GraphQLWsLink } from "@apollo/client/link/subscriptions";
import { createClient } from "graphql-ws";
import { getMainDefinition } from "@apollo/client/utilities";
import { WebSocket } from "ws";

const wsLink = new GraphQLWsLink(
    createClient({
        webSocketImpl: WebSocket,
        url: "ws://localhost:8080/subscriptions",
    })
);

const httpLink = new HttpLink({
    uri: `http://localhost:8080/query`,
});

const link = split(
    ({ query }) => {
        const def = getMainDefinition(query);
        return (
            def.kind === "OperationDefinition" && def.operation === "subscription"
        );
    },
    wsLink,
    httpLink
);

export const Client = new ApolloClient({
    link,
    cache: new InMemoryCache(),
});

我在这里完全错过了什么吗?我的安装中是否没有默认的Websocket实现?显然,“ WS”实现未切割,可能是因为fs在浏览器中不可用?

So I have a GraphQL server that I wrote in Go, following this tutorial pretty closely. I have my front-end written as a Next.js application, and I am currently trying to create a client to connect to my server and even following the subscription docs to the T, I cannot seem to get it to work. How is it that the examples provided do not include a webSocketImpl?

If I don't provide a webSocketImpl, I get this:

Error: WebSocket implementation missing; on Node you can `import WebSocket from 'ws';` and pass `webSocketImpl: WebSocket` to `createClient`

So, naturally, I import { WebSocket } from "ws"; , and have:

const wsLink = new GraphQLWsLink(
    createClient({
        webSocketImpl: WebSocket,
        url: "ws://localhost:8080/subscriptions",
    })
);

Where I then get:

error - ./node_modules/node-gyp-build/index.js:1:0
Module not found: Can't resolve 'fs'

Here is the full code, basically all I need is to create a ApolloClient and export it for use in my React code.

import { ApolloClient, HttpLink, InMemoryCache, split } from "@apollo/client";
import { GraphQLWsLink } from "@apollo/client/link/subscriptions";
import { createClient } from "graphql-ws";
import { getMainDefinition } from "@apollo/client/utilities";
import { WebSocket } from "ws";

const wsLink = new GraphQLWsLink(
    createClient({
        webSocketImpl: WebSocket,
        url: "ws://localhost:8080/subscriptions",
    })
);

const httpLink = new HttpLink({
    uri: `http://localhost:8080/query`,
});

const link = split(
    ({ query }) => {
        const def = getMainDefinition(query);
        return (
            def.kind === "OperationDefinition" && def.operation === "subscription"
        );
    },
    wsLink,
    httpLink
);

export const Client = new ApolloClient({
    link,
    cache: new InMemoryCache(),
});

Am I totally missing something here? Is there not a default WebSocket implementation in my installation? Obviously the "ws" implementation isn't cutting it, probably because fs is not available in-browser?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

蝶舞 2025-02-02 06:28:18

我在这里留下的一件事:我正在使用next.js。发生这种情况的原因是由于SSR。基本上,我们只需要使用``typeof窗口''!=='undefined'在浏览器中生成Websocket链接。这是我更新的代码:

import { ApolloClient, HttpLink, InMemoryCache, split } from "@apollo/client";
import { GraphQLWsLink } from "@apollo/client/link/subscriptions";
import { createClient } from "graphql-ws";
import { getMainDefinition } from "@apollo/client/utilities";

const wsLink =
    typeof window !== "undefined"
        ? new GraphQLWsLink(
                createClient({
                    url: "ws://localhost:8080/subscriptions",
                })
          )
        : null;

const httpLink = new HttpLink({
    uri: `http://localhost:8080/query`,
});

const link =
    typeof window !== "undefined" && wsLink != null
        ? split(
                ({ query }) => {
                    const def = getMainDefinition(query);
                    return (
                        def.kind === "OperationDefinition" &&
                        def.operation === "subscription"
                    );
                },
                wsLink,
                httpLink
          )
        : httpLink;

export const client = new ApolloClient({
    link,
    cache: new InMemoryCache(),
});

A major thing I left off here: I was using Next.js. The reason this was occurring was due to SSR. Basically, we need to only generate the WebSocket link if we are in the browser by using `typeof window !== 'undefined'. This is my updated code:

import { ApolloClient, HttpLink, InMemoryCache, split } from "@apollo/client";
import { GraphQLWsLink } from "@apollo/client/link/subscriptions";
import { createClient } from "graphql-ws";
import { getMainDefinition } from "@apollo/client/utilities";

const wsLink =
    typeof window !== "undefined"
        ? new GraphQLWsLink(
                createClient({
                    url: "ws://localhost:8080/subscriptions",
                })
          )
        : null;

const httpLink = new HttpLink({
    uri: `http://localhost:8080/query`,
});

const link =
    typeof window !== "undefined" && wsLink != null
        ? split(
                ({ query }) => {
                    const def = getMainDefinition(query);
                    return (
                        def.kind === "OperationDefinition" &&
                        def.operation === "subscription"
                    );
                },
                wsLink,
                httpLink
          )
        : httpLink;

export const client = new ApolloClient({
    link,
    cache: new InMemoryCache(),
});
丑丑阿 2025-02-02 06:28:18

我找到了一种与graphql-yoga一起使用的方式
是客户:

// import { createServer } from "@graphql-yoga/node";
import { makeExecutableSchema } from "@graphql-tools/schema";
import typeDefs from "@/server/graphql/typeDef/schema.graphql";
import resolvers from "@/server/graphql/resolvers";
import dbInit from "@/lib/dbInit";
import JWT from "jsonwebtoken";
import Cors from "micro-cors";

// const pubsub = new PubSub();
const schema = makeExecutableSchema({
  typeDefs,
  resolvers,
});

import {
  createServer,
  createPubSub,
  GraphQLYogaError,
} from "@graphql-yoga/node";
import { useResponseCache } from "@envelop/response-cache";
import { WebSocketServer } from "ws"; // yarn add ws
// import ws from 'ws'; yarn add ws@7
// const WebSocketServer = ws.Server;
import { useServer } from "graphql-ws/lib/use/ws";

const pubSub = createPubSub();

const server = createServer({
  cors: {
    credentials: "same-origin",
    origin: ["http://localhost:3000"], // your frontend url.
  },

  plugins: [
    useResponseCache({
      includeExtensionMetadata: true,
    }),
  ],
  context: async (ctx) => {
    let wsServer = null;
    wsServer = ctx.res.socket.server.ws ||= new WebSocketServer({
      port: 4000,
      path: "/api/graphql",
    });
    wsServer &&= useServer({ schema }, wsServer);

    const db = await dbInit();
    let { token, customerId, customerExpire } = ctx.req.cookies;
    // 1. Find optional visitor id
    let id = null;
    if (token) {
      try {
        let obj = JWT.verify(token, "MY_SECRET");
        id = obj.id;
      } catch (err) {
        console.error("error on apollo server", err); // expired token, invalid token
        // TODO try apollo-link-error on the client
        throw new AuthenticationError(
          "Authentication token is invalid, please log in"
        );
      }
    }

    return {
      ...ctx,
      userId: id,
      customerId,
      pubSub,
    };
  },
  schema,

});

export default server;

和客户

import { useMemo } from "react";
import {
  ApolloClient,
  InMemoryCache,
  split,
  HttpLink,
  createHttpLink,
} from "@apollo/client";
import merge from "deepmerge";
import { getMainDefinition } from "apollo-utilities";
import { GraphQLWsLink } from "@apollo/client/link/subscriptions";
import { createClient } from "graphql-ws";

// const link = process.env.SERVER_LINK;
let apolloClient;
//create websocket link
const wsLink =
  typeof window !== "undefined"
    ? new GraphQLWsLink(
        createClient({
          url: "ws://localhost:4000/api/graphql",

          on: {
            connected: () => console.log("connected client"),
            closed: () => console.log("closed"),
          },
        })
      )
    : null;


//create http link
const httplink = new HttpLink({
  uri: "http://localhost:3000/api/graphql",
  credentials: "same-origin",
});

//Split the link based on graphql operation
const link =
  typeof window !== "undefined"
    ? split(
        //only create the split in the browser
        // split based on operation type
        ({ query }) => {
          const { kind, operation } = getMainDefinition(query);
          return kind === "OperationDefinition" && operation === "subscription";
        },
        wsLink,
        httplink
      )
    : httplink;

//create apollo client
function createApolloClient() {
  return new ApolloClient({
    ssrMode: typeof window === "undefined",
    link: link,
    cache: new InMemoryCache(),
  });
}

export function initializeApollo(initialState = null) {
  const _apolloClient = apolloClient ?? createApolloClient();

  if (initialState) {
    // Get existing cache, loaded during client side data fetching
    const existingCache = _apolloClient.extract();

    // Merge the existing cache into data passed from getStaticProps/getServerSideProps
    const data = merge(initialState, existingCache);

    // Restore the cache with the merged data
    _apolloClient.cache.restore(data);
  }

  if (typeof window === "undefined") return _apolloClient;

  if (!apolloClient) apolloClient = _apolloClient;

  return _apolloClient;
}

export function useApollo(initialState) {
  const store = useMemo(() => initializeApollo(initialState), [initialState]);
  return store;
}

I found a way how it`s work with GraphQL-yoga
It's client :

// import { createServer } from "@graphql-yoga/node";
import { makeExecutableSchema } from "@graphql-tools/schema";
import typeDefs from "@/server/graphql/typeDef/schema.graphql";
import resolvers from "@/server/graphql/resolvers";
import dbInit from "@/lib/dbInit";
import JWT from "jsonwebtoken";
import Cors from "micro-cors";

// const pubsub = new PubSub();
const schema = makeExecutableSchema({
  typeDefs,
  resolvers,
});

import {
  createServer,
  createPubSub,
  GraphQLYogaError,
} from "@graphql-yoga/node";
import { useResponseCache } from "@envelop/response-cache";
import { WebSocketServer } from "ws"; // yarn add ws
// import ws from 'ws'; yarn add ws@7
// const WebSocketServer = ws.Server;
import { useServer } from "graphql-ws/lib/use/ws";

const pubSub = createPubSub();

const server = createServer({
  cors: {
    credentials: "same-origin",
    origin: ["http://localhost:3000"], // your frontend url.
  },

  plugins: [
    useResponseCache({
      includeExtensionMetadata: true,
    }),
  ],
  context: async (ctx) => {
    let wsServer = null;
    wsServer = ctx.res.socket.server.ws ||= new WebSocketServer({
      port: 4000,
      path: "/api/graphql",
    });
    wsServer &&= useServer({ schema }, wsServer);

    const db = await dbInit();
    let { token, customerId, customerExpire } = ctx.req.cookies;
    // 1. Find optional visitor id
    let id = null;
    if (token) {
      try {
        let obj = JWT.verify(token, "MY_SECRET");
        id = obj.id;
      } catch (err) {
        console.error("error on apollo server", err); // expired token, invalid token
        // TODO try apollo-link-error on the client
        throw new AuthenticationError(
          "Authentication token is invalid, please log in"
        );
      }
    }

    return {
      ...ctx,
      userId: id,
      customerId,
      pubSub,
    };
  },
  schema,

});

export default server;

And client

import { useMemo } from "react";
import {
  ApolloClient,
  InMemoryCache,
  split,
  HttpLink,
  createHttpLink,
} from "@apollo/client";
import merge from "deepmerge";
import { getMainDefinition } from "apollo-utilities";
import { GraphQLWsLink } from "@apollo/client/link/subscriptions";
import { createClient } from "graphql-ws";

// const link = process.env.SERVER_LINK;
let apolloClient;
//create websocket link
const wsLink =
  typeof window !== "undefined"
    ? new GraphQLWsLink(
        createClient({
          url: "ws://localhost:4000/api/graphql",

          on: {
            connected: () => console.log("connected client"),
            closed: () => console.log("closed"),
          },
        })
      )
    : null;


//create http link
const httplink = new HttpLink({
  uri: "http://localhost:3000/api/graphql",
  credentials: "same-origin",
});

//Split the link based on graphql operation
const link =
  typeof window !== "undefined"
    ? split(
        //only create the split in the browser
        // split based on operation type
        ({ query }) => {
          const { kind, operation } = getMainDefinition(query);
          return kind === "OperationDefinition" && operation === "subscription";
        },
        wsLink,
        httplink
      )
    : httplink;

//create apollo client
function createApolloClient() {
  return new ApolloClient({
    ssrMode: typeof window === "undefined",
    link: link,
    cache: new InMemoryCache(),
  });
}

export function initializeApollo(initialState = null) {
  const _apolloClient = apolloClient ?? createApolloClient();

  if (initialState) {
    // Get existing cache, loaded during client side data fetching
    const existingCache = _apolloClient.extract();

    // Merge the existing cache into data passed from getStaticProps/getServerSideProps
    const data = merge(initialState, existingCache);

    // Restore the cache with the merged data
    _apolloClient.cache.restore(data);
  }

  if (typeof window === "undefined") return _apolloClient;

  if (!apolloClient) apolloClient = _apolloClient;

  return _apolloClient;
}

export function useApollo(initialState) {
  const store = useMemo(() => initializeApollo(initialState), [initialState]);
  return store;
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文