En begyndervejledning til GraphQL

Et af de mest diskuterede udtryk i dag er API. Mange mennesker ved ikke nøjagtigt, hvad en API er. Grundlæggende står API for Application Programming Interface. Det er, som navnet siger, en grænseflade, som folk - udviklere, brugere, forbrugere - kan interagere med data med.

Du kan tænke på en API som bartender. Du beder bartenderen om en drink, og de giver dig, hvad du ønskede. Enkel. Så hvorfor er det et problem?

Siden starten på det moderne web har opbygning af API'er ikke været så hårdt som det lyder. Men at lære og forstå API'er var. Udviklere udgør størstedelen af ​​de mennesker, der bruger din API til at opbygge noget eller bare forbruge data. Så din API skal være så ren og så intuitiv som muligt. En veldesignet API er meget nem at bruge og lære. Det er også intuitivt, et godt punkt at huske på, når du begynder at designe din API.

Vi har brugt REST til at opbygge API'er i lang tid. Sammen med det kommer nogle problemer. Når du bygger en API ved hjælp af REST-design, står du over for nogle problemer som:

1) du har mange slutpunkter

2) det bliver meget sværere for udviklere at lære og forstå din API

3) der er over- og underhentning af information

For at løse disse problemer oprettede Facebook GraphQL. I dag synes jeg GraphQL er den bedste måde at opbygge API'er på. Denne artikel fortæller dig, hvorfor du skal begynde at lære det i dag.

I denne artikel vil du lære, hvordan GraphQL fungerer. Jeg vil vise dig, hvordan du opretter en meget veldesignet, effektiv og kraftfuld API ved hjælp af GraphQL.

Du har sikkert allerede hørt om GraphQL, da mange mennesker og virksomheder bruger det. Da GraphQL er open source, er dets samfund vokset enormt.

Nu er det tid for dig at begynde at lære i praksis, hvordan GraphQL fungerer og alt om dets magi.

Hvad er GraphQL?

GraphQL er et open source-forespørgselssprog udviklet af Facebook. Det giver os en mere effektiv måde at designe, oprette og forbruge vores API'er på. Dybest set er det erstatningen for REST.

GraphQL har mange funktioner, som:

  1. Du skriver de data, du ønsker, og du får nøjagtigt de data, du ønsker. Ikke mere overhentning af information, som vi er vant til med REST.
  2. Det giver os et enkelt slutpunkt , ikke mere version 2 eller version 3 til den samme API.
  3. GraphQL er stærkt skrevet , og med det kan du validere en forespørgsel inden for GraphQL-typesystemet før udførelse. Det hjælper os med at opbygge mere kraftfulde API'er.

Dette er en grundlæggende introduktion til GraphQL - hvorfor det er så stærkt, og hvorfor det vinder en masse popularitet i disse dage. Hvis du vil lære mere om det, anbefaler jeg dig at gå til GraphQL-webstedet og tjekke det ud.

Kom godt i gang

Hovedformålet med denne artikel er ikke at lære at opsætte en GraphQL-server, så vi kommer ikke dybt ind i det for nu. Målet er at lære, hvordan GraphQL fungerer i praksis, så vi bruger en GraphQL-server med nul konfiguration kaldet Graph️ Graphpack.

For at starte vores projekt skal vi oprette en ny mappe, og du kan navngive den, hvad du vil. Jeg vil navngive det graphql-server:

Åbn din terminal og skriv:

mkdir graphql-server

Nu skal du have npm eller garn installeret i din maskine. Hvis du ikke ved, hvad disse er, er npm og garn pakkehåndtering af JavaScript-programmeringssproget. For Node.js er standardpakkestyreren npm .

Skriv følgende kommando i din oprettede mappe:

npm init -y

Eller hvis du bruger garn:

yarn init 

npm opretter en package.jsonfil til dig, og alle de afhængigheder, du har installeret, og dine kommandoer vil være der.

Så nu skal vi installere den eneste afhængighed, som vi skal bruge.

☄️Graphpack giver dig mulighed for at oprette en GraphQL-server med nul konfiguration . Da vi lige er begyndt med GraphQL, vil dette hjælpe os meget med at fortsætte og lære mere uden at blive bekymrede for en serverkonfiguration.

I din terminal skal du installere den i din rodmappe således:

npm install --save-dev graphpack

Eller hvis du bruger garn, skal du gå sådan her:

