What is GraphQL?

GraphQL comes from Facebook and was open sourced in 2015. It is an API query language. If you think back to SQL, isn’t it surprisingly similar? They are both Query Languages. SQL is a Structured Query Language, and GraphQL, obviously, is a Graph Query Language. At this point, you might say, why is it called graph?

MySQL is an implementation of SQL, Apollo, Relay is also an implementation of the GraphQL specification

The data source for SQL is a database. The data source for GraphQL can be restful apis, various services/microservices, or databases

Why is it called graph?

In the world of GraphQL, everything is a graph, and you can model your business model as a graph. Since the structure of a graph is closer to the natural world than a relational database, there is no need to transform the graph structure into a relational structure when designing a graph database.

What are the benefits of GraphQL?

  • Front-end flexibility. You can fetch the fields on demand, or you can aggregate the data on the interface to get all the data at once
  • Back-end complexity is reduced. No longer need to maintain version numbers of interfaces, reducing redundant business code (more likely to be added apis that duplicate existing apis, resulting in redundancy of back-end business code)
  • Strongly typed. Complete type verification mechanism provides a more robust interface
  • Readable, the code is the document

Without further further, let’s take a look at how GraphQL defines its interfaces and see what their interfaces look like.

Data preparation

Start by preparing a simple list of user data. Note: Data can come from databases, upstream servers/microservers, etc. GraphQL itself is not a database.

[{id: 1.key: 1.name: "John Doe".email: "[email protected]".age: 22 },
  { id: 2.key: 2.name: "Jane Doe".email: "[email protected]".age: 23}]Copy the code

Schema

Schema is the traditional interface document in GraphQL. You can define the name of the query, the input parameters and the output parameters (the returned fields) in the Schema.

Each Schema has a Root Query and Root Mutation.

  • Query: Defines the Query action
  • Mutation: Defines the actions of adding, deleting, and modifying

Based on the list of users just prepared, let’s look at how to write and define interfaces to users. As you can see below, schema definitions are very similar to typescript.

// schema.graphql
type Query {
  // User list
  users: [User]!
  // Individual user detailsuser (id: ID!) : User! } type Mutation {// Add a useraddUser (id: ID! , name:String! , email:String! , age: Int): User// Update the userupdateUser (id: ID! , name:String.email: String.age: Int): User
  // Delete the userdeleteUser(id: ID!) : User! } type User {id: ID!
  key: Int!
  name: String!
  email: String!
  age: Int!
}
Copy the code

type

As you can see above, type is an important component of schema. Strong typing is one of the important features of GraphQL. Types fall into two categories:

  • Scalar types (base types) : Int, Float, String, Boolean, and ID

The enum type enum is a collection of optional values of a special scalar type that can be enumerated

  • Object type: A type related to the business, such as User.
type User {
  id: ID!
  key: Int!
  name: String!
  email: String!
  age: Int!
}
Copy the code

Note: The base type is a leaf node. Define object types until all are base types

Passing parameters

/ / parameter idtype Query { user (id: ID!) : User! }Parameter id, name, email, agetype Mutation { addUser (id: ID! , name:String! , email:String! , age: Int): User }Copy the code

The meaning of an exclamation mark

  • Retrieves the field from the server and returns a non-null value
// Return a non-empty array of User types
type Query {
  users: [User]!
}
Copy the code
  • Defines parameters for a field. The parameters passed cannot be null values
// The id passed is a non-empty IDtype Query { user (id: ID!) : User! }Copy the code

Complexity analysis

A graphQL request may put tremendous pressure on the server. If the database is operated too much, it may lead to a DDoS attack. Complexity analysis is implemented using @complexity

type Query {
  me: User @complexity(value: 10)}Copy the code

Abandoned fields

You can mark a field as obsolete and give the reason for it. In this way, users of older versions can be prompted to upgrade to the latest interface in a friendly way during version iteration. Deprecated fields are implemented by adding @deprecated

type User {
  avatar: String @deprecated(reason: "Moved to UserAvatar.")}Copy the code

Now that you have understood the definition of interfaces, how do interfaces fetch and process data? Graphql does this with resolver.

resolver

Next, we need to provide a resolver function for each field in Root Query and Root Mutation.

import {users} from '.. /db';
const resolvers = {
  Query: {
    users: (parent, args) = > {
      return users
    },
    user: (parent, {id}) = > {
      return users.find(item= > item.id == id)
    }
  },
  Mutation: {
    updateUser: (parent, {id, name, age}) = > {
      let user = users.find(item= > item.id == id)
      user.name = name
      user.age = age
      return user
    }
  }
}

export default resolvers
Copy the code

Next, let’s build a simple GraphQL Server using GraphPack

Graphpack of actual combat

Graphpack can create a simple zero-configured GraphQL Server

Graphpack is a zero-configuration GraphQL server environment that integrates Webpack + Express + Prisma + Babel + Apollo-server + Websocket and supports hot update

First, create an empty project, after init yarn, install GraphPack

yarn add graphpack
Copy the code

Configure the GraphPack startup and packaging scripts

// package.json
"scripts": {
    "dev": "graphpack"."build": "graphpack build"
}
Copy the code

Create a new directory SRC. The directory structure is as follows

  1. Db /index holds the user’s mock data
export let users = [
  { id: 1.key: 1.name: "John Doe".email: "[email protected]".age: 22 },
  { id: 2.key: 2.name: "Jane Doe".email: "[email protected]".age: 23}];Copy the code
  1. Schema is defined in schema.graphQL
type Query {
  users: [User]! user (id: ID!) : User! } type Mutation { addUser (id: ID! , name:String! , email:String! , age: Int): User updateUser (id: ID! , name:String.email: String.age: Int): User deleteUser(id: ID!) : User! } type User {id: ID!
  key: Int!
  name: String!
  email: String!
  age: Int!
}
Copy the code
  1. Each analytic function is defined in resolvers/index
import {users} from '.. /db';

const resolvers = {
  Query: {
    users: (parent, args, context, info) = > {
      return users
    },
    user: (parent, {id}, context, info) = > {
      return users.find(item= > item.id == id)
    }
  },
  Mutation: {
    addUser: (parent, { id, name, email, age }, context, info) = > {
      const user = { id, name, email, age }
      users.push(user)
      return user
    },
    updateUser: (parent, { id, name, email, age }, context, info) = > {
      const user = users.find(item= > item.id == id)
      user.name = name
      user.email = email
      user.age = age
      return user
    },
    deleteUser: (parent, { id }, context, info) = > {
      const userIndex = users.findIndex(user= > user.id === id);
      if (userIndex === -1) throw new Error("User not found.");
      const deletedUsers = users.splice(userIndex, 1);
      return deletedUsers[0]; }}}export default resolvers;
Copy the code

Yarn dev Start the server and go to http://localhost:4000. In this interface, we can test the interfaces, somewhat similar to Postman. First test the query for the user list Users and the single user detail user

query {
  users {
    key
    name
    age
    email
  }
  user (id: 1) {
    name
    age
  }
}
Copy the code

Test the update user mutation operation again. Example Update the information about the user whose ID is 1

mutation {
  updateUser (id: 1.name: "lily".age: 20.email: "[email protected]") {
    id
    name
    age
    email
  }
}
Copy the code

After the update, switch to the Users list and refresh, and find that the data has become the latest user information

Other mutation changes operate similarly, interested students can try one by one.

The last

The GraphQL server has been set up. How to request it in the React client? To be continued in the next chapter…

Graphql Chinese document