Writing in the front

I’m going to share GraphQL with my team recently, so I’m going to take a look at this article, and I hope you’ll come away with the following:

  • The concept of GraphQL
  • Why use GraphQL
  • How to use GraphQL
  • Issues to be aware of with GraphQL

concept

The concept of GraphQL is brief: a query language for apis. Putting this aside for a moment, let’s think about what a programming language does: it defines the syntax, the developer programs the code according to the specified syntax, and then gets the program running. Similarly, GraphQl is a query language for the API. It defines the syntax rules for the API query. Developers can develop the API according to the syntax rules, and then the client can make a request to the server to do the API query.

For API query languages, most readers will probably think of REST, and yes, GraphQL was designed as an alternative to REST, and they both represent a design specification for apis.

Although the name is GraphQL, it has no direct connection to the database, and the official document, the FAQ, explains why.

Why GraphQL

Since its launch in 2012, GraphQL has been used by many large companies in their business. Facebook, not to mention GitHub, has fully used GraphQL in their API V4, and Airbnb has migrated most of its API to GraphQL… Therefore, GraphQL has been validated by the business, so we can use it with confidence.

So what is the charm of GraphQL relative to traditional REST that will win out in these companies’ technology selection battles?

The endpoint

The core concept of REST is resources, and one interface is used to manipulate a single resource. In our daily business, we need to request multiple urls to obtain different data.

In contrast, GraphQL usually has only one entry, and we get the resource we want from the parameter description, which means that we can complete the same request with less network connection costs.

Accurate data acquisition

Different terminals may have different information to present. For example, the Web side usually needs to present all the information possible, while the mobile side may only need to present the key summary information. But from a development point of view, we often want an interface that can meet the needs of different ends, which results in a waste of network resources at some end because the response packets return useless data to the client.

In the case of REST, there are two solutions to the above problem:

  • Provide different apis for different terminals
  • The second is to use an API that returns a union of data required by different terminals

Both options have their own problems, with the first adding extra development effort and the second resulting in excessive data acquisition on different terminals.

GraphQL is a good way to solve the above problem, because the application, not the server, controls the data.

Powerful developer tools

GraphiQL is the IDE of GraphQL service. Developers can not only view documents in GraphiQL, but also enjoy intelligent code prompts and error prompts when debugging, which brings great convenience to developers.

More powerful features

GraphQL also has many powerful features, such as the API evolution process without partitioning, built-in parameter verification and server push, etc. For more details, please refer to the official website.

How to use GraphQL

After introducing GraphQL’s many features, it’s time to start using it.

A complete GraphQL query typically goes through three steps: describing the data, requesting the data, and getting the results.

Describe data

type Project {
  name: String
  tagline: String
  contributors: [User]
}
Copy the code

Let’s parse this data description code one by one:

  • typeIs the keyword, indicating that one will be defined nextGraphQL Object typeThat is, the one that followsProject.
  • name,taglinecontributorsProjectType on the field that is indicated in an operationProjectAny part of the GraphQL query of type, can only appearname,taglinecontributorsField.
  • StringIs the built-inscalarType, we cannot subselect the scalar type in the query.
  • [User]Indicates a null value or aUserArray, so so when you querycontributorsField, you always get a null value, or an array, where every object in the array is null orUserType.

The request data

GraphQL Schema has two special types: Query and Mutation, which define the entry to each GraphQL Query, means that each Query of GraphQL must be a field of type Query or Mutation.

Therefore, if we want to execute the following query:

{
  project(name: "GraphQL") {
    tagline
  }
}
Copy the code

The following schema definitions must exist:

type Query {
  project(name: String): Project
}
Copy the code

results

The structure of the response was exactly the same as the structure we described, which allowed us to use the data as we expected, greatly improving the efficiency of client development.

GraphQL also has many basic concepts and usages, such as variables, aliases, directives, and type systems, etc. Due to space, we will not introduce them here, interested readers can visit the official document to view.

Client implementation

GraphQL client implementation solution can help developers better data request and processing, so that developers can focus on developing UI. Relay and Apollo are two of the client-side solutions that are often mentioned.

  • Relay: Relay is a solution that Facebook has built for its own mobile applications. It is a GraphQL client that primarily meets its own needs.

  • Apollo: Apollo is the open source solution for the GraphQL community and is one of the more popular solutions used by companies. Apollo provides a complete set of solutions and documentation from IDE (Apollo Studio, GraphQL Cloud service platform), Client (Apollo Client) to Server (Apollo Server). For more information, visit ApollographQL.

Issues to be aware of with GraphQL

Scenarios aside, no solution is perfect, and GraphQL is no exception. N+1 problem is one of the most important problems in GraphQL.

N + 1 problem

The N+1 problem is caused by GraphQL’s execution mechanism: a GraphQL service is created by defining the type and the fields on that type, and then providing parsing functions for each field of each type.

For example, if we get a list of users through a GraphQL service, the type definition would look like this:

type Query {
  users: User[]
}

type User {
  id: ID
  name: String
  addressId: Int
  address: Address
}

type Address {
  id: ID
  province: String
  city: String
}
Copy the code

Meanwhile, its analytic function is as follows:

function queryUsers(request) {
  // Run a db query to get the list of users
}

function getAddress(user) {
  // Resolve address information through a single User object
  const { addressId } = user;
  // Query the address table by addressId
}
Copy the code

To put it simply, when we parse a field, we can only parse the field’s parent type object data. In the example above, the address field can only be resolved through a single instance object (suppose) User of its parent type User. N users have to query the address table N times. Plus the first batch query of the User list from the data, the entire request goes through N+1 database queries.

The solution is to collect all the addresses in the address parsing function, and then use the in operator to query all the addresses in the database, so you can query all the addresses in the database.

DataLoader enables us to implement the above optimizations, with the main core points being batch processing and caching. The code in this repository is very concise, should be less than 400 lines of code with the comments removed, interested readers can see how it works.

conclusion

This is the end of the introduction to GraphQL. Due to the limitations of space and level, there are many features to be skipped. Please leave your footprints in the comments section to discuss the questions.