-
Notifications
You must be signed in to change notification settings - Fork 27.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
example: with-apollo-subscription #10902
Comments
Found a solution without apollo using npm swr instead... |
Found this issue because I also had some initial trouble with using apolloClient.js from with-apollo example, with changes to use ws if client-side:
Is there any problem with this solution that I haven't bumped into yet? Or should something like this perhaps be included in the with-apollo example? |
Thanks a lot! @johnniehard With your hints I got it working. import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { HttpLink } from 'apollo-link-http';
import fetch from 'isomorphic-unfetch';
import { WebSocketLink } from 'apollo-link-ws';
import { SubscriptionClient } from 'subscriptions-transport-ws';
import { parseCookies } from 'nookies';
const SERVER = process.env.GRAPHQL_SERVER;
const HTTP_URI = `https://${SERVER}/v1/graphql`;
const WS_URI = `wss://${SERVER}/v1/graphql`;
const COOKIE_JWT_TOKEN = process.env.COOKIE_JWT_TOKEN;
export default function createApolloClient(initialState, ctx) {
const ssrMode = (typeof window === 'undefined');
let link, token;
if (ssrMode) {
// on Server...
token = parseCookies(ctx)[COOKIE_JWT_TOKEN]
link = new HttpLink({
uri: HTTP_URI,
credentials: 'same-origin',
headers: {
authorization: token ? `Bearer ${token}` : ''
},
fetch
});
} else {
// on Client...
token = parseCookies()[COOKIE_JWT_TOKEN]
const client = new SubscriptionClient(
WS_URI, {
reconnect: true,
connectionParams: {
headers: {
authorization: token ? `Bearer ${token}` : ''
}
}
}
);
link = new WebSocketLink(client);
}
return new ApolloClient({
ssrMode,
link,
cache: new InMemoryCache().restore(initialState)
});
} |
@tobkle what's |
yes |
@tobkle I use auth0 as auth-provider and therefore the session-cookie is This is my auth-solution without cookies: import { ApolloClient } from 'apollo-client'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { HttpLink } from 'apollo-link-http'
import { setContext } from 'apollo-link-context'
import { onError } from 'apollo-link-error'
import fetch from 'isomorphic-unfetch'
import { WebSocketLink } from 'apollo-link-ws'
import { SubscriptionClient } from 'subscriptions-transport-ws'
import { split } from 'apollo-link'
import { getMainDefinition } from 'apollo-utilities'
let accessToken = null
const requestAccessToken = async () => {
if (accessToken) return
const res = await fetch(`${process.env.DOMAIN}/api/session`)
if (res.ok) {
const json = await res.json()
accessToken = json.accessToken
} else {
accessToken = 'public'
}
}
// return the headers to the context so httpLink can read them
const authLink = setContext(async (req, { headers }) => {
await requestAccessToken()
if (!accessToken || accessToken === 'public') {
return {
headers,
}
} else {
return {
headers: {
...headers,
Authorization: `Bearer ${accessToken}`,
},
}
}
})
// remove cached token on 401 from the server
const resetTokenLink = onError(({ networkError }) => {
if (networkError && networkError.name === 'ServerError' && networkError.statusCode === 401) {
accessToken = null
}
})
const httpLink = new HttpLink({
uri: process.env.API_URL,
credentials: 'include',
fetch,
})
const createWSLink = () => {
return new WebSocketLink(
new SubscriptionClient(process.env.API_WS, {
lazy: true,
reconnect: true,
connectionParams: async () => {
await requestAccessToken()
return {
headers: {
authorization: accessToken ? `Bearer ${accessToken}` : '',
},
}
},
})
)
}
export default function createApolloClient(initialState, ctx) {
accessToken = null
const ssrMode = typeof window === 'undefined'
let link
if (ssrMode) {
link = authLink.concat(resetTokenLink).concat(httpLink)
} else {
const wsLink = createWSLink()
link = split(
({ query }) => {
const definition = getMainDefinition(query)
return definition.kind === 'OperationDefinition' && definition.operation === 'subscription'
},
resetTokenLink.concat(wsLink),
authLink.concat(resetTokenLink).concat(httpLink)
)
}
return new ApolloClient({
ssrMode,
link,
cache: new InMemoryCache().restore(initialState),
})
} |
Hi @johnniehard and @tobkle, thank you for the solution, works like a charm. I noticed that for every mutation, this current set up uses the websocket setup instead of the HTTP setup. I'm wondering if this doesn't have any performance implication on the server or the app itself. |
#Just Incase anyone needs a solution to the problem stated above. import { ApolloClient } from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
import { HttpLink } from "apollo-link-http";
import fetch from "isomorphic-unfetch";
import { WebSocketLink } from "apollo-link-ws";
import { SubscriptionClient } from "subscriptions-transport-ws";
import cookie from "js-cookie";
import { getMainDefinition } from "apollo-utilities";
import { split } from "apollo-link";
const URI = "http://localhost:4000";
const WS_URI = "ws://localhost:4000";
export default function createApolloClient(initialState, ctx) {
// console.log("in apolloCLient", ctx);
// let token;
let link, token, httpLink, wsLink;
const ssrMode = typeof window === "undefined";
token = cookie.get("token");
// console.log("in apolloCLient", token);
httpLink = new HttpLink({
uri: URI,
credentials: "same-origin",
headers: {
Authorization: token ? `Bearer ${token}` : ""
},
fetch
});
if (ssrMode) {
return new ApolloClient({
ssrMode,
link: httpLink,
cache: new InMemoryCache().restore(initialState)
});
} else {
// on Client...
const client = new SubscriptionClient(WS_URI, {
reconnect: true,
connectionParams: {
// headers: {
Authorization: token ? `Bearer ${token}` : ""
// }
}
});
wsLink = new WebSocketLink(client);
link = process.browser
? 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;
return new ApolloClient({
ssrMode,
link,
cache: new InMemoryCache().restore(initialState)
});
}
} |
For an example using Apollo client v3.0 and TypeScript, here is my version:
|
how to make apollo server for subscription in client?? |
If you're using Apollo client, you don't need an Apollo server specifically - any GraphQL server will do! There's several ways of going about this - for example, I'm using PostGraphile, which creates a GraphQL server based on a PostgreSQL DB) For more information around Apollo Server specifically, here's a good place to start: |
@david718 I'm trying to figure out the same thing. So far I've got in my /pages/api/graphql.ts: const apolloServer = new ApolloServer({
typeDefs,
resolvers,
subscriptions: {
path: '/api/graphql',
keepAlive: 9000,
onConnect: () => console.log('connected'),
onDisconnect: () => console.log('disconnected'),
}, But it seems somehow, you've got to do something with I can't really figure that out. @tobkle How did you do this? You said you used |
What is going on here?
doesn't this always return createApolloClient(initialState) as globalApolloClient is null? |
This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you. |
Feature request
A working example with a simple Apollo Client Subscription.
Is your feature request related to a problem? Please describe.
Trying to get an Apollo Client setup to work with Next.JS version 9 using the
with-apollo example
and switching between apollo-link-ws and apollo-link-http by using the http-link split option: There is a hint for such a solution in this example: subscriptions-transport-ws. However, I'm trying now for days to figure out, how this works. Having overcome all errors meanwhile, and get the useQuery to work, but the useSubscription never leaves the loading state. There was another hint here: addressing such an infinite loading state. But I don't get it working.A clear and concise description of what you want and what your use case is.
Want to use Apollo Subscriptions with Next.JS Version 9.
Describe the solution you'd like
A clear and concise description of what you want to happen.
Describe alternatives you've considered
Based on the example with-apollo, tried to do that:
./ApolloClient.js:
./pages/apollo_subscription.js:
A clear and concise description of any alternative solutions or features you've considered.
Additional context
Add any other context or screenshots about the feature request here.
The text was updated successfully, but these errors were encountered: