We’ve been doing server-side React rendering for quite a while already. We’re changing the flow a bit, because it used to be that requests would go to Python which would then call out to Node for server side rendering. Going forward, our CDN will talk to the Node React render server directly to get complete pages.
First of all, I’ll give a shoutout to Michael Nygard for his documenting architecture decisions blog post. I didn’t have to create my own answer to the question of migrating to GraphQL. I was able to just look up the architecture decision record (from September 2017).
We saw the benefits as:
Data from GraphQL queries is typed, which can help the front-end operate more reliably on it. Our REST endpoints also have type information, but we aren’t currently exporting this information to the front-end.
GraphQL queries can collect a variety of data in one request. This should improve performance since the same data might take multiple REST API calls to fetch. Also GraphQL queries can omit unneeded data.
Performance can also be improved since that web front-end client Apollo does caching, and this can help avoid repeated calls to the backend for data.
Manually testing GraphQL queries is easier than testing REST APIs because of the built-in query explorer.
Front-end developers can make some changes to queries without requiring any backend work to provide extra data.
and the drawbacks as:
It can be harder to debug GraphQL queries when implementing them, since by default errors are handled rather than causing a traceback. We may want to explore improving the debugging story.
For one-off queries, it may be easier to implement a REST endpoint, because to implement a GraphQL query involves building classes that describe the types of the different parts of the response rather than just describing the signature.
Our current implementation of GraphQL makes us reliant on Apollo and Graphene. Both libraries have quirks that have to be learned and worked around.
As far as generating optimal database queries, GraphQL server implementations generally have the idea of writing a “resolver” which knows how to look up entities in the database. Since GraphQL’s schema is a graph, that means you could have an entity that’s an “invoice” and you could ask for a specific invoice by ID and request its line items (which are each distinct entities as well). In an RDBMS, there’s a normal 1:many relationship between invoice and line items, and the resolver would be able to collect up all of the line items with a single query.
Generally speaking, you can design your GraphQL schema to make lookups reasonably efficient for whatever kind of database tech you’re using. (If you’re using a graph database, it becomes really natural, I should think. We’re not, though.)
I’ll note that our new GraphQL setup is more complex because of federation. Looking up entities in our datastore doesn’t change, but the queries themselves go through a query planner which distributes parts of the query to different services.
Bold move, I hope that their reasons for it are justified and they’ll come out OK on the other end as I really love what Khan Academy is doing.
How will you handle the server-side rendering for React if the services are in Go?
Thanks, and I agree that it’s a challenge.
We’ve been doing server-side React rendering for quite a while already. We’re changing the flow a bit, because it used to be that requests would go to Python which would then call out to Node for server side rendering. Going forward, our CDN will talk to the Node React render server directly to get complete pages.
I’d be happy to answer any questions you have. We’ll definitely follow up with more blog posts as we go along.
Thank you for writing the article.
I have two questions:
¹ I only have superficial knowledge about GraphQL, so my questions could be a bit naïve.
Good questions!
First of all, I’ll give a shoutout to Michael Nygard for his documenting architecture decisions blog post. I didn’t have to create my own answer to the question of migrating to GraphQL. I was able to just look up the architecture decision record (from September 2017).
We saw the benefits as:
and the drawbacks as:
As far as generating optimal database queries, GraphQL server implementations generally have the idea of writing a “resolver” which knows how to look up entities in the database. Since GraphQL’s schema is a graph, that means you could have an entity that’s an “invoice” and you could ask for a specific invoice by ID and request its line items (which are each distinct entities as well). In an RDBMS, there’s a normal 1:many relationship between invoice and line items, and the resolver would be able to collect up all of the line items with a single query.
Generally speaking, you can design your GraphQL schema to make lookups reasonably efficient for whatever kind of database tech you’re using. (If you’re using a graph database, it becomes really natural, I should think. We’re not, though.)
I’ll note that our new GraphQL setup is more complex because of federation. Looking up entities in our datastore doesn’t change, but the queries themselves go through a query planner which distributes parts of the query to different services.