在 nextJS 上配置 apollo 客户端以进行订阅的问题

Posted

技术标签:

【中文标题】在 nextJS 上配置 apollo 客户端以进行订阅的问题【英文标题】:Issue configuring apollo client on nextJS for subscriptions 【发布时间】:2020-01-26 05:57:02 【问题描述】:

所以,Apollo 客户端用于进行 GraphQL 查询和变异调用,但是当我配置 websocket Link 时,我在浏览器上收到错误:Error: ws does not work in the browser. Browser clients must use the native WebSocket object

我确实尝试过关注这篇文章,但没有成功 -> https://github.com/apollographql/subscriptions-transport-ws/issues/333

    const isBrowser = typeof window !== 'undefined';

    const authLink = setContext((_,  headers ) => 
        const token = getToken();
        console.log('Token', token);
        // return the headers to the context so httpLink can read them
        return 
            headers: 
                ...headers,
                authorization: token ? `Bearer $token` : "",
            
        
    );

    const wsLink =  isBrowser ? new WebSocketLink(
        uri: 'ws://127.0.0.1:8080/v1/graphql',
        options: 
            lazy: true,
            reconnect: true,
            connectionParams: () => 
                const token = getToken();
                return headers: Authorization: `Bearer $token`
            
        ,
        webSocketImpl: ws
    ): null;

    const terminatingLink = isBrowser ? split(
        ( query ) => 
            const  kind, operation  = getMainDefinition(query);
            return kind === "OperationDefinition" && operation === "subscription";
        ,
        wsLink,
        authLink.concat(httpLink)
    ): authLink.concat(httpLink);
    const link = ApolloLink.from([reportErrors, terminatingLink]);

    return new ApolloClient(
        connectToDevTools: isBrowser,
        s-s-rMode: !isBrowser, // Disables forceFetch on the server (so queries are only run once)
        link: link,
        cache: new InMemoryCache().restore(initialState || )
    );

【问题讨论】:

你看到 nextjs 的 apollo 例子了吗? github.com/zeit/next.js/tree/canary/examples/with-apollo 您设法解决了这个问题吗?我目前正在处理同样的问题。 【参考方案1】:

它对我来说很好用。之前的 apollo 版本可以查看@xiao's package

import nextWithApollo from "next-with-apollo";
import 
  ApolloProvider,
  ApolloClient,
  ApolloLink,
  HttpLink,
  split,
 from "@apollo/client";
import  getDataFromTree  from "@apollo/client/react/s-s-r";
import  getMainDefinition  from "@apollo/client/utilities";
import  InMemoryCache  from "@apollo/client/cache";
import  WebSocketLink  from "@apollo/link-ws";
import fetch from "isomorphic-unfetch";

export const withApollo = (
  component: Parameters<ReturnType<typeof nextWithApollo>>[0]
): ReturnType<ReturnType<typeof nextWithApollo>> => 
  const wsUrl = `ws://localhost:8000/graphql`;
  const httpUrl = `http://localhost:8000/graphql`;
  if (!httpUrl) 
    throw new Error(
      "either url or httpUrl must be provided to make an apollo connection"
    );
  

  const s-s-rMode = !process.browser;

  const httpLink: ApolloLink = new HttpLink(
    uri: httpUrl,
    credentials: "same-origin",
    fetch,
  );
  let link = httpLink;
  if (!s-s-rMode && wsUrl) 
    const wsLink = new WebSocketLink(
      uri: wsUrl,
      options: 
        reconnect: true,
      ,
      webSocketImpl: WebSocket,
    );
    link = split(
      ( query ) => 
        const def = getMainDefinition(query);
        return (
          def.kind === "OperationDefinition" && def.operation === "subscription"
        );
      ,
      wsLink,
      httpLink
    );
  

  return nextWithApollo(
    ( initialState ) => 
      return new ApolloClient(
        link,
        s-s-rMode,
        connectToDevTools: !s-s-rMode,
        cache: new InMemoryCache().restore((initialState as any) || ),
      );
    ,
    
      render: ( Page, props ) => (
        <ApolloProvider client=props.apollo>
          <Page ...props />
        </ApolloProvider>
      ),
    
  )(component,  getDataFromTree );
;

【讨论】:

【参考方案2】:

我也遇到了同样的问题,并发了package 来解决它。它支持启用 s-s-r 的查询/变异/订阅。

【讨论】:

以上是关于在 nextJS 上配置 apollo 客户端以进行订阅的问题的主要内容,如果未能解决你的问题,请参考以下文章

作为道具传递与提取缓存 Apollo 客户端 Nextjs

如何在客户端 NextJS 中使用 Apollo GraphQL 订阅?

使用 Apollo 客户端在 nextJs 中传递授权标头的最佳方法? ReferenceError: localStorage 未定义

NextJS + Apollo:如何在 getServerSideProps 内的 apolloClient.query 上获取多个查询?

NextJS/Typescript/Apollo 错误;类型上不存在属性

Apollo 客户端未在 Nextjs Lamda 中发送 JWT 不记名令牌