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

[Next.js] When to do cache.extract() and include it in the HTML doc with Suspense SSR? #11383

Closed
jackyef opened this issue Nov 24, 2023 · 9 comments

Comments

@jackyef
Copy link

jackyef commented Nov 24, 2023

I have read some issues regarding React 18 + Apollo Client 3.8 Suspense SSR support, in particular:

In non-Suspense world, we previously would await getDataFromTree() and call cache.extract() after it.

Now that we are in Suspense world, is there a way to know when all the queries has been resolved, but before the HTML document has been sent to the browser in Next.js? How do we sent the serialized cache of SSR-resolved-suspense-queries to the browser?

The RFC mentioned this

@/benjamn has proposed an interesting idea of potentially transmitting the whole query results produced via SSR rather than normalized cache results that would need to be serialized. Queries might then be able to use these query results immediately which would then make their way into the cache. This is something we should consider via an ApolloLink.

but I am not sure if any further development has surfaced since the 3.8 release.

@phryneas
Copy link
Member

It did, in the form of https://github.com/apollographql/apollo-client-nextjs

I wrote a bit on it over in #11319 (comment)

TLDR: React does not provide us with the necessary primitives to support streaming SSR, so we have to rely on framework-specific workarounds to inject data into the stream. That means that it is currently impossible to use streaming SSR in hand-written SSR solutions with any data fetching library - except if you essentially reimplement your own stream injection mechanism (like Next.js does) and fork our package using that.

I'm not sure if Suspense is possible with "traditional" SSR methods, but if that is the case, you'd do it as before - render the full application and then call getDataFromTree

@jackyef
Copy link
Author

jackyef commented Nov 27, 2023

Thanks for your reply @phryneas !

What about page router use cases though? Correct me if I am wrong, but it seems like Suspense does work with page router as well. Here's a repo to play around with it: https://github.com/jackyef/next-apollo-suspense-ssr

Are you saying for this case we should still do the getDataFromTree? Wouldn't that mean the performance will actually be worse because before React 18, we would only be doing 2-pass render, and with React 18 the SSR would happen while waiting for Suspense and then we do 2-pass render again? 🤔

@phryneas
Copy link
Member

Since between those 2-pass-renders you would be waiting for all queries to finish, and the suspense queries will be "instant" if data is already in the cache, that will come out to the same performance as before.

@jackyef
Copy link
Author

jackyef commented Nov 27, 2023

Ah, so you are essentially saying page router wouldn't be able to benefit from useSuspenseQuery then? As they would still need to rely on getDataFromTree() 2-pass-renders?

Also, does this mean the recommendation for page router is still to do getDataFromTree in the getInitialProps?

@phryneas
Copy link
Member

The benefit here is that useSuspenseQuery gives you a much nicer DX regarding loading states and error handling.

Also, does this mean the recommendation for page router is still to do getDataFromTree in the getInitialProps?

If it works, I assume so. I have to admit I haven't tried it with the page router, but I wouldn't see how things would suddenly be different. The pages router uses renderToString, and that's all that counts for how you do SSR in the end.

@jackyef
Copy link
Author

jackyef commented Nov 27, 2023

Gotcha, but in regards to SSR perf, they would still be the same.

Ah, I was wondering if the page router does streaming or not, but I wasn't able to find it in the Next.js repo, that explains a lot.

Thanks a lot for your elaborate answers!

@jerelmiller
Copy link
Member

Hey @jackyef 👋

If I'm reading this right, it looks like your question has been resolved. As such, I'm going to go ahead and close out this issue. If I've missed something or there is still something actionable here, feel free to reopen. Thanks!

Copy link
Contributor

github-actions bot commented Feb 2, 2024

Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo Client usage and allow us to serve you better.

Copy link
Contributor

github-actions bot commented Mar 4, 2024

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
For general questions, we recommend using StackOverflow or our discord server.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 4, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants