preface

As a front-end, you complain about redundant request interface fields, you complain about having to request multiple interfaces to get the data you want, and you even hate that the back-end interface is poorly documented. As a back end, you can’t stand it when the front end points at your interface and complains why the front end doesn’t get the value it wants… Development confrontations like these have become commonplace, and GraphQL is here to stay.

What is a GraphQL

GraphQL is an open source data interaction solution of FackBook. It is a query statement for API interface and query existing data runtime environment. It provides a complete and easy-to-understand SET of API data descriptions, giving clients the power to query precisely the data they need without having to implement more code. Make API interface development easier and more efficient, support powerful developer tools

Problems encountered

  1. The number of interfaces is large and the maintenance cost is high

To ensure the universality of interfaces, the back-end usually constructs small-grained data interfaces, and then combines the data interfaces according to specific service products to expose the service interfaces.

Even so, there are still a lot of front-end interfaces, because the business is always changing, and when the current requirements change, the following will happen when it comes to changing the old requirements.

When the need for additive products increases, pages need more functionality, and data needs to be displayed in response, the addition of interfaces is understandable.

Reduce product requirements, page requirements to reduce functionality or reduce the display of certain information

  • The front end does not communicate with the back end. The front end displays only corresponding fields as required
  • Alternatively, the front end requires the back end to either develop a new interface or modify the old interface to remove redundant fields
  1. Interface fields are redundant, and multiple requests waste bandwidth

In order to facilitate the management interface, the back end usually develops only one SET of apis to accommodate data requests from different ends (Web/H5 /ios/ Android)

  • Different terminals have different requirements for display data. Especially in the development of the mobile end, the front-end needs the back end to return as few fields as possible to avoid bandwidth waste. Usually, the back end develops a set of API to adapt to the mobile end request
  • Does the back-end encapsulate the Action, maintain one more API, or does the front-end tolerate multiple HTTP requests?

Rendering a page requires sending four requests to get the corresponding data

  1. Indeterminate data structures

Front-end development With the full popularity of SPA, componentized development is also the general trend, and each component independently manages its own state. But componentization also causes some headaches for the front end, as some common components pull data from the server and then distribute it to child components or notify parent components. This communication brings complexity of data structure, unclear data, not knowing where to subscribe to the data response, resulting in clutter, etc. 4. Different interface field types For weakly typed languages such as javascript and PHP, string and number types in data interaction at the front and back ends may cause bugs at the front and back ends.

GraphQL solution

1.Free combination interfaceYou can combine and connect multiple GraphQL apis into one to reduce the number of requests

2,The value is on demand and no redundant fields are returned

GraphQL is strongly typed and validates queries in the GraphQL type system before execution, which helps us build more powerful apis

How to implement GraphQL

Before we get to the GraphQL implementation, let’s look at the traditional request data interaction.

Traditional REST requests

An interface requests the corresponding API to retrieve the corresponding dataGraphQL request GraphQL willMultiple request mergeTo get the fields corresponding to the user list, subject list, and fruit list. The implementation is that the client sends a specific request body ** (we call it the GraphQL client), the server receives the request, according to the parser(we call it the GraphQL server) ** parses and returns the specified data to the front-end, and the request body and response body of this part are called schema, as shown in the following figure

The schema defines the front-end requirements to obtain those data and corresponding fields, and the back-end will parse the schema into the Document AST syntax tree according to GraphQL parsing, and invoke the corresponding Action and Modal queries. Next, we will parse the schema in detail

Schema

Schema is a protocol used to define a scalar type that describes an interface. The scalar types of type are String, Int, Float, Boolean, Enum, and ID. Query,Mutation(the action you want to perform is add, delete, or change)

Query operationIn the schema, we define an interface to get a list of users, which returns the user name, age, when the user was created, and so on

/ /...
// Define user informationtype UserInfo{ name! :String.// Define the name as a stringage! : Int,/ /! To indicate that this field is automatically non-null, the GraphQL service guarantees that it will always return you a value when you query this field
  createTime: Float
}

Query {
  // Define user list, return user information
  getUserList: [UserInfo]
}
// 
Copy the code

The mutation operation defines an operation to add a user. Name and age are required fields and return the interface response code RET and response information

/ /...
// Define user information
type UserInfo{
  name: String.// Define the name as a stringage! : Int,/ /! To indicate that this field is automatically non-null, the GraphQL service guarantees that it will always return you a value when you query this field
  createTime: Float
}
type Ret{
  ret: Int,
  msg: String
}

Mutation {
  // Define user list, return user information
  addUser: (input: UserInfo): Ret
}
// 
Copy the code

How are the front and back ends implemented

  • The data model is designed to describe the data object. Its function can be seen as VO, which tells GraphQL how to describe the defined data, in preparation for the next query return.
  • The front end uses Schema query language (Schema) to describe the data object types and specific required fields (called declarative data acquisition).
  • The back-end GraphQL automatically assembles data fields based on requests sent from the front end and returns them to the front end.

Back-end GraphQL officially provides C# /.net, Go, Java, JavaScript, PHP, Python, Ruby, Swift and more than ten language tool libraries. Here we take JavaScript as an example.

A reference implementation of the GraphQL specification designed to run in a Node.js environment. Create index. Js, install dependencies graphql library, defined schema, operation node index, js, we can visit the hello, getUserInfo, addUser interface, etc

var { graphql, buildSchema } = require('graphql');

var schema = buildSchema(` type UserInfo { name: String, age: Int, createTime: Float } type Ret { ret: Int, msg: String } type Query { hello: String, getUserList: [UserInfo], } Mutation { addUser: (input: UserInfo): Ret } `);

var root = { hello: () = > 'Hello world! ' };

graphql(schema, '{ hello }', root).then((response) = > {
  console.log(response);
});
// 
Copy the code

GraphQL and Node library combined development

Express-graphql is provided in conjunction with the Node Express library

npm install express-graphql graphql
Copy the code
var express = require('express');
var graphqlHTTP = require('express-graphql');
var { buildSchema } = require('graphql');

var schema = buildSchema(` type UserInfo { name: String, age: Int, createTime: Float } type Ret { ret: Int, msg: String } type Query { hello: String, getUserList: [UserInfo], } Mutation { addUser: (input: UserInfo): Ret } `);

var root = {
  hello: () = > 'Hello world! '.getUserList: [{name: 'Ming'.age: 8.createTime: 451647414144
    },
    {
      name: 'kenny'.age: 18.createTime: 812344314710}]// ...
};

var app = express();
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true,})); app.listen(4000.() = > console.log('Now browse to localhost:4000/graphql'));
Copy the code

Front-end As long as the front end is submitted through GraphQL request library, or send ajax request in accordance with the schema syntax, here we use graphQL-request request, similar to common axios, fetch, etc

npm install graphql-request
Copy the code
import { GraphQLClient } from "graphql-request"

// instantiate a GraphQL
const graphqlClient = new GraphQLClient("/test/graphql/api", {
  credentials: "same-origin",})Return id,name,abstract,create_time,update_time
const query = ` query querySubjectList{ querySubjectList { id name abstract create_time update_time } } `

graphqlClient
  .request(query, vars = {})
  .then(res= > {
    resolve(res)
  })
  .catch(err= > {
    console.log("err", err)

    rej(err)
  })

Copy the code

Spa development often encounter a component to adapt to different interface fields, for example, we define a Select component, render list support valueMap is value and label, if the back end interface returns id, name, etc., usually the front end needs to give the component adapter, GraphQL aliases allow us to define the name of the returned field. In the image below, we change the ID to value, label. This allows you to rename the field in the result to whatever name you want

query querySubjectList{
  querySubjectList {
    value: id
    label: name
    abstract
    create_time
    update_time
  }
}
Copy the code

Front-end friendly Schema Play DirectivesThe variables we discussed above allow us to avoid manual string interpolation to build dynamic queries. Passing variables to parameters solves a lot of these problems, but we may also need a way to dynamically change the structure of our query using variables. For example, let’s say we have a UI component that has a summary view and a detail view, the latter of which has more fields than the former

{
  "episode": "JEDI"."withFriends": false
}

query Hero($episode: Episode, $withFriends: Boolean!) {
  hero(episode: $episode) {
    name
    friends @include(if: $withFriends) {
      name
    }
  }
}
Copy the code

Return result:

{
  "data": {
    "hero": {
      "name": "R2-D2"}}}Copy the code

You can learn more about this in GraphQL

conclusion

When developing the service side, we can make the service more atomic. We don’t care what fields the front end needs. We can write the service according to the GraphQL Schema based on the best practices of the back end. The front end can compose data and services according to the Schema without constantly asking the back end to add or subtract fields or interfaces.

GraphQL remove the binding between the interface and data, made the abstract and the finishing on the business data model, the way to model the relationship between the clear, through these relationships, specific business scenarios can customize their own data, based on different business scenarios as long as the same set of data model can reuse of interface.

More benefits, please slowly experience in the development practice!

A link to the

GraphQL