3/31/2019 Comments GraphQL from REST perspectiveA majority of web sites are SPAs, built either with Angular, Vue, React or any other framework. My personal preference is Angular but this is not the case of this topic :) Apart from the web sites, a lot of mobile applications are hybrid built with frameworks such as Ionic. All of them require a back-end system that handles the database calls, the heavy data processing/manipulation etc. How does the Client app (SPA or hybrid) communicates with the Server App (back-end)? I bet that the first thing that arises in your mind is the REST. And yup! You are right. This is not the only solution though. There are other solutions that you should consider. From the title of this post, you can imagine what the solution I am talking about is :). GraphQL. Let's see what this is and how we can use it. Server Communication - RESTWhen you have to build a REST API, you know that you have to respect the REST principles and implement certain verbs. Those are:
The POST is responsible to Create data in the data-store. The PUT is responsible to Update/Replace data in the data-store. The PATCH is responsible to Update/Modify data in the data-store. The DELETE is responsible to Delete data in the data-store. If we had to categorize them, wouldn't it be safe to set them under Query and Mutate categories? Well yes :) it would be safe. (glad you agree!) Under Query we would have the GET verb and under Mutate we would have the POST, PUT, PATCH, DELETE verbs. Think of it. When we perform a GET request, we query the data from the data-store. Whereas, we mutate the data for all the other verbs. Server Communication - GraphQLHaving categorized the REST verbs under Query and Mutate let's see the two basic factors of GraphQL. Queries and Mutations. I am sure you got it. Right? You can imagine what each one is responsible for. We will see more soon... REST payloadsFor the communication between the Front-End(client) and the Back-End(server) we need to have a contract. We need to have a schema. I use the term "payload" for this. For the sake of this post we will use the following JSON structure In order to built this payload, we need to have the relevant objects/classes as well. (the code is in TS) GraphQL TypesWhen REST have payloads, the GraphQL have the Types. In order to depict the above payload in Types we have to have the following This notation it looks like JSON. But it's not. It's a GraphQL SDL (Schema Definition Language) which consists of Type and Fields (it has much more but we won't cover them here. We will see just the very basics) Types In front of Project and Task we see the keyword type. Field The field is consist of a name and a "data" type. "id: ID" "Data" types In GraphQL the data types are called scalar types. That's why I have the term data in quotes. The built-in scalar types are
Note that with exclamation mark (!) we set the required fields REST endpoints/resourcesHow can the Client request for Projects from the Server? We have to implement the relevant endpoints GET → /projects POST → /projects PUT → /projects/:id DELETE → /projects/:id PATCH → /projects/:id Say, that we need to get the tasks of a specific project. We need to implement a sub-resource/endpoint GET → /projects/:id/tasks (and all other verbs) What if we want to get only that tasks though? Oh yes! We have to implement another endpoint GET → /tasks (and all other verbs) GraphQL resolversThe REST implementation have the endpoints, whereas the GraphQL have the Resolvers. In order to follow the comparison between REST and GraphQL, think of Resolvers sort of what the controllers are in REST. The communication between the Client and the Server is made only via one endpoint. I am using the Apollo Framework and by default this exposes the /graphql endpoint. Having said that, how can the Client requests for Projects from the Server? QUERY → /graphql MUTATION → /graphql Two major questions came in the surface!
GraphQL QueriesThe Client is responsible to query the data from the Server. And can change the query any time without having to change anything on the Server! This is a legit query and we are asking for the fields "id" and "name" from the "Project", we ask for the relevant "Tasks" each "Project" has and we want to get only the "name" of each "Task". If we want more or less fields, we can do so The second query won't return any Task and won't even send a query to DB. Cool ehh? GraphQL Resolvers - ImplementationLet's see an implementation of the resolvers By convention the Resolvers should be written under Query, Mutation or by scalar types. We can see here that we have Query.projects and Project.tasks As I said earlier, the Resolvers are sort of the same with Controllers. The Queries are associated with the Resolvers In this example, the Query.projects executes a query to DB via mongoose and returns all the items. if you scroll up a bit, you will see that we have the name projects in the query. That projects is associated with the Query.projects. The Client is responsible for WHAT GraphQL query and the responseSo far so good. What is the response of the query? No more than a simple JSON This query... returns... Why is it called GraphQL? Where is the graph?You might say that there is no reason to go with GraphQL as it seems to do similar things as REST does. Well, yes and no. In REST we can not query from the client and if we have a demanded view on the client side, we might need to send multiple requests to the server via REST. Multiple requests means roundtrips which is translated with performance issues. The solution for the demanded view in GraphQL, is to built a graph and request what the client requires via a single request. We asked for the "name" and "id" of a particular "Project", the fields "id" and "name" of the relevant "Tasks" and then we want to get the "Projects" that are associated with each "Task" and the "Tasks" that are associated with each "Project". This seems to be an exaggeration! Think that the response of the GraphQL is the view model of the client. As such, you can do your bindings without having a middle layer to manipulate the data and the schema Problems and solutionsProblem: Multiple round-trips to server to get the data needed for the Client Solution: Get all the data via a single query and have only one round-trip Problem: The data transferred in the wire are way more than required Solution: The Client decides what data is required and not the server Problem: The server Serializes way more data than required Solution: The Client decides what data is required and hence the Serialization time is decreased ConclusionsThe GraphQL is relatively new to me. I hope I managed to help you understand the very basic concepts. As everything, requires study and experimentation.
Each implementation have its cons and pros. The GraphQL seems to be very promising and there are very nice frameworks out there. It is not a panacea though! If you have any question, please shoot it. I will be happy to try answer it for you
Comments
|
AuthorI am an Angular GDE, content creator who loves sharing knowledge TagsAll Angular Angularjs General Graphql Ionic Javascript .net Nodejs Typescript |