What is GraphQL (& why should you use it)?
GraphQL is an API syntax that defines how to fetch data from one or many databases.
Since this query language for APIs was open sourced in 2015 by a small company named Facebook
To put all of the website features into the users’ hands, with their mobile apps.A way that would make traffic between clients and servers simpler and more organized.
GraphQL was the result.
They made it possible to manage data over a single endpoint via HTTP. Each query you send to your API gets you exactly what you want. What I mean is that you’ll receive nothing more and nothing less on the other end than exactly what you need. The data required is determined client side instead of letting servers control it, helping to build apps that are way faster and more stable.
Its type schema system-Apollo Tutorial regroups all the data you can access under different fields, no matter where it is stored. You can relate these to one another to get the information needed in one simple request.
Important definitions
Query: A query is what a client sends to a server in order to specify the necessary data. For our upcoming use case, it would look like this:
{
players {
first_name
}
What you would get in return for this query are all the first names of the players of our fictional sport league.
Schema: The blueprint for communication between client and server. It specifies what queries clients can make, the types of data retrievable, and relationships between types.
Resolvers: A function applied to every field. It specifies how that field is connected to the backend and fetches data for that field from a database.
GraphQL vs REST APIs
Some times you have to make different calls to different endpoints for a single request, like loading a page. It made the process slower as you scaled to more complex architectures. And it can rapidly become a real mess with REST APIs for that reason.
So, why choose GraphQL?
There are a few situations where GraphQL absolutely is the best option to build your server with, such as:
- If you have multiple clients, because they simply write their own queries in the language of their choice (GraphQL supports them all);
- If you work on different platforms: web, mobile, apps, etc.;
- If your API is highly customizable.
Plain GraphQL Example Without any libraries
{
"name": "GraphQL_intro",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"graphql": "^15.1.0"
}
}
const {graphql,buildSchema} = require('graphql')
//Create Schema Definition
//Query is the Root Type
//Query can have properties or fields
//message going to return a string
const schema = buildSchema(`
type Query{
message : String
}
`)
//In order to return message, we have to have a resolver function
const rootvalue = {
message: () => 'GraphQL Works'
}
//It needs three parameters
// graphql(
// schema,
// query,
// rootvalue
// )
graphql(
schema,
`{
message
}`,
rootvalue
) .then(
res => console.dir(res, {depth: null})
).catch(
console.error
)
/*
OUTPUT :
{ data: { message: 'GraphQL Works' } }
*/
Example 2 : Returning array of values
const {graphql,buildSchema} = require('graphql')
const db={
users: [
{ id: '1', email: 'alex@gmail.com', name: 'Alex' },
{ id: '2', email: 'max@gmail.com', name: 'Max' }
],
}
//Create Schema Definition
//Query is the Root Type
//Query can have properties or fields
//users going to return a array of user
const schema = buildSchema(`
type Query{
users : [User!]!
}
type User{
id: ID!
email: String!
name: String
}
`)
//In order to return users, we have to have a resolver function
const rootvalue = {
users: () => db.users
}
//users is a type , so we need to mention the fields
graphql(
schema,
`{
users {
email
}
}`,
rootvalue
) .then(
res => console.dir(res, {depth: null})
).catch(
console.error
)
/*
Output :
{
data: {
users: [
{ email: 'alex@gmail.com' },
{ email: 'max@gmail.com' }
]
}
}
*/
What is Node.js Express?
Express is a fast, unopinionated, minimalist web framework for Node.js.
Basic Steps to build GraphQL App :
- Creating a project for the API
- Building a GraphQL schema and resolvers
- Crafting an Express app
- Linking the GraphQL API to a database(MonogoDb, PostgreSQL)
What we have in express is same, just we need type definition and schema. We are making some request like Query and Mutations for client side. Those we need to define some where and our server needs to be bootstrap with all available query at the backend and all available mutation at the backend.
We can define the Query and Mutation in my schema. For that first doing a type definition (ex : User, Recipe.. from there we will returning User Object, Recipe Object) then define the Query and Mutation then defining the implementation of those Queries and Mutation in the resolvers.
We will not be returning only single attribute otherwise for the single attribute you don’t need a type definition.
Here i have a type Query and in the type Query here these all the Queries will be triggering from the client-side
type Query {
User (Id: Int!) : User; // User is the returning object
}
When i hit the Query user, i should get a user object. When i have all users, what should i get the user array (allUsers() : [User !]). Another we can get whole recipe, it will return an array of recipes. Below is the query to fetch data from the server.
Ex :
type Query {
user (Id: Int!) : User; // get user by id
allUsers(): [User!] //get all users
allRecipe: [Recipe!] //get all recipe
recipe(Id: Int!): Recipe //get single recipe
}
Now there can be some Mutations which we’ll be talking. Mutations are same as query only the differences will be using Mutation for them like createUser(…), createRecipe(…). This Mutation will be used for creating the resource and updating resource. They will have enough payload(name: string) From client-side will be triggering Query, Mutation and Subscription.
To implement all this we will use resolver.
Example 2
package.json
"dependencies": {
"apollo-server-express": "^2.19.0",
"bcryptjs": "^2.4.3",
"express": "^4.17.1",
"express-session": "^1.17.1",
"graphql": "^15.4.0",
"pg": "^8.4.0",
"reflect-metadata": "^0.1.10",
"typeorm": "0.2.29"
}
index.ts
import {ApolloServer} from 'apollo-server-express';
import * as express from 'express';
import { typeDefs } from './typeDefs';
import { resolvers } from './resolvers';
const server = new ApolloServer({
typeDefs,
resolvers
})
const app = express();
server.applyMiddleware({app});
app.listen({ port: 4000 }, ()=>{
console.log(`Server ready at http://localhost:4000${server.graphqlPath}`)
})
typeDefs.ts
import { gql } from 'apollo-server-express';
export const typeDefs = gql`
type Query {
hello: String!
}
`
resolvers.ts
export const resolvers = {
Query:{
hello: ()=>{
return 'Hi'
}
}
}
Debugg
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"/**"
],
"program": "${workspaceFolder}\\server\\src\\resolvers.ts",
"outFiles": [
"${workspaceFolder}/**/*.js"
]
}
]
}
Reference
Apollo Tutorial
modularizing-your-graphql-schema-code
express-graphql-tutorial
tkssharma
GraphQL Intro
Traversy Media
CodeWithKris
Will Ward
Chris DeSilva – NBA Scoreboard