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

NextJS Server Components and Subscriptions Example #2715

Open
jovermier opened this issue May 15, 2024 · 9 comments
Open

NextJS Server Components and Subscriptions Example #2715

jovermier opened this issue May 15, 2024 · 9 comments
Assignees
Labels
enhancement New feature or request

Comments

@jovermier
Copy link

Is your feature request related to a problem? Please describe.
I have spent hundreds of hours trying to get NextJS server components and client-side subscriptions working together with authorization. Having the session work both on the backend and frontend, keeping the session alive, and keeping the server rendered user state in sync with the client-side state has been a nightmare. There are the black boxes: @nhost/apollo, @nhost/core, @nhost/nextjs, @nhost/nhost-js, @nhost/react-apollo. Keeping them all in sync and knowing which NhostClient from a particular package to use is not always obvious.

Describe the solution you'd like
Update or create a new example using all of the major features of Nhost in a single NextJS with server components project.
Features I would like to see:

  • server rendered user specific data
  • client rendered user specific query data
  • client rendered subscription user specific data (even better if you can demonstrate multiple roles being used at the same time)
  • server action mutation of data
  • log in / log out
  • ability to recover after the browser sleeps the tab
  • all above state properly synced after a user logs out & logs in, user returns to a page with an old token
@jovermier jovermier added the enhancement New feature or request label May 15, 2024
@dbarrosop
Copy link
Contributor

dbarrosop commented May 15, 2024

Hi,
you have a comprehensive example here: https://github.com/nhost/nhost/tree/main/examples/quickstarts/nextjs-server-components

There is also some SSR stuff here: https://github.com/nhost/nhost/blob/main/examples/nextjs/pages/public-ssr.tsx

Unfortunately, there are too many ways to do different things with Next.js, making it challenging to cover all in a single example. As a result, various things may be illustrated across different examples :(

Regards

@jovermier
Copy link
Author

The SSR example shows how to set the session using the pages router in nextjs but this approach I don't think is compatible with app router. The server components example using app router does not show how to configure NhostProvider nor NhostApolloProvider.

@jovermier
Copy link
Author

I created a repo based off of the nhost server components quickstart project. It is still very buggy but with the issue mentioned in the original post. It does implement SSR data fetch, CSR data fetch, and CSR subscriptions.

I had to do some hacking on the NhostSession cookie as the different nhost packages seem to expect different formats.

https://github.com/jovermier/nhost-nextjs-app-router

@dbarrosop
Copy link
Contributor

I created a repo based off of the nhost server components quickstart project.

Great, this is very cool. I will ask a colleague to take a look. Is there anything in particular you need help with here?

I had to do some hacking on the NhostSession cookie as the different nhost packages seem to expect different formats.

What do you mean? Could you point me to the inconsistencies, please? AFAICT the only valid type for the NhostSession is the one defined here

@jovermier
Copy link
Author

jovermier commented May 17, 2024

The quickstart nextjs-server-components example base64 encodes the session. I wasn't sure what the reason for that was. The @nhost/nextjs and @nhost/react packages seem to set the cookie not base64 encoded.

const initialSession: NhostSession = JSON.parse(atob(sessionCookieValue) || 'null')

I am going to continue working on the example project today to better demonstrate the challenges keeping the auth state in sync.

@jovermier
Copy link
Author

jovermier commented May 17, 2024

I also added auth state on the home page. This produces error Error: Text content does not match server-rendered HTML. This demonstrates some of the weirdness around keeping the state synced.

Logging in and out does not invalidate the cache on the client rendered components. I would have expected the @nhost/nextjs version to properly handle this.

@jovermier
Copy link
Author

Here is an example of coming back to localhost after an hour. The refresh token in the browser automatically gets a user session but hasura claims and the session are null.

Auth Sync Screenshot

@dbarrosop
Copy link
Contributor

dbarrosop commented May 23, 2024

A colleague will take a deeper look on a best-effort basis but a few comments for now:

  • The most important bit is that the SDK is designed to work on the browser. There are some bits that don't work on the server. I.e., the auto signin and the autorefresh token is probably best left disabled on the server side. Maybe providing a custom storage could make those work but I don't think those will work out of the box.
  • The base64 encoding is done as "special treatment" to be able to send the session as a cookie from the client to the server. All libraries will expect it in plain json but to simplify transport we encodein base64 prior to sending from the client to the server. Keep in mind most authentication methods will have to happen on the browser so if you need the session on the server too you will need to send it in a cookie or similar.
  • The SDK won't keep any state or similar between client and server, if you need to sync any state you need to implement this yourself. The previous point about sending the session as a cookie encoded in base64 is an example of this.

@jovermier
Copy link
Author

Your points make sense.

Can you explain why this occurs:

  1. sign in
  2. refresh homepage (notice getSession and getHasuraClaims value)
  3. sign out
  4. notice getSession is now null as expected but getHasuraClaims value still contains the previous logged in user claim
  5. refresh page
  6. notice getSession and getHasuraClaims values remain the same

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

No branches or pull requests

3 participants