History of GraphQL
GraphQL was initially developed by Meta (formerly Facebook) in 2012 to address internal issues with their mobile applications. As an alternative to representational state transfer (REST) architecture, GraphQL became open source in 2015. Consequently, because GraphQL makes data transfers more efficient, it reduced network usage for Meta’s mobile applications drastically. Since then, GraphQL has attracted a large number of developers and is becoming increasingly popular for client-server communication.
Why Adopt GraphQL?
Before adopting GraphQL, developers should be familiar with RESTful architecture. Here are some of the benefits of using GraphQL over REST:
- GraphQL allows developers to easily integrate with databases, JSON files, RESTful APIs, and cloud services.
- It prioritizes giving clients the exact data required and nothing more, so only the needed data is received, helping to eliminate over-fetching.
- It can be used to construct requests that pull data from multiple sources into a single API call and response.
- Easier to adopt new data to existing objects, helping to improve future changes and potential under-fetching.
- For example, an existing setup with objects and types already defined needs to include more data in the object (this could require a large change of including an additional fetch within the flow) or additional steps when modeling/mapping the responses to the object.
How GraphQL Works
A common GraphQL workflow can be seen below:
- First, specific data is requested from the client via a query to the GraphQL server.
- To retrieve that data, a function on the GraphQL server is invoked.
- Lastly, the GraphQL server returns the specific data requested by the client.
In a system like REST, only a single set of arguments can be passed in: the query parameters and URL segments of the request. But in GraphQL, every field and nested object has its own set of arguments, making GraphQL a complete replacement for making multiple API fetches. By passing arguments into scalar fields, data transformations can be implemented on the server rather than on every individual client, which can be more efficient.
In GraphQL, object types are the most basic building blocks of a schema and represent the kinds of objects that can be fetched from the service, along with their fields. In the GraphQL schema language, they can be represented as follows:
Charactertype is an example of an object type, it has a set of fields that define its characteristics.
appearsInare fields that belong to the
Characterobject type in GraphQL. These fields contain specific information about a
Character, and they are the only fields that can be included in a GraphQL query when retrieving data about a
Stringis one of the predefined scalar types in GraphQL. Scalar types represent a single, indivisible value and cannot have sub-selections within a query. The
Stringtype represents a sequence of characters and is one of the default scalar types provided by GraphQL.
String!type indicates that a field is non-nullable, which means that it will always return a value when queried. This is represented in the type language using an exclamation mark (
!). This means that when this field is included in a query, a string value must be received in the response, rather than a
[Episode!]!represents an array of non-nullable
Episodeobjects. When the
appearsInfield is queried, an array of
Episodeobjects must be received in the response, even if the array is empty. Additionally, each item in the array is guaranteed to be a non-null
It is also possible to assign default values to variables in the query by adding the default value after the type declaration.
If default values are provided for all variables in the query, it is not necessary to pass any variables when calling the query. However, if variables are passed in as part of the variables dictionary, they will take precedence over the default values.
GraphQL includes a set of predefined scalar types that can be used in the schema. These are known as the “default scalar types”:
Int: A signed 32-bit integer.
Float: A signed double-precision floating-point value.
String: A UTF-8 character sequence.
ID: Represents a unique identifier, which is often used to reference an object or as the key for a cache. It is a string type that is intended to represent a unique identifier for an object, such as a database record or a file.
GraphQL provides support for a third type of operation called subscriptions in addition to queries and mutations. Subscriptions allow a client to receive real-time updates from the server. Subscriptions in GraphQL, like queries, allow the retrieval of data from the server. However, subscriptions are different from queries in that they are long-lasting operations that can change their result over time. A subscription maintains an active connection to the server, typically using WebSockets, which allows the server to push updates to the client whenever the data changes. This enables the client to receive updates about the data in real-time, rather than having to request the data again each time it changes. They can be used to notify the client in real-time about changes such as the creation of a new object or changes to an important field.
Error handling is part of the default GraphQL response structure. Here’s how it works:
- Successful requests return a JSON response with a data field containing the results of a query/mutation.
- Un-successful requests include an additional errors field, representing an array of errors that may have occurred during a request.
- Errors are returned within the errors array field.
- Requests may return a partial response where some fields contain data and others contain an errors array.