How Facebook's GraphQL Will Change Backend Development
In the early days of web the pages sent to the client were just static HTML, but some interactivity was soon built by generating those pages on the fly for each request. JavaScript was released and we started adding snippets of it on those pages. The release of XMLHttpRequest enabled pages to easily fetch more data from the server and, as time passed, people started to built single-page applications, where the backend became just a JSON API for the app running fully in the browser.
Awesome libraries like React emerged and made building these single-page apps with JavaScript faster than ever before and easy to reason about the flow of data, resulting in maintainable and blazing fast user interfaces.
But someone still had to build, test and maintain that backend, deploy it to a server, monitor it and keep it running. The backend was often built using different languages and tools by a separate group of developers, leading to communication overhead and knowledge silos. Complex code was required to integrate the backend API with the apps running on the client. The inception of backend as a service (BaaS) brought some help to the situation on the server: the provider of the BaaS would give you access to their generic backend that would store your data and let you access it, typically using a REST API. This reduced the amount of work required to get an app running and deployed.
But even though client-side libraries were usually provided by the vendor, building the app on top of any backend, including BaaS, still required lots of custom (and typically vendor specific) code on the client to integrate with it.
Facebook Leading the Way
Fast forward to 2015, Relay and GraphQL are introduced by Facebook. The soon-to-be-open-sourced library Relay manages the data of an application on the client and automatically fetches data from the server. It uses a new query language called GraphQL to build a query that fetches exactly the data that the components of the application need, by combining the queries defined in each component. The generic data store in Relay makes it unnecessary to write custom code for each type of data and handles many common patterns like pagination and optimistic updates.
Relay – the Only Store You Need on the Client
Flux is a nice way to structure large applications with its dispatcher, stores and actions. Its simple data flow really makes applications easier to reason about, even for new people joining a project. But it leaves many questions open that you need to solve yourself, particularly around how to talk to a backend. This is a lot of work to implement correctly and things like server-side rendering complicate things further. There is a proliferation of Flux implementations, and while great for the innovation in the community, this can also be overwhelming while starting a project. The different implementations solve different problems and to solve all the problems of you easily end up rolling out yet another flavor of Flux.
Relay is the next evolution of Flux. In apps using Relay, the components define their data fetching needs. Relay does to data fetching what React did to UI: it makes it declarative. Components defining their data queries inline enables Relay to merge together the queries from all the components, fetch all the data required before the app is rendered and manage the data and updates to it.
Instead of you writing a new store for each type of data, Relay has one store for all your data. This lets Relay handle many common tasks. For example optimistic updates: it’s desirable to update the application state optimistically when doing mutations to data, so the UI updates immediately. Using Flux, this is typically handled in stores by storing the new value there, possibly keeping a reference to the previous value in an immutable data structure to enable rolling back, if something goes wrong. This is not trivial and there aren’t too many generic solutions, resulting in more code to build, test and maintain. Relay takes care of this for us in its store using a queue for pending updates and automatically handles errors.
There is a bunch of these benefits that you get for free by using Relay to manage the data. It handles paginated queries, wires up the store to your components etc. And it’s going to be a battle tested chunk of code like React is: Facebook is already using it in their production apps such as Ads for iOS (a React Native app) with more coming. It’s in their best interest to make it as robust as possible.
GraphQL – Simple and Declarative Query Language
The data fetching needs of components are defined using GraphQL – a new query language that Relay uses to talk to the server. The syntax is very simple. Let’s we have a component that shows a photo posted by a user. It needs some data like this:
{
"id": "c49bc1e1-26c1-49c5-b9c5-c89e24be0ac4",
"url": "https://pics.example.com/dog",
"caption": "My Dog",
"author": {
"id": "5a0cba48-c014-4cf0-b6fb-0bf7514b8165",
"name": "Alice"
}
}
To write a GraphQL query to fetch that you can simply imagine taking this JSON object and removing all the values and adding what is called a “root call” in the beginning, ending up with this query:
node(id: "c49bc1e1-26c1-49c5-b9c5-c89e24be0ac4") {
id,
url,
caption,
author {
id,
name
}
}
This is GraphQL. Relay combines GraphQL queries from your components and sends the combined query for fetching all the necessary data to the server. The server simply responds with a JSON object with data.
Writing queries like this has a number of benefits. First of all, your backend doesn’t end up having custom endpoints for all different kinds of data. That means less code for adding new features. There is just the GraphQL endpoint and it can be optimized and cached heavily.
The client only fetches what it needs. Making changes to an application results in new fields being added and removed. After a while it’s very hard to tell if some field is used in some part of the app or if it could be removed. Removing a field from one component can subtly break another component that implicitly depended on it. Over-fetching (bloating the size of responses) and under-fetching (breaking the app) happens easily. With each component declaring the data it depends on this problem goes away.
Why REST Is Not Enough?
A common way to structure a backend API these days is with REST, specifying endpoints for each type, or resource. Where this breaks down however, is when we want to build any view in our app that requires a tree of related resources, e.g. a feed of shared photos with some comments on each photo and the users who commented. You have to make multiple requests, which can be very slow especially when those requests can not be made in parallel. The code to perform these fetches can also become quite complex, adding to the burden of integrating the frontend with an API. Alternatively you end up creating custom endpoints for the specific needs of your apps, with more backend code to write and maintain. Especially hard, if you have more than one app using the same API. Making even small changes in a backend like this can be a lot of work and have unexpected effects on the apps using it, requiring lots of coordination between different developers and teams.
A GraphQL backend has a schema that defines which fields and calls are available for each type of data. This means adding new models or fields becomes a simple task of adding or modifying types in the schema. When a field has been added in the schema it can be queried. A frontend developer can then go and make a change in just the component that actually uses the data and it works. GraphQL makes it possible to build a backend and integrate it with the frontend with much less custom plumbing than before and to make fast changes with less fear of breaking things.
Making queries becomes even easier with tools that provide autocomplete for queries based on the schema (the schema can be queried with GraphQL queries too). One such tool is GraphiQL, used internally at Facebook and we expect many open source tools to become available after GraphQL is released.
This Is Where the Magic Happens
Spent the afternoon with the relay team at facebook today. Their new office is amazing but the team is even better :) pic.twitter.com/QO3NlUyCDx
— Ryan Florence (@ryanflorence) April 23, 2015
With React, Facebook revolutionized how UI is built for web and mobile apps. Now they are revolutionizing data fetching for those apps. We are looking forward to the open source release of Relay and GraphQL by the amazing team of Facebook engineers and everything the community comes up with after that happens. The future looks bright.
Stay Tuned
We think Relay and GraphQL can change how apps are built. That’s by why we are building Reindex – the first backend as a service optimized for React and Relay. More details coming in the next few weeks!