GraphQL er det nye buzzword inden for API-udvikling. Mens RESTful API’er fortsat er den mest populære måde at udstille data fra applikationer på, har de mange begrænsninger, som GraphQL har til formål at løse.
GraphQL er et forespørgselssprog, der er skabt af Facebook, og som blev omdannet til et open source-projekt i 2015. Det tilbyder en intuitiv og fleksibel syntaks til at beskrive og tilgå data i et API.
Denne vejledning vil undersøge, hvordan man opbygger et GraphQL Node.js-projekt. Vi vil bruge GraphQL til at bygge en Todo-applikation i Express.js webrammen til Node.
Hvad er GraphQL?
Fra den officielle dokumentation: “GraphQL er et forespørgselssprog til API’er og en runtime til at opfylde disse forespørgsler med dine eksisterende data. GraphQL giver en komplet og forståelig beskrivelse af dataene i din API, giver klienterne mulighed for at spørge om præcis det, de har brug for, og ikke mere, gør det lettere at udvikle API’er over tid og muliggør kraftfulde udviklerværktøjer.”
GraphQL er en server-side runtime til udførelse af forespørgsler ved hjælp af det typesystem, du har defineret for dine data. GraphQL er heller ikke bundet til nogen specifik database eller lagringsmotor. I stedet bakkes den op af din eksisterende kode og datalagring. Du kan få en detaljeret sammenligning af disse teknologier med GraphQL vs. RESTful API-guiden.
Hvis du vil oprette en GraphQL-tjeneste, starter du med at definere skematyper og oprette felter ved hjælp af disse typer. Dernæst leverer du en funktionsopløser, der skal udføres på hvert felt og hver type, når der anmodes om data fra klientsiden.
GraphQL-terminologi
GraphQL-typesystemet bruges til at beskrive, hvilke data der kan forespørges, og hvilke data du kan manipulere. Det er kernen i GraphQL. Lad os diskutere forskellige måder, hvorpå vi kan beskrive og manipulere data i GraphQ.
Objekttyper
GraphQL-objekttyper er datamodeller, der indeholder stærkt skrevne felter. Der skal være en 1-til-1-mapping mellem dine modeller og GraphQL-typer. Nedenfor er et eksempel på en GraphQL-type:
type User {
id: ID! # The "!" means required
firstname: String
lastname: String
email: String
username: String
todos: [Todo] # Todo is another GraphQL type
}
Queries
GraphQL Query definerer alle de forespørgsler, som en klient kan køre på GraphQL API’et. Du bør definere en RootQuery
, som vil indeholde alle eksisterende forespørgsler som en konvention.
Nedenfor definerer og mapper vi forespørgslerne til den tilsvarende RESTful API:
type RootQuery {
user(id: ID): User # Corresponds to GET /api/users/:id
users: [User] # Corresponds to GET /api/users
todo(id: ID!): Todo # Corresponds to GET /api/todos/:id
todos: [Todo] # Corresponds to GET /api/todos
}
Mutations
Hvis GraphQL-forespørgsler er GET
-forespørgsler, er mutationer POST
, PUT
, PATCH
og DELETE
-forespørgsler, der manipulerer GraphQL API.
Vi vil placere alle mutationer i en enkelt RootMutation
for at demonstrere dem:
type RootMutation {
createUser(input: UserInput!): User # Corresponds to POST /api/users
updateUser(id: ID!, input: UserInput!): User # Corresponds to PATCH /api/users
removeUser(id: ID!): User # Corresponds to DELETE /api/users
createTodo(input: TodoInput!): Todo
updateTodo(id: ID!, input: TodoInput!): Todo
removeTodo(id: ID!): Todo
}
Du har bemærket brugen af -input
typer til mutationerne såsom UserInput
, TodoInput
. Det er altid den bedste praksis altid at definere inputtyper til oprettelse og opdatering af dine ressourcer.
Du kan definere inputtyperne som nedenfor:
input UserInput {
firstname: String!
lastname: String
email: String!
username: String!
}
Resolvers
Resolvers fortæller GraphQL, hvad der skal ske, når der anmodes om hver forespørgsel eller mutation. Det er en grundlæggende funktion, der gør det hårde arbejde med at ramme databaselaget for at udføre CRUD-operationer (oprette, læse, opdatere, slette), ramme et internt RESTful API endpoint eller kalde en microservice for at opfylde klientens anmodning.
Du kan oprette en ny resolvers.js-fil og tilføje følgende kode:
import sequelize from '../models';
export default function resolvers () {
const models = sequelize.models;
return {
// Resolvers for Queries
RootQuery: {
user (root, { id }, context) {
return models.User.findById(id, context);
},
users (root, args, context) {
return models.User.findAll({}, context);
}
},
User: {
todos (user) {
return user.getTodos();
}
},
}
// Resolvers for Mutations
RootMutation: {
createUser (root, { input }, context) {
return models.User.create(input, context);
},
updateUser (root, { id, input }, context) {
return models.User.update(input, { ...context, where: { id } });
},
removeUser (root, { id }, context) {
return models.User.destroy(input, { ...context, where: { id } });
},
// ... Resolvers for Todos go here
}
}
Schema
GraphQL-skemaet er det, som GraphQL eksponerer for verden. Derfor vil typer, forespørgsler og mutationer blive inkluderet i skemaet for at blive eksponeret for verden.
Nedenfor kan du se, hvordan du eksponerer typer, forespørgsler og mutationer for verden:
schema {
query: RootQuery
mutation: RootMutation
}
I ovenstående script har vi inkluderet RootQuery
og RootMutation
, som vi har oprettet tidligere, og som skal eksponeres for verden.
Hvordan fungerer GraphQL med Node.js og Express.js?
GraphQL tilbyder en implementering til alle større programmeringssprog, og Node.js er ikke undtaget. På det officielle GraphQL-websted er der en sektion for JavaScript-understøttelse, og der er også andre implementeringer af GraphQL for at gøre det nemt at skrive og kode.
GraphQL Apollo tilbyder en implementering til Node.js og Express.js og gør det nemt at komme i gang med GraphQL.
Du vil lære at oprette og udvikle din første GraphQL-applikation i Node.js og Express.js backend-ramme ved hjælp af GraphQL Apollo i næste afsnit.
Opsætning af GraphQL med Express.js
Det er ligetil at opbygge en GraphQL API-server med Express.js for at komme i gang. I dette afsnit vil vi undersøge, hvordan man opbygger en GraphQL-server.
Initialisér projekt med Express
Først skal du installere og opsætte et nyt Express.js-projekt. Opret en mappe til dit projekt, og installer Express.js ved hjælp af denne kommando:
cd <project-name> && npm init -y
npm install express
Ovenstående kommando opretter en ny package.json-fil og installerer Express.js-biblioteket i dit projekt.
Dernæst strukturerer vi vores projekt som vist i billedet nedenfor. Det vil indeholde forskellige moduler til projektets funktioner som f.eks. brugere, todos osv.
Initialisere GraphQL
Lad os starte med at installere GraphQL Express.js-afhængighederne. Kør følgende kommando for at installere:
npm install apollo-server-express graphql @graphql-tools/schema --save
Oprettelse af skemaer og typer
Dernæst opretter vi en index.js-fil i mappen modules og tilføjer følgende kodestump:
const { gql } = require('apollo-server-express');
const users = require('./users');
const todos = require('./todos');
const { GraphQLScalarType } = require('graphql');
const { makeExecutableSchema } = require('@graphql-tools/schema');
const typeDefs = gql`
scalar Time
type Query {
getVersion: String!
}
type Mutation {
version: String!
}
`;
const timeScalar = new GraphQLScalarType({
name: 'Time',
description: 'Time custom scalar type',
serialize: (value) => value,
});
const resolvers = {
Time: timeScalar,
Query: {
getVersion: () => `v1`,
},
};
const schema = makeExecutableSchema({
typeDefs: [typeDefs, users.typeDefs, todos.typeDefs],
resolvers: [resolvers, users.resolvers, todos.resolvers],
});
module.exports = schema;
Kode gennemgang
Lad os gennemgå kodeudsnittet og bryde det ned:
Trin 1
Først importerede vi de nødvendige biblioteker og oprettede standard forespørgsels- og mutationstyper. Forespørgsels- og mutationstyperne indstiller kun versionen af GraphQL API’et for nu. Vi vil dog udvide forespørgslen og mutationen til at omfatte andre skemaer, efterhånden som vi fortsætter.
Trin 2:
Derefter oprettede vi en ny scalartype for tid og vores første resolver til den forespørgsel og mutation, der er oprettet ovenfor. Derudover genererede vi også et skema ved hjælp af funktionen makeExecutableSchema
.
Det genererede skema indeholder alle de andre skemaer, vi importerede, og vil også indeholde flere, når vi opretter og importerer dem.
Ovenstående kodestump viser, at vi importerede forskellige skemaer i makeExecutableSchema-funktionen. Denne fremgangsmåde hjælper os med at strukturere applikationen med henblik på kompleksitet. Dernæst skal vi oprette de Todo- og User-skemaer, som vi importerede.
Oprettelse af Todo-skema
Todo-skemaet viser simple CRUD-operationer, som brugerne af applikationen kan udføre. Nedenfor er det skema, der implementerer Todo CRUD-operationen.
const { gql } = require('apollo-server-express');
const createTodo = require('./mutations/create-todo');
const updateTodo = require('./mutations/update-todo');
const removeTodo = require('./mutations/delete-todo');
const todo = require('./queries/todo');
const todos = require('./queries/todos');
const typeDefs = gql`
type Todo {
id: ID!
title: String
description: String
user: User
}
input CreateTodoInput {
title: String!
description: String
isCompleted: Boolean
}
input UpdateTodoInput {
title: String
description: String
isCompleted: Boolean
} extend type Query {
todo(id: ID): Todo!
todos: [Todo!]
}
extend type Mutation {
createTodo(input: CreateTodoInput!): Todo
updateTodo(id: ID!, input: UpdateTodoInput!): Todo
removeTodo(id: ID!): Todo
}
`;
// Provide resolver functions for your schema fields
const resolvers = {
// Resolvers for Queries
Query: {
todo,
todos,
},
// Resolvers for Mutations
Mutation: {
createTodo,
updateTodo,
removeTodo,
},
};
module.exports = { typeDefs, resolvers };
Gennemgang af kode
Lad os gennemgå kodeudsnittet og bryde det ned:
Trin 1:
Først oprettede vi et skema for vores Todo ved hjælp af GraphQL type
, input
og extend
. Nøgleordet extend
bruges til at arve og tilføje nye forespørgsler og mutationer til den eksisterende rodforespørgsel og mutation, som vi oprettede ovenfor.
Trin 2:
Dernæst oprettede vi en resolver, som bruges til at hente de korrekte data, når en bestemt forespørgsel eller mutation kaldes.
Når resolver-funktionen er på plads, kan vi oprette individuelle metoder til forretningslogikken og databasemanipulationen som vist i eksemplet create-todo.js.
Opret en fil create-user.js i mappen ./mutations/
, og tilføj forretningslogikken for at oprette en ny Todo i din database.
const models = require('../../../models');
module.exports = async (root, { input }, context) => {
return models.todos.push({ ...input });
};
Kodestumpen ovenfor er en forenklet måde at oprette en ny Todo i vores database ved hjælp af Sequelize ORM. Du kan få mere at vide om Sequelize, og hvordan du konfigurerer det med Node.js.
Du kan følge det samme trin for at oprette mange skemaer afhængigt af din applikation, eller du kan klone det komplette projekt fra GitHub.
Dernæst skal vi opsætte serveren med Express.js og køre den nyoprettede Todo-applikation med GraphQL og Node.js.
Opsætning og kørsel af serveren
Til sidst vil vi opsætte vores server ved hjælp af apollo-server-express
-biblioteket, som vi installerede tidligere, og konfigurere den.
apollo-server-express
er en simpel wrapper af Apollo Server for Express.js, Det anbefales, fordi det er udviklet til at passe ind i Express.js udvikling.
Ved hjælp af de eksempler vi diskuterede ovenfor, lad os konfigurere Express.js-serveren til at arbejde med det nyligt installerede apollo-server-express
.
Opret en server.js-fil i rodmappen, og indsæt følgende kode:
const express = require('express');
const { ApolloServer } = require('apollo-server-express');
const schema = require('./modules');
const app = express();
async function startServer() {
const server = new ApolloServer({ schema });
await server.start();
server.applyMiddleware({ app });
}
startServer();
app.listen({ port: 3000 }, () =>
console.log(`Server ready at http://localhost:3000`)
);
I ovenstående kode har du med succes oprettet din første CRUD GraphQL-server til Todos og Users. Du kan starte din udviklingsserver og få adgang til legepladsen ved hjælp af http://localhost:3000/graphql. Hvis alt er lykkedes, bør du blive præsenteret for nedenstående skærm:
Oversigt
GraphQL er en moderne teknologi, der understøttes af Facebook, og som forenkler det kedelige arbejde med at skabe API’er i stor skala med RESTful-arkitekturmønstre.
Denne vejledning har belyst GraphQL og demonstreret, hvordan du udvikler din første GraphQL API med Express.js.
Lad os vide, hvad du bygger ved hjælp af GraphQL i kommentarerne nedenfor.
Skriv et svar