From REST
to GraphQL
https://unsplash.com/photos/GpVTuahi2aM
Photo by https://unsplash.com/photos/GpVTuahi2aM
All the tools to get your existing REST APIs working with GraphQL
GraphQL is now a well-recognized technology in the front-end world (and beyond), bringing many advantages:
  • better integrations with React components with great clients and typings generation
  • Great client-side cache system allowing smart fetching policy and optimistic updates of the UI at low cost
  • Faster data loading with fewer API roundtrips

 

However, one of the main challenges of GraphQL is adoption, especially on already existing REST APIs.
This article will guide you to the different strategies to migrate your React apps to GraphQL:
  • Migrate your React app without changing your APIs
  • Migrating your API without rewriting it
  • Rewriting your API in GraphQL

 

 

Migrate your React app only with Apollo

This approach might be the best if you want to try GraphQL at a low cost.
The biggest obstacle to GraphQL adoption on existing systems is the rewrite of APIs:
  • it requires to rewrite all the business logic
  • current APIs may not have useful GraphQL server libraries
  • migrating existing APIs gradually might be hard
In short, rewriting an API just to give a try to a new technology is expensive.
Fortunately, Apollo GraphQL brings an elegant solution to React developers that want to try GraphQL without making any changes to the existing APIs.
The apollo-link-rest package is here to help, as shown on the official documentation:
/images/publications/from-rest-to-graphql-1.png

 

Use Apollo Link REST

Getting started in 2 minutes

Once installed (complete instructions can be found on the official documentation), adding apollo-link-rest to your React project is very simple:
1import { ApolloClient } from 'apollo-client';
2import { InMemoryCache } from 'apollo-cache-inmemory';
3import { RestLink } from 'apollo-link-rest';
4
5// setup your `RestLink` with your endpoint
6const restLink = new RestLink({ uri: "<YOUR_REST_API_PATH>" });
7
8// setup your client
9const client = new ApolloClient({
10  link: restLink,
11  cache: new InMemoryCache(),
12});
You now have Apollo GraphQL ready to be used in your project!
Let’s see some use-cases for a TodoList component:
1const query = gql`
2  query todos {
3    todos @rest(type: "Todo", path: “todos", method:GET) {
4      id
5      title
6      createdAt: created_at
7    }
8  }
9`;
10// [...]
11const TodoList = () => {
12  const { data, loading } = useQuery(query)
13  // [...]
14}
Note that you can also nest @rest usage along with the handy @exportAs directive:
1const query = gql`
2  query todos {
3    todos @rest(type: "Todo", path: “todos", method:GET) {
4      id
5      title
6      createdAt: created_at
7      user_id @export(as: "user_id")
8      user @rest(path: '/people/{exportVariables.user_id}', method:GET, type: 'User') {
9        firstName
10        lastName
11      }
12    }
13  }
14`;
15

 

What if I have multiple REST APIs?

Apollo got you covered!
In order to support multiple endpoints (API versions or microservices subdomains), a single configuration change is required:
1 const link = new RestLink({
2   endpoints: {
3      v1: 'api.com/v1',
4      v2: 'api.com/v2',
5      people: ‘people.api.com/v1’,
6   }
7});
Then, you will have to specify the endpoint at the query level, example with our previous query:
1const query = gql`
2  query todos {
3    todos @rest(type: "Todo", path: “todos", method:GET, endpoint: ‘v2’) {
4      id
5      title
6      createdAt: created_at
7      user_id @export(as: "user_id")
8      user @rest(path: '/{exportVariables.user_id}', method:GET, type: 'User', endpoint: ‘people’) {
9        firstName
10        lastName
11      }
12    }
13  }
14`;
15

 

Takeaways

apollo-link-rest is a great way to try GraphQL over existing REST APIs; however, you should keep in mind that:
  • it is a great temporary solution which does not bring all the advantages of using the “native” GraphQL approach, because of:
    • no Subscriptions support (realtime over WebSocket)
    • a lot of maintenance is required for large use-case (manual type mapping at the query level)
    • no TypeScript types generation
  • there is no guarantee that Apollo will maintain this link in future releases

 

 