yarn add --dev graphpack

Når Graphpack er installeret, skal du gå til vores scripts i package.jsonfilen og sætte følgende kode der:

"scripts": { "dev": "graphpack", "build": "graphpack build" }

Vi opretter en mappe, der hedder src, og det bliver den eneste mappe på hele vores server.

Create a folder called src, after that, inside our folder, we’re going to create three files only.

Inside our src folder create a file called schema.graphql. Inside this first file, put the following code:

type Query { hello: String }

In this schema.graphql file is going to be our entire GraphQL schema. If you don’t know what it is, I’ll explain later — don't worry.

Now, inside our src folder, create a second file. Call it resolvers.js and, inside this second file, put the following code:

import { users } from "./db"; const resolvers = { Query: { hello: () => "Hello World!" } }; export default resolvers;

This resolvers.js file is going to be the way we provide the instructions for turning a GraphQL operation into data.

And finally, inside your src folder, create a third file. Call this db.js and, inside this third file, put the following code:

export let users = [ { id: 1, name: "John Doe", email: "[email protected]", age: 22 }, { id: 2, name: "Jane Doe", email: "[email protected]", age: 23 } ];

In this tutorial we’re not using a real-world database. So this db.js file is going to simulate a database, just for learning purposes.

Now our src folder should look like this:

src |--db.js |--resolvers.js |--schema.graphql

Now, if you run the command npm run dev or, if you’re using yarn, yarn dev, you should see this output in your terminal:

You can now go to localhost:4000 . This means that we’re ready to go and start writing our first queries, mutations, and subscriptions in GraphQL.

You see the GraphQL Playground, a powerful GraphQL IDE for better development workflows. If you want to learn more about GraphQL Playground, click here.

Schema

GraphQL has its own type of language that’s used to write schemas. This is a human-readable schema syntax called Schema Definition Language (SDL). The SDL will be the same, no matter what technology you’re using — you can use this with any language or framework that you want.

This schema language its very helpful because it’s simple to understand what types your API is going to have. You can understand it just by looking right it.

Types

Types are one of the most important features of GraphQL. Types are custom objects that represent how your API is going to look. For example, if you’re building a social media application, your API should have types such as Posts, Users, Likes, Groups.

Types have fields, and these fields return a specific type of data. For example, we’re going to create a User type, we should have some name, email, and age fields. Type fields can be anything, and always return a type of data as Int, Float, String, Boolean, ID, a List of Object Types, or Custom Objects Types.

So now to write our first Type, go to your schema.graphql file and replace the type Query that is already there with the following:

type User { id: ID! name: String! email: String! age: Int }

Each User is going to have an ID, so we gave it an ID type. User is also going to have a name and email, so we gave it a String type, and an age, which we gave an Int type. Pretty simple, right?

But, what about those ! at the end of every line? The exclamation point means that the fields are non-nullable, which means that every field must return some data in each query. The only nullable field that we’re going to have in our User type will be age.

In GraphQL, you will deal with three main concepts:

  1. queries — the way you’re going to get data from the server.
  2. mutations — the way you’re going to modify data on the server and get updated data back (create, update, delete).
  3. subscriptions — the way you’re going to maintain a real-time connection with the server.

I’m going to explain all of them to you. Let’s start with Queries.

Queries

To explain this in a simple way, queries in GraphQL are how you’re going to get data. One of the most beautiful things about queries in GraphQL is that you are just going to get the exact data that you want. No more, no less. This has a huge positive impact in our API — no more over-fetching or under-fetching information as we had with REST APIs.

We’re going to create our first type Query in GraphQL. All our queries will end up inside this type. So to start, we’ll go to our schema.graphql and write a new type called Query:

type Query { users: [User!]! }

It’s very simple: the usersquery will return to us an array of one or more Users. It will not return null, because we put in the ! , which means it’s a non-nullable query. It should always return something.

But we could also return a specific user. For that we’re going to create a new query called user. Inside our Query type, put the following code:

user(id: ID!): User! 

Now our Query type should look like this:

type Query { users: [User!]! user(id: ID!): User! }

As you see, with queries in GraphQL we can also pass arguments. In this case, to query for a specific user, we’re going to pass its ID.

But, you may be wondering: how does GraphQL know where get the data? That’s why we should have a resolvers.js file. That file tells GraphQL how and where it's going to fetch the data.

