2
votes

So, the Apollo client works for making GraphQL query and mutation calls but when i configure websocket Link, i get error on the browser: Error: ws does not work in the browser. Browser clients must use the native WebSocket object.

I did try following this article but no success -> 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,
        ssrMode: !isBrowser, // Disables forceFetch on the server (so queries are only run once)
        link: link,
        cache: new InMemoryCache().restore(initialState || {})
    });
}
2
Did you see the nextjs example of apollo? github.com/zeit/next.js/tree/canary/examples/with-apolloAfsanefda
Did you manage to resolve this issue? I'm currently dealing with the same issue.TheoG

2 Answers

1
votes

I have encountered the same issue and made a package to solve it. It supports query/mutation/subscription with SSR enabled.

0
votes

It works fine for me. For previous apollo versions, you can check @xiao's package

import nextWithApollo from "next-with-apollo";
import {
  ApolloProvider,
  ApolloClient,
  ApolloLink,
  HttpLink,
  split,
} from "@apollo/client";
import { getDataFromTree } from "@apollo/client/react/ssr";
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 ssrMode = !process.browser;

  const httpLink: ApolloLink = new HttpLink({
    uri: httpUrl,
    credentials: "same-origin",
    fetch,
  });
  let link = httpLink;
  if (!ssrMode && 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,
        ssrMode,
        connectToDevTools: !ssrMode,
        cache: new InMemoryCache().restore((initialState as any) || {}),
      });
    },
    {
      render: ({ Page, props }) => (
        <ApolloProvider client={props.apollo}>
          <Page {...props} />
        </ApolloProvider>
      ),
    }
  )(component, { getDataFromTree });
};