Migrate your API with GraphQL Mesh

It exists an alternative to the previous approach, which requires less maintenance on the front-end.
Using apollo-link-rest consists of proxying your existing REST APIs on the front-end side.
Another proxying solution exists on the back-end side: GraphQL Mesh.
/images/publications/from-rest-to-graphql-2.png
GraphQL is a back-end tool that allows the transformation of many types of existing data sources (REST APIs, GRPC APIs, and SQL databases) to stable GraphQL APIs.
Leveraging OpenAPI/Swagger REST API definition, GraphQL Mesh allows you to run a GraphQL server.

 

Proxy your REST APIs

Let’s see an example with a side-project, from 2016, that heavily used the Spotify API.
I needed to get many related data records, which was painful with the Spotify API, a REST API (and throttled).
To solve this issue, I built the spotify-graphql library that was acting as a GraphQL proxy over the Spotify API.
Building this proxy using the graphql package took me weeks; let’s see now how we can achieve similar results in a few minutes with GraphQL Mesh:
First, we need to get a definition (Swagger or OpenAPI compliant) of the Spotify API:
/images/publications/from-rest-to-graphql-3.png
Found!
And create a GraphQL Mesh configuration file:
1sources:
2  - name: Spotify
3    handler:
4      openapi:
5        source: https://raw.githubusercontent.com/APIs-guru/openapi-directory/master/APIs/spotify.com/v1/swagger.yaml
6        operationHeaders:
7           Authorization: <Spotify Token>
.meshrc.yaml configuration file
and them, just by running yarn graphql-mesh serve, I get a fully working Spotify GraphQL:
/images/publications/from-rest-to-graphql-4.png
You now have a fully capable GraphQL API with:
  • non specific maintenance on the front-end side
  • Support for TypeScript types generation with GraphQL Code Generator

 

Secure your GraphQL Mesh server

We know how to transform an existing REST API into a GraphQL one, in order to expose a GraphQL Mesh server publicly, I would advise providing an additional gateway by following this check-list:
As it follows:
/images/publications/from-rest-to-graphql-7.png
The gateway, as a first step (1), ensures that all incoming queries are authenticated and allowed to be processed by the GraphQL Mesh server as a second step (2).

As written in the official documentation, you can also add an authentication layer using Resolvers composition:
1transforms:
2  - resolversComposition:
3        - resolver: 'Query.me'
4          composer: is-auth#isAuth
5        - resolver: 'Mutation.*'
6          composer: is-admin#isAdmin
1export const isAuth = next => (root, args, context, info) => {
2    if(!context.currentUser) {
3        throw new Error('Unauthorized');
4    }
5    return next(root, args, context, info);
6}

 

Takeaways

GraphQL Mesh is a more persistent approach than apollo-link-rest when it comes to proxying existing REST APIs:
  • Low maintenance on the front-end side
  • Support for TypeScript types generation with GraphQL Code Generator
  • Possibility to extends existing APIs and migrate gradually
  • Subscription over HTTP Webhooks
If you’re interested in GraphQL Mesh for more advanced use-cases, I highly advise you to take a look at its other powerful features such as Extending Schema and Cache transforms.

 

 

Rewrite your API in GraphQL

Reaching this section means that you are really committed to using GraphQL by rewriting your existing REST APIs. That’s great!

Rewrite simple (CRUD) APIs with Hasura

If your existing REST API is simple, providing mainly CRUD operations with a bit of ACL and business logic, I would advise using Hasura:
/images/publications/from-rest-to-graphql-5.png
Hasura is an open-source (and on-premise) solution that allows building production-ready GraphQL APIs with ease with:
  • blazing-fast performances over Postgres
  • support of subscriptions over Postgres
  • ACL support
  • Support for custom logic with the “Actions feature”
To be honest, I think it is, it is the best solution if your existing REST APIs are simple and based on Postgres.
You will find all the steps to get started over an existing database on the official documentation, along with how to setup ACL and custom business logic with Actions.

 

Hybrid approach with Prisma

