Skip to content
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

Difference between "apollo-client-nextjs" and pure "apollo-client" #306

Open
BarrelRider opened this issue Jun 2, 2024 · 4 comments
Open

Comments

@BarrelRider
Copy link

Since there was no "discussion" section in repository, I wanted to open this topic to fill the gaps in my mind.

You see, I'm able to send query to my graphQL server like this

import { getClient } from "./ApolloClientRSC"
export default async function Home() {
const { data: projectsData } = await getClient().query({query: FETCH_PROJECTS})
}

I'm using "apollo-client-nextjs" above. But, I can even send my queries by using plain "apollo-client" in my RSC like below.

import client from "./ApolloClient"
export default async function Home() {
const { data: skillsData } = await client.query({query: FETCH_SKILLS})
const { data: projectsData } = await client.query({query: FETCH_PROJECTS})
}

This one, I'm not using "apollo-client-nextjs". Why should I use "apollo-client-nextjs" if I'm able to do it in plain "apollo-client" ?

What is the difference between "apollo-client-nextjs" and plain "apollo-client" at all ?

Thanks

@phryneas
Copy link
Member

phryneas commented Jun 3, 2024

These two will behave very differently.

Your hand-written one will create one instance of ApolloClient that will be shared between all incoming requests and users. There are a few problems with that:

  • sensitive data might leak between users
  • the cache will never be emptied
    • it will grow forever and never free memory (you're in for a memory leak here!)
    • data might get very outdated

Generally, for all SSR purposes, we recommend to create a new instance of ApolloClient. That's what registerApolloClient and getClient do: every request will get a new instance of ApolloClient, and calling getClient multiple times during one request will give you the same instance every time.

Note that in RSC, you cannot create an ApolloClient instance in a component, hold it in state and pass it down in a provider manually, as in RSC neither state nor context exist.

Giving registerApolloClient also gives you the added benefit of PrefetchQuery - using RSC for fetching data and hydrating it in Client Components.

@kunalvirk
Copy link

Hey @phryneas,

I am using the same with WPGraphQL as my backend and the auth uses refreshToken. I have setup the apollo-client-next.js alongwith apollo-client.
The token rotation and session management is not working as it should as in the tokens go out-of-sync quite often and hence a query:

Do I need to write two separate apollo setups i.e. one with NextSSRApolloClient wrapping the root layout and the other one using registerApolloClient?

Your hand-written one will create one instance of ApolloClient that will be shared between all incoming requests and users. There are a few problems with that:

What if I do wanna share a single instance to make sure they all have the same session token (needed for cart sync)?

Basically, the goal is to make apollo instance have the updated session token.

Thanks,
KV

@phryneas
Copy link
Member

@kunalvirk Your code will run in three different places, probably at different times:

  • registerApolloClient will run on the server when rendering your React Server Components each time the user navigates within your application
  • ApolloNextAppProvider will run on (potentially, a different) server after a user opened the page in their browser
  • ApolloNextAppProvider will run in the users's browser

Unfortunately, by the nature of Next.js, token handling will be different in those three cases and you cannot share anything authentication-related between them - they run on different machines, at different times. There is technically no way to share any instance between them.

I hope this info gives you a bit of a direction so you can find out in which of those situations, your token is not being refreshed as a starting point.

@kunalvirk
Copy link

I don't know if it makes sense but for this only nature of Next.js app router, I used redis for storing refresh tokens and every time a request starts to progress I reference it to the cache and set the cookie from auth link. This sometime result in different session tokens but more or less this works.

I have started to miss page router.

Thanks @phryneas

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants