Back in 2012, Facebook mobile developers only had a RESTful API to access resources, and able to create advanced queries using FQL (An SQL-Like language developed by Facebook to let API clients run their own queries). This technology didn't suit well their needs; they wanted an API technology that let them access the whole Facebook model, in a really simple way, and not thinking in terms of resources nor representations (only JSON is supported). Then GraphQL was born.
Most commonly known as a query language, GraphQL is much more than that:
- Query language - Let client-side application run their own queries. It supports filtering, pagination, fields-selection, etc. Queries are just a string sent from the client to the server. Given the nature of the schema, graphql reduces the required number of requests.
- Schema definition language - There is no need to appeal to third-party technologies to define the domain model. The GraphQL Schema Language is also strongly typed.
- A reference implementation - The
graphql-js
project. - An ecosystem - Together with the spec, the language, and the reference implementations, are some official tools, like GraphiQL (an IDE and query runner), or express-graphql (a middleware for express to create a GraphQL server).
These are the Design Principles behind GraphQL:
- Hierarchical. Views in applications displays information hierarchically. GraphQL queries are hierarchical as well, to mimic the structure of the views. Unlike REST, which exposes resources, GraphQL promotes its entity graph.
- Product-Centric. It was born to solve the problems of the frontend developers.
- Strong-typing. This allows for validation, either with development tools or in the server.
- Client-specified queries. Thanks to the strongly-typed schema, servers expose their capabilities, and then clients decide what they exactly want.
- Introspective. The query language itself is able to ask a server about it's type system. This enables the promotion of tooling and shared libraries.
Among other thinks, this also improves the evolvability of the API, as we can monitor which fields are actually being used/requested, which makes deprecation much easier.
GraphQL adoption has not stopped increasing since its inception. GitHub announcement of their new GraphQL API clearly was a game changer: 60% of their database requests were because of their REST API: an hypermedia-based API often requires several round-trips to fetch all the information needed (dealing with under-fetching and over-fetching in REST is far from trivial). They had got several other concerns (they wanted type-safety, a better pagination strategy, automatic documentation from the code, etc.) Turned out GraphQL matched all their requirements.
However, some people argue that most of the claimed advantages of GraphQL over REST can actually be used on REST (sparse fieldsets, schema, query language, embedded resources, etc).
Here we will just make a quick introduction to some concepts of the GraphQL Query Language. It support three different operations: query
, mutation
and subscription
. In the following case we are running the me
query, and selecting the field name
from its result:
{
me {
name
}
}
When the operation is of type query
, the operation type is optional. In case it was a mutation
or a subscription
it would be mandatory. In the following example we run a mutation setting a parameter id
. Note the operation type:
mutation {
deleteArticle(id: 5) { title }
}
Each request can contain a batch of several operations of the same type. For example:
mutation {
deleteArticle(id: 5) { title }
deleteComment(id: 50) { author { name } }
}
Additionally, we can name our operation to help monitoring and debugging:
mutation MyMutationName {
deleteArticle(id: 5) { title }
deleteComment(id: 50) { author { name } }
}
Finally, we can define variables
mutation MyMutationName($articleId: ID!, $commentId: ID!) {
deleteArticle(id: $articleId) { title }
deleteComment(id: $commentId) { author { name } }
}
In this case, variables will be specified in its own JSON object:
{
"articleId": 5,
"commentId": 50
}
This was just an introduction to the GraphQL syntax. In subsequent chapters we will explore each usage case.
Technically, GraphQL can run on top of any transport protocol. However, the most common choice is HTTP. This leads to the following:
Since GraphQL exploits the conceptual model of entity graph to represent the state of a system, entities are not identifier by a URI. Instead, there is a single entry point (URI) to make requests to the API.
Both GET
and POST
can be used. If using GET
, the query will be sent as a JSON string in the query
parameter, as in: http://myapi/graphql?query={me{name}}
. Optional parameters variable
and operationName
can be used as well.
When using POST
, an JSON object like this will be sent to the server:
{
"query": "...",
"operationName": "...",
"variables": {
"myVariable": "someValue"
}
}
Where operationName
and variables
are optional fields.
GraphQL only supports a single representation for their entities: JSON
. Specifically, the response will be wrapped in a JSON object with two fields, data
and errors
:
"data": { },
"errors": [ ]
}
Unlike REST (which is just an architectural style), there are a lot of implementations of the official GraphQL spec, both for server and clients, and for every major programming language.
The most popular ones are JavaScript based:
- express-graphql - GraphQL official middleware for Express.
- Apollo - The industry-standard solution for GraphQL.