First, go to our resolvers.js file and import the db.js that we just created a few moments ago. Your resolvers.js file should look like this:

import { users } from "./db"; const resolvers = { Query: { hello: () => "Hello World!" } }; export default resolvers;

Now, we’re going to create our first Query. Go to your resolvers.js file and replace the hello function. Now your Query type should look like this:

import { users } from "./db"; const resolvers = { Query: { user: (parent, { id }, context, info) => { return users.find(user => user.id === id); }, users: (parent, args, context, info) => { return users; } } }; export default resolvers;

Now, to explain how is it going to work:

Each query resolver has four arguments. In the user function, we’re going to pass id as an argument, and then return the specific user that matches the passed id. Pretty simple.

In the users function, we’re just going to return the users array that already exists. It’ll always return to us all of our users.

Now, we’re going to test if our queries are working fine. Go to localhost:4000 and put in the following code:

query { users { id name email age } }

It should return to you all of our users.

Or, if you want to return a specific user:

query { user(id: 1) { id name email age } }

Now, we’re going to start learning about mutations, one of the most important features in GraphQL.

Mutations

In GraphQL, mutations are the way you’re going to modify data on the server and get updated data back. You can think like the CUD (Create, Update, Delete) of REST.

We’re going to create our first type mutation in GraphQL, and all our mutations will end up inside this type. So, to start, go to our schema.graphql and write a new type called mutation:

type Mutation { createUser(id: ID!, name: String!, email: String!, age: Int): User! updateUser(id: ID!, name: String, email: String, age: Int): User! deleteUser(id: ID!): User! }

As you can see, we’re going to have three mutations:

createUser: we should pass an ID, name, email, and age. It should return a new user to us.

updateUser: we should pass an ID, and a new name, email, or age. It should return a new user to us.

deleteUser: we should pass an ID. It should return a new user to us.

Now, go to our resolvers.js file and below the Query object, create a new mutation object like this:

Mutation: { createUser: (parent, { id, name, email, age }, context, info) => { const newUser = { id, name, email, age }; users.push(newUser); return newUser; }, updateUser: (parent, { id, name, email, age }, context, info) => { let newUser = users.find(user => user.id === id); newUser.name = name; newUser.email = email; newUser.age = age; return newUser; }, 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]; } }

Now, our resolvers.js file should look like this:

import { users } from "./db"; const resolvers = { Query: { user: (parent, { id }, context, info) => { return users.find(user => user.id === id); }, users: (parent, args, context, info) => { return users; } }, Mutation: { createUser: (parent, { id, name, email, age }, context, info) => { const newUser = { id, name, email, age }; users.push(newUser); return newUser; }, updateUser: (parent, { id, name, email, age }, context, info) => { let newUser = users.find(user => user.id === id); newUser.name = name; newUser.email = email; newUser.age = age; return newUser; }, 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;

Now, we’re going to test if our mutations are working fine. Go to localhost:4000 and put in the following code:

mutation { createUser(id: 3, name: "Robert", email: "[email protected]", age: 21) { id name email age } }

It should return a new user to you. If you want to try making new mutations, I recommend you to try for yourself! Try to delete this same user that you created to see if it’s working fine.

Finally, we’re going to start learning about subscriptions, and why they are so powerful.

Subscriptions

As I said before, subscriptions are the way you’re going to maintain a real-time connection with a server. That means that whenever an event occurs in the server and whenever that event is called, the server will send the corresponding data to the client.

By working with subscriptions, you can keep your app updated to the latest changes between different users.

A basic subscription is like this:

subscription { users { id name email age } }

You will say it’s very similar to a query, and yes it is. But it works differently.

When something is updated in the server, the server will run the GraphQL query specified in the subscription, and send a newly updated result to the client.

We’re not going to work with subscriptions in this specific article, but if you want to read more about them click here.

Conclusion

Som du har set, er GraphQL en ny teknologi, der er virkelig stærk. Det giver os reel magt til at opbygge bedre og veldesignede API'er. Derfor anbefaler jeg, at du begynder at lære det nu. For mig vil det i sidste ende erstatte REST.

Tak, fordi du læste artiklen.

Følg mig på Twitter!

Følg mig på GitHub!

Jeg leder efter en fjernmulighed, så hvis har nogen, vil jeg meget gerne høre om det, så kontakt mig på min Twitter !