1

I was planning to upgrade to nextJS 13 with app router. But I'm not able to make apollo client work with the latest version. Creating a single cache for server components will leads to data leaks as apollo was designed with single user in mind. I found an experimental library(https://github.com/apollographql/apollo-client-nextjs) but I'm not confident enough to use an experimental lib in my project

To prevent data leaks I could create a new in memoryCache if i'm on server every time. But I'm not able to make it work as well.

const getClient = ()=>{
    if(!client || typeof window==="undefined"){
        client = new ApolloClient({
            link:new HttpLink({
                uri:"https://graph.staging.strollby.com/graphql",
            }),
            cache: new InMemoryCache(),
        });
    }
    return client
}

https://github.com/apollographql/apollo-client-nextjs, this library seems the right solution, but unfortunately.

This package is experimental. Generally it should work well, you might run into race conditions when your Client Component is still rendering in SSR, and already making overlapping queries on the browser. This cannot be addressed from our side, but would need API changes in Next.js or React itself. If you do not use suspense in your application, this will not be a problem to you.

Ajith
  • 45
  • 1
  • 7

1 Answers1

0

As you can read in that warning message, those potential race conditions are the only problem, and they are a Next.js problem, not a problem with the experimental library itself.

I might add: they are extremely rare - they would require a very long SSR run while a part of your application already started browser-side and fetches "newer" data through user interaction (e.g. the user deletes something in the browser while the server still renders with that item in the cache).

You can read more about this in this (slightly outdated) document: RFC for the Apollo Next.js story.

If you want to only do RSC, and never fetch anything with suspense in client components, that is even completely eliminated, as that warning applies to React's "streaming SSR" only, where the browser already starts running while the server is still doing SSR.

All that said: this is a shortcoming of Next (transporting values over too late) and you will encounter that with any client-side fetching library you might use for suspense in client components, until Next gets a better primitive in place. There is no way anyone could implement something better in userland, unless they were to fix Next.js itself. So as long as you plan to use the App Router, that library is your best choice.

It's probably more stable than the App Router itself, me as an author of that library and Vercel just have different opinions on what to call "stable".

phry
  • 35,762
  • 5
  • 67
  • 81
  • Thank you for your response. As mentioned in the question I did tried to implement the client by recreating the cache when calling from server. I'm able to make queries right right now. What are the drawbacks of using the client in this manner? – Ajith Aug 03 '23 at 08:46
  • Your server runs for a very long time, and potentially handles hundreds of requests at the same time. I don't see anything in your code that would prevent all these requests to work with the same cache. They all will share variables. – phry Aug 03 '23 at 08:51
  • Again, that library might be marked as "experimental", but nothing you can do as an end user will be any less experimental. The problem lies within Next.js – phry Aug 03 '23 at 08:53
  • ```let client:ApolloClient | null = null; const getClient = ()=>{` if(!client || typeof window==="undefined"){ // create new client } return client}``` New client will be created on each call to getClient if I'm on server, otherwise same client will be given back. This was my logic to implement this. – Ajith Aug 03 '23 at 08:55
  • Oh, sorry, misread that - but then you create too many clients. What if you call `getClient()` in two components during the same render? You throw away any benefit of the cache. – phry Aug 03 '23 at 08:59
  • Seriously: if you are uncertain, read the code, but take it from the author of that library: 1-2 months of work including cooperation with the React and Next.js team went into that library. Experimental or not - it's the best that's possible, and "I don't want to use something experimental" is not a good reason to roll your own implementation instead. In that case, the only takeaway could be not to use the App Router :/ – phry Aug 03 '23 at 09:01
  • Like... the main point of that library is to move data over safely from SSR to the browser. (This means Client Components!). If you go with your current approach, in Client Components requests will be made by the server, but the results will either not render out (using `useQuery`) or be rendered out (`useSuspenseQuery`), but not rehydrated on the client. You either make a ton of unneccesary requests, or you will get a rehydration mismatch on every first page load. – phry Aug 03 '23 at 09:15