Beruflich Dokumente
Kultur Dokumente
Start hiring
Login
Top 3%
Why
Clients
Partners
Community
Blog
About Us
Start hiring
Apply as a Developer
Login
Questions?
Contact Us
Search Topics
Hire a developer
201shares
You might have heard about the new kid around the block: GraphQL. If not, GraphQL is, in a word, a new way to fetch
APIs, an alternative to REST. It started as an internal project at Facebook, and since it was open sourced, it has gained a lot
of traction.
The aim of this article is to help you make an easy transition from REST to GraphQL, whether youve already made your
mind for GraphQL or youre just willing to give it a try. No prior knowledge of GraphQL is needed, but some familiarity
with REST APIs is required to understand the article.
The first part of the article will start by giving three reasons why I personally think GraphQL is superior to REST. The
second part is a tutorial on how to add a GraphQL endpoint on your back-end.
Making a REST call on the /users endpoint gives you back all the fields of the user, and the client only uses the ones it
needs. There is clearly some data transfer waste, which might be a consideration on mobile clients.
GraphQL by default fetches the smallest data possible. If you only need first and last names of your users, you specify that
in your query.
The interface below is called GraphiQL, which is like an API explorer for GraphQL. I created a small project for the
purpose of this article. The code is hosted on GitHub, and well dive into it in the second part.
On the left pane of the interface is the query. Here, we are fetching all the userswe would do GET /users with REST
and only getting their first and last names.
Query
query {
users {
firstname
lastname
}
}
Result
{
"data": {
"users": [
{
"firstname": "John",
"lastname": "Doe"
},
{
"firstname": "Alicia",
"lastname": "Smith"
}
]
}
}
If we wanted to get the emails as well, adding an email line below lastname would do the trick.
Some REST back-ends do offer options like /users?fields=firstname,lastname to return partial resources. For what its
worth, Google recommends it. However, it is not implemented by default, and it makes the request barely readable,
especially when you toss in other query parameters:
These query parameters are patches added to the REST API to imitate a query language. GraphQL is above all a query
language, which makes requests concise and precise from the beginning.
Endpoint Description
Things get trickier when our requests get more complex. Lets take the GET /users/:id/projects endpoint: Say I want to
show only the projects titles on the home page, but projects+tasks on the dashboard, without making multiple REST calls. I
would call:
In this case, would be it wiser to create a /projects endpoint to do this? Something like /projects?
userId=:id&include=tasks, as we would have one level of relationship less to include? Or, actually, a /tasks?
userId=:id endpoint might work too. This can be a difficult design choice, even more complicated if we have a many-to-
many relationship.
GraphQL uses the include approach everywhere. This makes the syntax to fetch relationships powerful and consistent.
Heres an example of fetching all projects and tasks from the user with id 1.
Query
{
user(id: 1) {
projects {
name
tasks {
description
}
}
}
}
Result
{
"data": {
"user": {
"projects": [
{
"name": "Migrate from REST to GraphQL",
"tasks": [
{
"description": "Read tutorial"
},
{
"description": "Start coding"
}
]
},
{
"name": "Create a blog",
"tasks": [
{
"description": "Write draft of article"
},
{
"description": "Set up blog platform"
}
]
}
]
}
}
}
As you can see, the query syntax is easily readable. If we wanted to go deeper and include tasks, comments, pictures, and
authors, we wouldnt think twice about how to organize our API. GraphQL makes it easy to fetch complex objects.
With REST, there are a couple of solutions. We can create a custom endpoint (i.e., an alias endpoint, e.g., /mobile_user), a
custom representation (Content-Type: application/vnd.rest-app-example.com+v1+mobile+json), or even a client-
specific API (like Netflix once did). All three of them require extra effort from the back-end development team.
GraphQL gives more power to the client. If the client needs complex requests, it will build the corresponding queries itself.
Each client can consume the same API differently.
Modern applications generally use several different services, which expose several APIs. We could actually think of
GraphQL as a gateway or a wrapper to all these services. All clients would hit the GraphQL endpoint, and this endpoint
would hit the database layer, an external service like ElasticSearch or Sendgrid, or other REST endpoints.
A second way of using both is to have a separate /graphql endpoint on your REST API. This is especially useful if you
already have numerous clients hitting your REST API, but you want to try GraphQL without compromising the existing
infrastructure. And this is the solution we are exploring today.
As said earlier, I will illustrate this tutorial with a small example project, available on GitHub. It is a simplified project
management tool, with users, projects, and tasks.
The technologies used for this project are Node.js and Express for the web server, SQLite as the relational database, and
Sequelize as an ORM. The three modelsuser, project, and taskare defined in the models folder. The REST endpoints
/api/users, /api/projects and /api/tasks are exposed to the world, and are defined in the rest folder.
Do note that GraphQL can be installed on any type of back-end and database, using any programming language. The
technologies used here are chosen for the sake of simplicity and readability.
Our goal is to create a /graphql endpoint without removing the REST endpoints. The GraphQL endpoint will hit the
database ORM directly to fetch data, so that it is totally independant from the REST logic.
Types
The data model is represented in GraphQL by types, which are strongly typed. There should be a 1-to-1 mapping between
your models and GraphQL types. Our User type would be:
type User {
id: ID! # The "!" means required
firstname: String
lastname: String
email: String
projects: [Project] # Project is another GraphQL type
}
Queries
Queries define what queries you can run on your GraphQL API. By convention, there should be a RootQuery, which
contains all the existing queries. I also pointed out the REST equivalent of each query:
type RootQuery {
user(id: ID): User # Corresponds to GET /api/users/:id
users: [User] # Corresponds to GET /api/users
project(id: ID!): Project # Corresponds to GET /api/projects/:id
projects: [Project] # Corresponds to GET /api/projects
task(id: ID!): Task # Corresponds to GET /api/tasks/:id
tasks: [Task] # Corresponds to GET /api/tasks
}
Mutations
If queries are GET requests, mutations can be seen as POST/PATCH/PUT/DELETE requests (although really they are
synchronized versions of queries).
Note that we introduced new types here, called UserInput, ProjectInput, and TaskInput. This is a common practice with
REST too, to create an input data model for creating and updating resources. Here, our UserInput type is our User type
without the id and projects fields, and notice the keyword input instead of type:
input UserInput {
firstname: String
lastname: String
email: String
}
109shares
Schema
With types, queries and mutations, we define the GraphQL schema, which is what the GraphQL endpoint exposes to the
world:
schema {
query: RootQuery
mutation: RootMutation
}
This schema is strongly typed and is what allowed us to have those handy autocompletes in GraphiQL.
Resolvers
Now that we have the public schema, it is time to tell GraphQL what to do when each of these queries/mutations is
requested. Resolvers do the hard work; they can, for example:
We are choosing the third option in our example app. Lets have a look at our resolvers file:
const models = sequelize.models;
RootQuery: {
user (root, { id }, context) {
return models.User.findById(id, context);
},
users (root, args, context) {
return models.User.findAll({}, context);
},
// Resolvers for Project and Task go here
},
# Other queries
}
This means, if the user(id: ID!) query is requested on GraphQL, then we return User.findById(), which is a Sequelize
ORM function, from the database.
What about joining other models in the request? Well, we need to define more resolvers:
User: {
projects (user) {
return user.getProjects(); // getProjects is a function managed by Sequelize ORM
}
},
So when we request the projects field in a User type in GraphQL, this join will be appended to the database query.
You can play around with this here. For the sake of keeping the data on the server clean, I disabled the resolvers for
mutations, which means that the mutations will not do any create, update or delete operations in the database (and thus
return null on the interface).
Query
query getUserWithProjects {
user(id: 2) {
firstname
lastname
projects {
name
tasks {
description
}
}
}
}
mutation createProject {
createProject(input: {name: "New Project", UserId: 2}) {
id
name
}
}
Result
{
"data": {
"user": {
"firstname": "Alicia",
"lastname": "Smith",
"projects": [
{
"name": "Email Marketing Campaign",
"tasks": [
{
"description": "Get list of users"
},
{
"description": "Write email template"
}
]
},
{
"name": "Hire new developer",
"tasks": [
{
"description": "Find candidates"
},
{
"description": "Prepare interview"
}
]
}
]
}
}
}
It may take some time to rewrite all types, queries, and resolvers for your existing app. However, a lot of tools exist to help
you. For instance, there are tools that translate a SQL schema to a GraphQL schema, including resolvers!
And we can have a nice-looking GraphiQL interface on our back-end. To make a request without GraphiQL, simply copy
the URL of the request, and run it with cURL, AJAX, or directly in the browser. Of course, there are some GraphQL clients
to help you build these queries. See below for some examples.
Whats Next?
This articles aim is to give you a taste of what GraphQL looks like and show you that its definitely possible to try
GraphQL without throwing away your REST infrastructure. The best way to know if GraphQL suits your needs is to try it
yourself. I hope that this article will make you take the dive.
There are a lot of features we havent discussed about in this article, such as real-time updates, server-side batching,
authentication, authorization, client-side caching, file uploading, etc. An excellent resource to learn about these features is
How to GraphQL.
apollo-client. A GraphQL client with bindings for React, Angular 2, and other front-end frameworks.
In conclusion, I believe that GraphQL is more than hype. It wont replace REST tomorrow just yet, but it does offer a
performant solution to a genuine problem. It is relatively new, and best practices are still developing, but it is definitely a
technology that we will hear about in the next couple of years.
GraphQL is a query language and an alternative to REST. It started as an internal project at Facebook.
GraphQL merges all your RESTful endpoints into one and uses less network traffic.
Sort by Best
Recommend 5 Share
LOG IN WITH
OR SIGN UP WITH DISQUS ?
Name
In right hands REST approach is strong and doesn't have declared weaknesses.
For program there is not difference between building queries for `include` or graph syntax.
Taking a basic example from above where we fetch just a field or two from the Users table, in a Rest API we
would just fetch those fields from the DB while with GraphQL developers would be tempted to just fetch all user
data.
Maybe it's makes sense for APIs used by many different clients with different requirements.
Reply Share
Subscribe
The #1 Blog for Engineers
Get the latest content first.
Enter your email address...
Get Exclusive Updates
No spam. Just great engineering posts.
The #1 Blog for Engineers
Get the latest content first.
Thank you for subscribing!
Check your inbox to confirm subscription. You'll start receiving posts after you confirm.
109shares
Trending articles
Fastlane: iOS Automation on Cruise Control2 days agoMagento 2: Revision or Revolution?3 days agoGetting
Started with the Elm Programming Language9 days agoGraphQL vs. REST - A GraphQL Tutorial12 days agoTips to
Attract, Manage, and Retain Software Developers16 days agoGetting Started with TensorFlow: A Machine Learning
Tutorial17 days agoQuick Wins in the Enterprise With Salesforce AppExchange24 days agoFrom Solving Equations to
Deep Learning: A TensorFlow Python Tutorial25 days ago
Relevant Technologies
API Development
Amaury Martiny
Full-stack Developer
Amaury has more than five years of experience building full-stack web and mobile apps (Node.js, React, React Native). He
is currently working at Parity as a blockchain app developer. He is really interested in entrepreneurship and has worked for
startups of various sizes. In his spare time, he reads about machine learning and writes about hitchhiking, culture, and
philosophy on his travel blog.
Toptal Developers
Android Developers
AngularJS Developers
Back-End Developers
C++ Developers
Data Scientists
DevOps Engineers
Ember.js Developers
Freelance Developers
Front-End Developers
Full Stack Developers
HTML5 Developers
iOS Developers
Java Developers
JavaScript Developers
Machine Learning Engineers
Magento Developers
Mobile App Developers
.NET Developers
Node.js Developers
PHP Developers
Python Developers
React.js Developers
Ruby Developers
Ruby on Rails Developers
Salesforce Developers
Scala Developers
Software Developers
Unity or Unity3D Developers
Web Developers
WordPress Developers
iOS Developer
Front-End Developer
UX Designer
UI Designer
Financial Modeling Consultants
Interim CFOs
About
Top 3%
Clients
Freelance Developers
Freelance Designers
Freelance Finance Experts
About Us
Contact
Contact Us
Press Center
Careers
FAQ
Social
Facebook
Twitter
Google+
LinkedIn
Toptal
Privacy Policy
Website Terms
Start hiring
Login