Prisma is an excellent mid-field solution when it comes to building a new GraphQL API, especially with existing databases and logic.
Prisma provides a library that will avoid a lot of CRUD boilerplate and provide tools for common use-cases like pagination and filtering.
See Prisma as your best ally as an ORM and set of tools to build maintainable simple GraphQL APIs:
1const Query = objectType({
2  name: 'Query',
3  definition(t) {
4    t.crud.post()
5    t.list.field('feed', {
6      type: 'Post',
7      resolve: (_parent, _args, ctx) => {
8        return ctx.prisma.post.findMany({
9          where: { published: true },
10        })
11      },
12    })
13    t.list.field('filterPosts', {
14      type: 'Post',
15      args: {
16        searchString: stringArg({ nullable: true }),
17      },
18      resolve: (_, { searchString }, ctx) => {
19        return ctx.prisma.post.findMany({
20          where: {
21            OR: [
22              { title: { contains: searchString } },
23              { content: { contains: searchString } },
24            ],
25          },
26        })
27      },
28    })
29  },
30})
31
Leveraging Prisma makes building a GraphQL API fast and easy.
A great start would be to look at the many Github examples created by Prisma and find one that fit your use-case: https://github.com/prisma/prisma-examples.

 

A complete rewrite with Apollo Server libraries

Reality is more complex than documentation examples.
For this, Apollo has all the answers to build complex, custom, and scalable GraphQL APIs.
Apollo is definitely the go-to actor when it comes to building GraphQL API from scratch, with two mains solutions:
  • Apollo Server
  • Apollo Federation
(Federation is part of Server, but the differentiation is made for simplicity purposes)

A single or monolith GraphQL API: Apollo Server
Apollo was one of the first actors to proposed an alternative server library to graphql, back in 2016.
Covering how to set up a GraphQL Server with Apollo Server would deserve a dedicated article; however, here are the main takeaways from the documentation:
Apollo Server provides:
  • Straightforward setup, so your client-side developers can start fetching data quickly
  • Incremental adoption, allowing you to add features as they're needed
  • Universal compatibility with any data source, any build tool, and any GraphQL client
  • Production readiness, enabling you to ship features faster
Apollo Server will allow you to build a GraphQL API:
  • with the best Schema building tools
  • with an express-like approach
  • with subscriptions (realtime WebSocket) native support
  • compatible with existing REST data sources thanks to the RESTDataSource.
  • complete control over how custom are your resolvers since it’s plain node.js
  • performance optimizations with persisted queries and caching

The micro-services architecture GraphQL API: Apollo Federation
For microservices architecture fans, Apollo Federation is a dream come true.
/images/publications/from-rest-to-graphql-6.jpeg
Again, Apollo Federation is a subject that would require its own set of articles; however, the following points are worth considering in the decision making:
  • Pros: your servers and related code are well organized following the Separation of Concerns (type or concepts based)
  • Cons: all traffic comes through the gateway, which represents a bottleneck - and a SPOF
  • Pros: your schema is distributed, and each service is responsible for well-defined types. Also, all your services are unified as a single GraphQL Schema.
  • Cons: Apollo Federation does not support Subscriptions
  • Pros/Cons: Apollo Federation is better used with Apollo Studio, which provides a set of great tools but also end-up in a vendor lock-in

 

 

Summary

  • Migrate your React app without changing your APIs
Apollo’s apollo-link-rest is an excellent way to experiment with GraphQL for a small feature of your app in order to benchmark what GraphQL could bring to you.
  • Migrating your API without rewriting it
GraphQL Mesh is great to conduct a complete experiment or production solutions experience with GraphQL with no front-end compromise thanks to a full GraphQL API and TypeScript generation support.
  • Rewriting your API in GraphQL
Rewriting your existing REST API can be achieved in many ways depending on your domain complexity and existing databases:
  • Hasura is the go-to solution for a simple REST API based on Postgres with low business logic.
  • Prisma is a great idea when it comes to avoiding the standard boilerplate of CRUD operations in a GraphQL API
  • Finally, Apollo is providing all the tools for a complete from-scratch, production-ready and scalable API: from monolith to microservices-based APIs.