apollographql / apollo-client-nextjs

Apollo Client support for the Next.js App Router
https://www.npmjs.com/package/@apollo/experimental-nextjs-app-support
MIT License
402 stars 30 forks source link

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

Open BarrelRider opened 1 month ago

BarrelRider commented 1 month ago

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 commented 1 month ago

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:

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 commented 1 week ago

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 commented 1 week ago

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

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 commented 1 week ago

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