Erstellen von GraphQL-APIs mit Node
Veröffentlicht: 2022-12-20GraphQL ist das neue Schlagwort in der API-Entwicklung. Während RESTful-APIs nach wie vor die beliebteste Methode sind, um Daten aus Anwendungen bereitzustellen, weisen sie viele Einschränkungen auf, die GraphQL lösen soll.
GraphQL ist eine von Facebook entwickelte Abfragesprache, die 2015 in ein Open-Source-Projekt umgewandelt wurde. Sie bietet eine intuitive und flexible Syntax zur Beschreibung und zum Zugriff auf Daten in einer API.
In diesem Leitfaden erfahren Sie, wie Sie ein GraphQL-Node.js-Projekt erstellen. Wir verwenden GraphQL, um eine Todo-Anwendung im Express.js-Webframework für Node zu erstellen.
Was ist GraphQL?
Aus der offiziellen Dokumentation: „GraphQL ist eine Abfragesprache für APIs und eine Laufzeitumgebung zum Erfüllen dieser Abfragen mit Ihren vorhandenen Daten. GraphQL bietet eine vollständige und verständliche Beschreibung der Daten in Ihrer API, gibt Kunden die Möglichkeit, genau nach dem zu fragen, was sie brauchen, und nicht mehr, erleichtert die Entwicklung von APIs im Laufe der Zeit und ermöglicht leistungsstarke Entwicklertools.“
GraphQL ist eine serverseitige Laufzeit zum Ausführen von Abfragen unter Verwendung des Typsystems, das Sie für Ihre Daten definiert haben. Außerdem ist GraphQL nicht an eine bestimmte Datenbank oder Speicher-Engine gebunden. Stattdessen wird es von Ihrem vorhandenen Code und Datenspeicher unterstützt. Einen detaillierten Vergleich dieser Technologien erhalten Sie im Leitfaden GraphQL vs. RESTful API.
Um einen GraphQL-Dienst zu erstellen, definieren Sie zunächst Schematypen und erstellen Felder mit diesen Typen. Als Nächstes stellen Sie einen Funktionsauflöser bereit, der für jedes Feld und jeden Typ ausgeführt wird, wenn Daten von der Clientseite angefordert werden.
GraphQL-Terminologie
Das GraphQL-Typsystem wird verwendet, um zu beschreiben, welche Daten abgefragt und welche Daten bearbeitet werden können. Es ist der Kern von GraphQL. Lassen Sie uns verschiedene Möglichkeiten diskutieren, wie wir Daten in GraphQ beschreiben und manipulieren können.
Typen
GraphQL-Objekttypen sind Datenmodelle, die stark typisierte Felder enthalten. Es sollte eine 1-zu-1-Zuordnung zwischen Ihren Modellen und GraphQL-Typen geben. Unten sehen Sie ein Beispiel für den GraphQL-Typ:
type User { id: ID! # The "!" means required firstname: String lastname: String email: String username: String todos: [Todo] # Todo is another GraphQL type }
Abfragen
GraphQL Query definiert alle Abfragen, die ein Client auf der GraphQL-API ausführen kann. Sie sollten eine RootQuery definieren, die per Konvention alle vorhandenen Abfragen enthält.
Im Folgenden definieren und ordnen wir die Abfragen der entsprechenden RESTful-API zu:
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 }
Mutationen
Wenn GraphQL-Abfragen GET -Anforderungen sind, sind Mutationen POST -, PUT -, PATCH - und DELETE -Anforderungen, die die GraphQL-API manipulieren.
Wir werden alle Mutationen in einer einzigen RootMutation zusammenfassen , um Folgendes zu demonstrieren:
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 }
Sie haben die Verwendung von -input -Typen für die Mutationen wie UserInput , TodoInput bemerkt . Es empfiehlt sich immer, Eingabetypen zum Erstellen und Aktualisieren Ihrer Ressourcen zu definieren.
Sie können die Eingabetypen wie folgt definieren:
input UserInput { firstname: String! lastname: String email: String! username: String! }
Resolver
Resolver teilen GraphQL mit, was zu tun ist, wenn jede Abfrage oder Mutation angefordert wird. Es ist eine grundlegende Funktion, die die harte Arbeit erledigt, die Datenbankschicht zu treffen, um die CRUD-Vorgänge (Erstellen, Lesen, Aktualisieren, Löschen) auszuführen, einen internen RESTful-API-Endpunkt zu erreichen oder einen Microservice aufzurufen, um die Anfrage des Clients zu erfüllen.
Sie können eine neue Datei „ resolvers.js “ erstellen und den folgenden Code hinzufügen:
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
Das GraphQL-Schema ist das, was GraphQL der Welt aussetzt. Daher werden die Typen, Abfragen und Mutationen in das Schema aufgenommen, um der Welt zugänglich gemacht zu werden.
Im Folgenden erfahren Sie, wie Sie Typen, Abfragen und Mutationen der Welt zugänglich machen:
schema { query: RootQuery mutation: RootMutation }
In das obige Skript haben wir die RootQuery und RootMutation eingefügt , die wir zuvor erstellt haben, um sie der Welt zugänglich zu machen.
Wie funktioniert GraphQL mit Nodejs und Expressjs?
GraphQL bietet eine Implementierung für alle wichtigen Programmiersprachen, und Node.js ist nicht ausgenommen. Auf der offiziellen GraphQL-Website gibt es einen Abschnitt für JavaScript-Unterstützung, und es gibt auch andere Implementierungen von GraphQL, um das Schreiben und Programmieren in GraphQL zu vereinfachen.
GraphQL Apollo stellt eine Implementierung für Node.js und Express.js bereit und erleichtert den Einstieg in GraphQL.
Im nächsten Abschnitt erfahren Sie, wie Sie Ihre erste GraphQL-Anwendung im Nodes.js- und Express.js-Backend-Framework mit GraphQL Apollo erstellen und entwickeln.
Einrichten von GraphQL mit Express.js
Das Erstellen eines GraphQL-API-Servers mit Express.js ist einfach zu beginnen. In diesem Abschnitt werden wir untersuchen, wie man einen GraphQL-Server erstellt.
Projekt mit Express initialisieren
Zuerst müssen Sie ein neues Express.js-Projekt installieren und einrichten.
Erstellen Sie einen Ordner für Ihr Projekt und installieren Sie Express.js mit diesem Befehl:
cd <project-name> && npm init -y npm install express
Der obige Befehl erstellt eine neue package.json -Datei und installiert die Express.js-Bibliothek in Ihrem Projekt.
Als nächstes strukturieren wir unser Projekt wie im Bild unten gezeigt. Es wird verschiedene Module für die Funktionen des Projekts wie Benutzer, Todos usw. enthalten.
Initialisieren Sie GraphQL
Beginnen wir mit der Installation der GraphQL Express.js-Abhängigkeiten. Führen Sie zur Installation den folgenden Befehl aus:
npm install apollo-server-express graphql @graphql-tools/schema --save
Erstellen von Schemas und Typen
Als Nächstes erstellen wir eine index.js -Datei im Modulordner und fügen das folgende Code-Snippet hinzu:
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;
Code-Komplettlösung
Lassen Sie uns das Code-Snippet durcharbeiten und es aufschlüsseln:
Schritt 1
Zuerst haben wir die erforderlichen Bibliotheken importiert und Standardabfrage- und Mutationstypen erstellt. Die Abfrage und Mutation legen vorerst nur die Version der GraphQL-API fest. Im weiteren Verlauf werden wir jedoch die Abfrage und Mutation erweitern, um andere Schemas einzubeziehen.
Schritt 2:
Dann haben wir einen neuen Skalartyp für die Zeit und unseren ersten Resolver für die oben erstellte Abfrage und Mutation erstellt. Darüber hinaus haben wir auch ein Schema mit der Funktion makeExecutableEchema generiert.
Das generierte Schema enthält alle anderen Schemas, die wir importiert haben, und wird auch mehr enthalten, wenn wir sie erstellen und importieren.
Das obige Code-Snippet zeigt, dass wir verschiedene Schemas in die Funktion makeExecutableEchema importiert haben. Dieser Ansatz hilft uns bei der Strukturierung der Anwendung für Komplexität. Als Nächstes erstellen wir die von uns importierten Todo- und Benutzerschemata.
Todo-Schema erstellen
Das Todo-Schema zeigt einfache CRUD-Vorgänge, die Benutzer der Anwendung ausführen können. Unten ist das Schema, das die Todo-CRUD-Operation implementiert.
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 };
Code-Komplettlösung
Lassen Sie uns das Code-Snippet durcharbeiten und es aufschlüsseln:
Schritt 1:
Zuerst haben wir ein Schema für unser Todo mit GraphQL type , input und extend erstellt. Das Schlüsselwort extend wird verwendet, um neue Abfragen und Mutationen zu erben und zu der bestehenden Stammabfrage und Mutation hinzuzufügen, die wir oben erstellt haben.
Schritt 2:
Als Nächstes haben wir einen Resolver erstellt, der verwendet wird, um die richtigen Daten abzurufen, wenn eine bestimmte Abfrage oder Mutation aufgerufen wird.
Mit der Resolver-Funktion können wir individuelle Methoden für die Geschäftslogik und die Datenbankmanipulation erstellen, wie im Beispiel create-todo.js gezeigt.
Erstellen Sie eine create-user.js- Datei im Ordner <code>./mutations</code> und fügen Sie die Geschäftslogik hinzu, um ein neues Todo in Ihrer Datenbank zu erstellen.
const models = require('../../../models'); module.exports = async (root, { input }, context) => { return models.todos.push({ ...input }); };
Das obige Code-Snippet ist eine vereinfachte Möglichkeit, ein neues Todo in unserer Datenbank mit dem Sequelize ORM zu erstellen. Sie können mehr über Sequelize und dessen Einrichtung mit Node.js erfahren.
Sie können denselben Schritt ausführen, um abhängig von Ihrer Anwendung viele Schemas zu erstellen, oder Sie können das vollständige Projekt von GitHub klonen.
Als nächstes richten wir den Server mit Express.js ein und führen die neu erstellte Todo-Anwendung mit GraphQL und Node.js aus
Einrichten und Ausführen des Servers
Zuletzt richten wir unseren Server mit der apollo-server-express- Bibliothek ein, die wir zuvor installiert haben, und konfigurieren sie.
Der apollo-server-express ist ein einfacher Wrapper von Apollo Server für Express.js. Er wird empfohlen, da er so entwickelt wurde, dass er in die Entwicklung von Express.js passt.
Lassen Sie uns anhand der oben besprochenen Beispiele den Express.js-Server so konfigurieren, dass er mit dem neu installierten apollo-server-express funktioniert.
Erstellen Sie eine server.js -Datei im Stammverzeichnis und fügen Sie den folgenden Code ein:
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`) );
Im obigen Code haben Sie erfolgreich Ihren ersten CRUD-GraphQL-Server für Todos und Benutzer erstellt. Sie können Ihren Entwicklungsserver starten und über http://localhost:3000/graphql auf den Playground zugreifen. Wenn alles erfolgreich ist, sollte Ihnen der folgende Bildschirm angezeigt werden:
Zusammenfassung
GraphQL ist eine moderne Technologie, die von Facebook unterstützt wird und die mühsame Arbeit vereinfacht, die mit der Erstellung umfangreicher APIs mit RESTful-Architekturmustern verbunden ist.
Dieser Leitfaden hat GraphQL erläutert und gezeigt, wie Sie Ihre erste GraphQL-API mit Express.js entwickeln.
Teilen Sie uns mit, was Sie mit GraphQL erstellen.