Building Native Mobile Apps with GraphQL
For almost a year now, attention of the whole Meteor community has been drawn to the Apollo project. At ReactEurope 2016 conference, Martijn Walraven from Meteor Development Group (MDG) gave a one-sentence summary of what Apollo is about:
It’s about building tools to improve the GraphQL developer experience.
- do one thing well
- are easy to understand
- are easy to debug
- offer an API surface that helps to integrate these tools into new environments.
In 2012 the Facebook team rewrote its main app from HTML5-based to a fully native iOS application. GraphQL data querying language was developed as a part of this effort. However, today there’s still no easy way of using GraphQL in native mobile environments outside of Facebook.
Mobile as an Important Use Case for GraphQL
The main issue for mobile clients is that they connect to networks with fairly high latency (even up to several seconds). That’s why it’s strongly desired to avoid repeated round trips to get data for the single view.
Most developers have encountered this while working with REST :
You start out with a neatly designed REST structure, separate endpoints for every object.
When you need the data together, and still want to avoid repeated round trips, you create new endpoints: the ones that give you exactly the data you need.
Since there are multiple clients for different platforms with slightly different data requirements, you’re sending data to the clients that don’t actually need it. You are overfetching data.
And when you consider different versions of these clients, for major versions you may actually have to create new endpoints. Endpoints that you’d have to maintain, and that duplicate code.
It’s obvious that the whole REST model of clients connecting to separate endpoints and servers deciding what to send is unscalable.
GraphQL is an amazing solution to this:
the server defines what data is available to clients in a form of a GraphQL schema;
- clients write queries that specify the exact data needs that they have.
Thus, it’s a great way of decoupling of the clients and services.
How to Connect a Mobile App to a GraphQL Server?
Every developer who would like to find an answer to this question will face the following challenges:
the technology used in Facebook is tightly coupled to the Facebook infrastructure and is not open-source
the GraphQL specification is well-written, however, it’s quite overwhelming, and hardly will help to convince people that GraphQL is simple.
Martijn shows an example app to demonstrate the capabilities of GraphQL clients. The GraphQL schema that underlies this app contains data both from an application specific database, and information that comes from the GitHub API. Martijn mentions a few ways to query the information in this schema in a native app.
HTTP POST request with GraphQL query. The basic conceptual model of GraphQL is Request => Response.
The most often used network transport is HTTP. There’s a simple way to make HTTP POST request with GraphQL query and get JSON back. This gives a lot of the GraphQL benefits without doing much Graph QL specific work on a client. But it does not fully utilize GraphQL.
Yet, type generation based on the GraphQL schema has its drawbacks.
Fields generation in the classes causes the schemas grow. Eventually, they may contain hundreds of fields. And you definitely don’t want all that information in your data types.
When you specify the exact data needs in a query, you want to make sure that in your UI code you only have access to the existing requested data.
Query specific types generation provides strong typing based on the actual queries you’re performing.
As the types are specific to the part of the query they are in, Martijn also suggests using fragments to generate interfaces or protocols. This would give a really easy way of getting both type safety and the ability to still have query-specific data classes.
Martijn shows a corresponding demo in swift, and remarks that similar solution is applicable for Java as well.
GraphQL Clients and Data Consistency
Quite often you make a query and use the value you get to show something in your UI. As the values may change in time, when you repeat the same query, you get a value different from the one you’ve got the first time. However, the original UI component will not update automatically. So, what you want as a GraphQL client is a single source of truth. Martijn shows the way to use a normalized data cache to make sure that objects have a single representation in the system.
Break up the tree of your query into separate objects
Normalize the results
- Store those results separately using an object ID
Use that single normalized cache to distribute data to your different UI components.
Consequently, the client uses the queries bound to UI components to query the cache. This gives the results of the queries you’ve done yourself, and also updates information that might come in from other queries, or even from other update mechanisms. In addition, this allows to minimize the queries that you actually send to the server. Moreover, you can reuse the information that’s already in the cache, and only query for information that’s not there.
As Apollo is a community-driven project, he encourages developers who are interested in using GraphQL to share their ideas. The common effort will certainly help to bring native clients base for GraphQL further.
Watch the whole presentation by Martijn Walraven on ReactEurope YouTube channel:
P.S. February 7-14, 2017 was announced an online Apollo Contributor Week .
It's a pleasure for us to work on projects which include GraphQL development. With the benefits, mentioned above, we believe that the technology might find its place in your marketplace platform creation process.