apollo-client: SSR stopped working in Next.js app from @apollo/client-beta.8

Intended outcome:

When following the next.js with-apollo example using @apollo/client-beta.8 or any newer client in ssrMode, we should see the loaded GraphQL data in our markup when we view the page source.

Actual outcome:

When we inspect the page source, the markup shows that our page is in a loading state.

How to reproduce the issue:

Use beta.8 or greater in the next.js with-apollo example. The last two commits in the repo included below will show the viewed source of a page including markup in a loading state when using beta.8, and returning the expected markup with GraphQL supplied data in beta.7.

https://github.com/lyonsv/with-apollo-app

A quick sample of a few versions before 7 suggest this is a regression in introduced between 7 and 8. Glancing at the commits between the two versions, there’s a lot going on and there’s nothing obvious to me that could be the cause.

The commits where the the problem occurs should be identifiable below:

https://github.com/apollographql/apollo-client/commits/ab0bbe2f5b06465c9c54de8c633e119e21881504

The problem was raised by tests that I have written in Cypress inspecting the request, and on my express server used in Next.js. Happy to contribute similar tests to prevent this regression from occurring again - it’s a hard one to spot.

Versions

System: OS: macOS 10.15.5 Binaries: Node: 14.2.0 - /usr/local/bin/node Yarn: 1.7.0 - ~/.yarn/bin/yarn npm: 6.14.4 - /usr/local/bin/npm Browsers: Chrome: 83.0.4103.97 Firefox: 65.0 Safari: 13.1.1 npmPackages: @apollo/client: 3.0.0-beta.8 => 3.0.0-beta.8

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 9
  • Comments: 21 (6 by maintainers)

Most upvoted comments

Although this issue is resolved, I seem to have used some keywords that will lead people here for reasons that are more to do with the next.js examples, than with apollo client. Summary of my knowledge below:

  1. Up until early 2020, Next.js included a complex example for how to use Apollo with SSR. It looked something like this.
  2. In migrating from Apollo client v2 -> v3, an SSR/Apollo/Next.js setup that follows the original Next.js with-apollo example could break your SSR.
  3. In order to not return loading state markup from the server, it’s now necessary to check if useQuery is returning both loading and data is undefined if (!data && loading) { return <Loading />} , before returning your component that uses loaded data. Any Apollo/client version greater than beta.23 should be fine.
  4. At this point, it looks probable that a lot of code can be deleted if you use the latest version of apollo-client v3 and SSG, which you get a sense of from the latest with-apollo example. This example would not work with apollo client v3, because it just checks if the state is loading on the server - and not if !data. It works fine if you add the !data check

Point 3 is going to catch a lot of people, as you won’t spot that SSR is broken in the browser or in your test suite, unless you test the body of the response to a request - which I’d recommend doing. I had the inelegant cypress test below in my code base, and it did the job:

describe('a ssr request visits homepage', () => {
  it('sees the hero section of the app', () => {
    cy.request(routes.home).as('homepage')
    cy.get('@homepage').should(response => {
      // home-content-desktop should be visible in loaded state
      const ssrHero = response.body.search('home-content-desktop')
      // if it was not visible, a search for the string position within body would return -1. 
      expect(ssrHero).to.not.eq(-1)
    })
  })
})

I think using apollo with nextjs was a wrong decision altogether 😦

That makes sense, thanks @jcreighton . A check for !data solves the problem using the latest release candidate.

So checking for !data before the loading check solves the issue for us as well, but it’s a bit disturbing that the semantics of “loading” have changed. I suspect this is going to cause a lot of headache for people migrating to 3.x.

@lyonsv The difference between beta.7 and beta.8 is the PostList component is receiving its data vs not (the query succeeding in index.js in both versions). That issue is resolved as of beta.23. What you’re encountering now is related to loading being set to true on the server, see https://github.com/apollographql/react-apollo/issues/3338#issuecomment-528462945 and https://github.com/apollographql/react-apollo/issues/3338#issuecomment-571854056. On this line, you’ll want to check if !data in addition to the loading states. Then you’ll see the markup as expected.

@lyonsv Thanks for the quick reply to @jcreighton’s questions! Glad this is resolved for you.

@msreekm @nodabladam @jsartisan Mind taking your discussion somewhere else?

Hi @nodabladam ,Thanks for the link. i will give it a try.

just worried that if we still get Apptree working now , timneutkens mentioned in the same thread that it may break in near future ? do you still recommend this approach?

https://github.com/vercel/next.js/discussions/11957#discussioncomment-29427