We’ve just released Graffiti: it transforms your existing models into a GraphQLGraphQL is a server-side runtime that can execute queries using a type system. It's a query language used for APIs, created from any existing code by defining types and fields. schema. Here is how.
ReactEurope happened last week in the beautiful city of Paris. As it was expected and long-awaited, Facebook released their implementation of the GraphQL draft.
What is GraphQL?
GraphQL is a query language created by Facebook in 2012 which provides a common interface between the client and the server for data fetching and manipulations.
The client asks for various data from the GraphQL server via queries. The response format is described in the query and defined by the client instead of the server: they are called client‐specified queries.
The structure of the data is not hardcoded as in traditional REST APIs – this makes retrieving data from the server more efficient for the client.
For example, the client can ask for linked resources without defining new API endpoints. With the following GraphQL query, we can ask for the user specific fields and the linked friends resource as well.
{
user(id: 1) {
name
age
friends {
name
}
}
}
In a resource based REST API it would look something like:
GET /users/1 and GET /users/1/friends
or
GET /users/1?include=friends.name
GraphQL overview
It’s important to mention that GraphQL is not language specific, it’s just a specification between the client and the server. Any client should be able to communicate with any server if they speak the common language: GraphQL.
Key concepts of the GraphQL query language are:
- Hierarchical
- Product‐centric
- Strong‐typing
- Client‐specified queries
- Introspective
I would like to highlight strong-typing here which means that GraphQL introduces an application level type system. It’s a contract between the client and server which means that your server in the background may use different internal types. The only thing here what matters is that the GraphQL server must be able to receive GraphQL queries, decide if that it is syntactically correct and provide the described data for that.
For more details on the concept of GraphQL check out the GraphQL specification.
Where is it useful?
GraphQL helps where your client needs a flexible response format to avoid extra queries and/or massive data transformation with the overhead of keeping them in sync.
Using a GraphQL server makes it very easy for a client side developer to change the response format without any change on the backend.
With GraphQL, you can describe the required data in a more natural way. It can speed up development, because in application structures like top-down rendering in React, the required data is more similar to your component structure.
Check out our previous query and how similar it is to the following component structure:
<App>
<User>
<Friend/>
<Friend/>
</User>
</App>
Differences with REST
REST APIs are resource based. Basically what you do is that you address your resources like GET /users/1/friends
, which is a unique path for them. It tells you very well that you are looking for the friends of the user with id=1
.
The advantages of REST APIs are that they are cacheable, and their behaviour is obvious.
The disadvantage is that it’s hard to specify and implement advanced requests with includes, excludes and especially with linked resources. I think you have already seen requests like:GET /users/1/friends/1/dogs/1?include=user.name,dog.age
This is exactly the problem what GraphQL wants to solve. If you have types of user
and dog
and their relations are defined, you can write any kind of query to get your data.
You will have the following queries out of the box:
- get name of the user with
id=1
{
user(id: 1) {
name
}
}
- get names for friends of the user with
id=1
{
user(id: 1) {
friends {
name
}
}
}
- get age and friends of the user with
id=1
{
user(id: 1) {
age
friends {
name
}
}
}
- get names of the dogs of the friends of the user with
id=1
🙂
{
user(id: 1) {
friends {
dogs {
name
}
}
}
}
Simple right? Implement once, re-use it as much as possible.
GraphQL queries
You can do two type of queries with GraphQL:
- when you fetch (get) data from your server and the
- when you manipulate (create, update, delete) your data
GraphQL queries are like JSON objects without properties:
// a json object
{
"user": "name"
}
// a graphql query
{
user {
name
}
}
I already showed some queries for getting data from the GraphQL server, but what else can we do?
We can write named queries:
{
findUser(id: 1)
}
you can pass parameters to your query:
query findUser($userId: String!) {
findUser(id: $userId) {
name
}
}
With the combination of these building blocks and with the static typing we can write powerful client specified queries. So far so good, but how can we modify our data? Let’s see the next chapter for mutations.
GraphQL mutations
With GraphQL mutation you can manipulate data:
mutation updateUser($userId: String! $name: String!) {
updateUser(id: $userId name: $name) {
name
}
}
With this, you can manipulate your data and retrieve the response in the required format at the same time – pretty powerful, isn’t it?
The recommendation here is to name your mutations meaningful to avoid future inconsistencies. I recommend to use names like: createUser
, updateUser
or removeUser
.
GraphQL through HTTP
You can send GraphQL queries through HTTP:
GET
for queryingPOST
for mutation
Caching GraphQL requests
Caching can work the same way with GET queries, as you would do it with a classic HTTP API. The only exception is when having a very complex query – in that case you may want to send that as a POST
and use caching on a database/intermediary level.
Other Transport layers
HTTP is just one option – GraphQL is transport independent, so you can use it with websockets or even mqtt.
GraphQL example with Node.js server
The Facebook engineering team open-sourced a GraphQL reference implementation in JavaScript. I recommend checking their implementation to have a better picture about the possibilities of GraphQL.
They started with the JavaScript implementation and also published an npm
library to make GraphQL generally available. We can start playing with it and build a simple GraphQL Node.js server
with MongoDB
. Are you in? 😉
The GraphQL JS library provides a resolve
function for the schemas:
user: {
type: userType,
args: {
id: {
name: 'id',
type: new GraphQLNonNull(GraphQLString)
}
},
resolve: (root, {id}) => {
return User.findById(id);
}
}
The only thing what we have to do here is to provide the data for the specific resolve functions. These functions are called by GraphQL JS in parallel.
We can generate a projection for our MongoDB query in the following way:
function getProjection (fieldASTs) {
return fieldASTs.selectionSet.selections.reduce((projections, selection) => {
projections[selection.name.value] = 1;
return projections;
}, {});
}
and use it like:
resolve: (root, {id}, source, fieldASTs) => {
var projections = getProjection(fieldASTs);
return User.findById(id, projections);
}
This helps optimising the amount of the fetched data from our database.
Check out the Node.jsNode.js is an asynchronous event-driven JavaScript runtime and is the most effective when building scalable network applications. Node.js is free of locks, so there's no chance to dead-lock any process. implementation with MongoDB for more details:
https://github.com/RisingStack/graphql-server
Take a look at Graffiti: it transforms your existing models into a GraphQL schema.