question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Initial Server Side Rendering Fails, Tries To Make Request to Current Server

See original GitHub issue

Intended outcome:

I’m building a NextJS app that uses apollo-client to fetch data during Server-side rendering, with credentials included.

Actual outcome:

Any time I try to include CORS credentials to include cookies, the initial request will fail on the server side.

On initial load, you see that several components start in the “loading” state, even though they’re supposed to be rendered server-side. They do eventually populate on the client, but in my logs I’m getting this error:

[Network error]: SyntaxError: Unexpected token N in JSON at position 0

Which I know means that I’m getting HTML or an error back when apollo-client expects JSON.

But the reason this is happening is because it looks like apollo-client is trying to make a request to the same server that I’m doing SSR on, not the endpoint that I’ve specified in my config:

at=info method=POST path="/" host=advanced-react-frontend.herokuapp.com request_id=d406a7fe-4fc4-4dc0-89fd-9ab9076b1608 fwd="71.78.33.134,54.147.22.164" dyno=web.1 connect=0ms service=4ms status=501 bytes=123 protocol=https

Here’s a snippet of my config as well:

https://github.com/mattfwood/next-apollo-issue/blob/master/lib/withData.js

 return new ApolloClient({
    uri: 'https://advanced-react-backend.herokuapp.com',
    request: operation => {
      operation.setContext({
        fetchOptions: {
          credentials: 'include',
        },
        headers,
      });
    },
});

How to reproduce the issue:

Here’s a live demo of the issue: https://advanced-react-frontend.herokuapp.com/

And here’s the repo: https://github.com/mattfwood/next-apollo-issue

I’ve been trying to fix this for more than 10 hours. Here are the things I’ve identified and that made it so difficult to debug:

  • This only happens when my frontend and backend are both on real servers. When I run my frontend locally, it always successfully queries my (local) server while doing server-side rendering.
  • This made me think that it might’ve been a CORS issue, but I’ve triple checked and I am getting no request to my backend server before the page initially renders. The issue is because apollo-client is trying to query the current server (my NextJS server) first, which doesn’t have a route for a POST to /, so it returns a 501. In fact, if I use apollo-link-error to force Apollo to throw an error if a query fails, I get absolute no requests logged on my server.
  • If I turn CORS completely off on both my frontend and backend, it works as intended. But obviously since I’m trying to use cookies to store user session, this isn’t an option.
  • I’ve also tried copying this example apollo config exactly, and it still has the same issues.

Any help would be greatly appreciated. The entire apollo library is incredibly well-designed and I’ve been trying to dig into the source code to figure out why this might happen, but so far I haven’t had any luck.

Versions

System: OS: macOS 10.14.1 Binaries: Node: 11.1.0 - /usr/local/bin/node Yarn: 1.12.1 - /usr/local/bin/yarn npm: 6.4.1 - /usr/local/bin/npm Browsers: Chrome: 70.0.3538.110 Safari: 12.0.1 npmPackages: apollo-boost: ^0.1.16 => 0.1.22 apollo-client: ^2.4.2 => 2.4.7 next-with-apollo: ^3.1.3 => 3.3.0 react-apollo: ^2.2.1 => 2.3.2

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:17

github_iconTop GitHub Comments

18reactions
dggodfreycommented, Dec 19, 2018

@mattfwood I have been having this exact same problem (I am also building a nextjs app with SSR and apollo-client and when it is deployed it doesn’t work). Even with JWT auth. I have looked through your code to try and help my problem, but then I realized something that we both overlooked!

You are right, this part is the problem.

request: operation => {
      operation.setContext({
        fetchOptions: {
          credentials: 'include',
        },
        headers,
      });
    },

More specifically the problem is headers. I, like you, have function createClient({ headers }) {***code that returns the apollo client***}. The headers are then set in the request method when the apollo client is run. If you console.log out headers and watch logs on the deployed app, you get back a big long object. One of them being host: 'your-front-end-host.com'. The request setContext overwrites the host of your back-end graphql uri you set earlier. Essentially, you end up replacing your graphql endpoint with your front-end app endpoint. It took me forever to find it because I wasn’t even thinking about ES6 and how it makes headers, into headers: headers. Not a problem on localhost because the host would be the same. So, my app works now that I am only pulling out of headers what I need instead of replacing it entirely. For example, this is what I have now:

request: operation => {
      operation.setContext({
        fetchOptions: {
          credentials: 'include',
        },
        headers: {
           cookie: headers && headers.cookie // NOTE: client-side headers is undefined!
        },
      });
    },

Anyway, I have been banging my head and had the exact same problem as you. Figured I would share a little bit of what I learned in hopes it will help you with your application! Good luck!

4reactions
Stenbaekcommented, May 1, 2019

After some research, I think I found a solution. It all comes down to how the browser handles 3rd party cookies. Apps cannot set cookies for *.herokuapp.com… Read more here: https://devcenter.heroku.com/articles/cookies-and-herokuapp-com

When I set up my backend on backend.mydomain.com, and the frontend on the same domain (eg. staging.mydomain.com), it works flawlessly, while still using

headers: { cookie: headers && headers.cookie },

as suggested by @dggodfrey:

Read more comments on GitHub >

github_iconTop Results From Across the Web

Error when I make a server-side rendering - Stack Overflow
This usually happens when the component that you are using has asynchronous code that is not running on the server.
Read more >
Server-side rendering - Apollo GraphQL Docs
Server -side rendering (SSR) is a performance optimization for modern web apps. It enables you to render your app's initial state to raw...
Read more >
How to Enable Server-Side Rendering for a React App
In this tutorial, you will initialize a React app using Create React App and then modify the project to enable server-side rendering.
Read more >
Server-side rendering: how to serve authenticated content
The answer is server-side rendering. This is the practice of running the front-end view logic on the server so that it can render...
Read more >
Tag: Server-side Rendering - somewhat abstract
As you may recall, for hydration to work properly, the initial render cycle of our React app on both the server and client...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found