Erstellen von serverlosen GraphQL- und REST-APIs mit AWS Amplify

Mit AWS Amplify können Entwickler schnell leistungsfähige Dienste in der Cloud erstellen und sich mit ihnen verbinden. Im vorigen Lernprogramm haben Sie erfahren, wie Sie Amplify in einem React-Projekt einrichten und Authentifizierung, S3-Speicher und Hosting verwenden. Wenn Sie eine Einführung in AWS Amplify benötigen, lesen Sie zuerst diesen Beitrag.

In diesem Beitrag gehen wir weiter mit React und AWS Amplify, um Funktionen wie verwaltete GraphQL-Datenschichten und Lambda-Funktionen zu erkunden.

Eine GraphQL-API hinzufügen

Sehen wir uns an, wie Sie eine AWS AppSync GraphQL-API zu unserem Projekt hinzufügen und mit der Verwendung in unserem Projekt beginnen können.

Die API, die wir erstellen werden, wird eine Restaurant-API sein, mit der wir mit den Restaurants, die wir mögen oder besuchen möchten, Schritt halten können.

Um die GraphQL-API zu unserem Projekt hinzuzufügen, können Sie den folgenden Befehl verwenden:

addiere api

Sie werden aufgefordert, einige Konfigurationsfragen zu beantworten. Wählen Sie die folgenden Optionen aus:

  • Servicetyp: GraphQL
  • API-Name: TutsGraphQLAPI
  • Berechtigungsart: API-Schlüssel
  • annotiertes GraphQL-Schema: N
  • Geführte Schemaerstellung: Y
  • Was beschreibt dein Projekt am besten? Einzelobjekt mit Feldern (z. B. „Todo“ mit ID, Name, Beschreibung)
  • Möchten Sie das Schema jetzt bearbeiten?? Y

Wenn Sie dazu aufgefordert werden, aktualisieren Sie das Schema wie folgt, und speichern Sie die Datei:

// in amplify-web-app / amplify / backend / api / TutsGraphQLAPI / schema.graphql type Restaurant @model id: ID! Name: String! Beschreibung: String

Dadurch wird nur ein einzelner Datentyp erstellt-Restaurant-mit erforderlichen ID- und Namensfeldern sowie einer optionalen Beschreibung.

Lassen Sie uns nun die Aktualisierungen auf unser Konto übertragen:

Push verstärken

Nun wurde die API erstellt!

Was ist hier gerade passiert? AWS Amplify verwendete die integrierte GraphQL-Umwandlungsbibliothek zum Erstellen einer vollständigen GraphQL-API, einschließlich zusätzlicher Schemata, Resolver und einer Datenquelle.

Um die neue AWS AppSync-API jederzeit nach ihrer Erstellung anzuzeigen, können Sie das Dashboard unter https://console.aws.amazon.com/appsync aufrufen und auf die soeben erstellte API klicken (vergewissern Sie sich, dass Ihre Region dies ist.) richtig eingestellt). Im AWS AppSync-Dashboard können Sie die API-Konfiguration anzeigen und Abfragen und Mutationen für die API durchführen.

GraphQL-Mutationen ausführen

Lassen Sie uns als Nächstes mit der API aus unserer React-Anwendung interagieren.

Als erstes möchten wir eine Mutation erstellen. In GraphQL entsprechen Mutationen den REST-Werten STELLEN, DRÜCKEN und LÖSCHEN Operationen. Da sich in unserer Datenbank noch keine Daten befinden, erstellen wir eine Mutation, um ein neues Restaurantelement zu erstellen.

Dazu werden wir importieren API und graphqlOperation von AWS Amplify, Definieren einer Mutation und Ausführen der Mutation.

Schauen wir uns eine Beispiel-App an, die eine Mutation implementiert. Im App.js, Zunächst importieren wir React, unsere App-CSS und die erforderlichen AWS Amplify-Komponenten.

importieren Sie React, Component aus 'reagieren'; import './App.css'; importieren withAuthenticator aus 'aws-amplify-reag' importieren API, graphqlOperation aus 'aws-amplify'

Als Nächstes definieren wir eine Mutation, um ein Restaurant zu erstellen. Wir geben an, dass die Mutation einen Namen und eine Beschreibung akzeptiert und benannt wird createRestaurant. Diese Mutation wurde automatisch definiert, als wir das erstellt haben Restaurant Schema oben. Beachten Sie, dass die Mutation in GraphQL-einer domänenspezifischen Abfragesprache angegeben ist.

const CreateRestaurant = 'mutation ($ name: String !, $ description: String) createRestaurant (Eingabe: Name: $ Name Beschreibung: $ Beschreibung) ID Name Beschreibung'

Jetzt erstellen wir unsere App-Komponente.

Klasse App erweitert die Komponente // Erzeuge den Anfangsstatus state = name: ", description:" // Aktualisierungsstatus, wenn der Benutzer die Eingaben onChange = e => this.setState ([e.target.name]: e) eingibt .target.value) // Funktion zum Ausführen der Mutation definieren // Komponente rendern

Als nächstes noch im App Komponente definieren wir eine Funktion, um die Mutation auszuführen. Dies führt die Mutation durch Aufruf aus API.graphql, Weitergabe der Mutation und Daten.

 // Funktion definieren, um die Mutation auszuführen createRestaurant = async () => if (this.state.name === "|| this.state.description ===") return try const restaurant = name: this.state .name, Beschreibung: this.state.description erwarten API.graphql (graphqlOperation (CreateRestaurant, restaurant)) this.setState (name: ", description:") console.log ('restaurant wurde erfolgreich erstellt!') (err) console.log ('Fehler beim Erstellen eines Restaurants ...')

Dann rendern wir die Komponente und verknüpfen unsere Änderungshandler- und Mutationsfunktionen.

 // Rendern der Komponente render () return ( 
)

Zum Schluss exportieren wir die App Komponente mit Authentifizierung.

export default withAuthenticator (App, includeGreetings: true);

Sie sollten diesen Code ausführen und mit der Erstellung neuer Restaurantelemente in der API beginnen können.

Öffnen Sie das AWS AppSync-Dashboard, wählen Sie Ihre API aus und klicken Sie auf, um die tatsächliche Datenquelle anzuzeigen, um festzustellen, ob die Daten vorhanden sind Datenquellen im linken Menü und klicken Sie dann auf Ressourcenname. Dadurch wird die Amazon DynamoDB-Tabelle geöffnet. In der Tabelle können Sie die Daten in sehen Artikel Tab.

GraphQL-Abfragen ausführen

Als Nächstes wollen wir uns ansehen, wie Daten von der API abgefragt werden. Wir werden dies in drei Schritten umsetzen:

  1. eine Abfrage definieren
  2. Führen Sie die Abfrage aus, wenn die App geladen wird
  3. Speichern Sie das Ergebnis der Abfrage in unserem Status und rendern Sie es in der Benutzeroberfläche

Zuerst definieren wir die Abfrage in eine neue Komponente. Wieder verwenden wir die GraphQL-Sprache, um die Abfrage festzulegen. Wir benutzen die listRestaurants Abfrage, die automatisch definiert wurde, als wir die Restaurants Schema. Das folgende Snippet gibt an, dass wir eine Liste mit Elementen erwarten, die jeweils eine ID, einen Namen und eine Beschreibung enthalten.

const ListRestaurants = 'query listRestaurants Elemente ID-Name-Beschreibung

Als Nächstes müssen wir einen zusätzlichen Anfangsstatus hinzufügen, um das vom Server zurückgegebene Array von Restaurants aufzunehmen.

state = name: ", description:", restaurants: []

Wir müssen auch eine hinzufügen componentDidMount Lebenszyklusereignis, um Daten vom GraphQL-Server abzufragen. Diese async-Methode aktualisiert den Komponentenstatus, wenn die Restaurantliste vom Server zurückgegeben wird.

async componentDidMount () try const restaurants = erwarte API.graphql (graphqlOperation (ListRestaurants)) console.log ('restaurants:', restaurants) this.setState (restaurants: restaurants.data.listRestaurants.items) catch ( err) console.log ('Fehler beim Abrufen von Daten:', err)

Zum Schluss erstellen wir eine Komponente, die die Zuordnung übernimmt Restaurants Array vom Komponentenzustand zu HTML.

this.state.restaurants.map ((r, i) => ( 

r.name

r.description

))

Wenn wir nun die App ausführen, werden wir feststellen, dass die Daten der API in einer Liste auf dem Bildschirm dargestellt werden. Die App zeigt jedoch keine Änderungen an, wenn die Daten aktualisiert werden, beispielsweise wenn Sie ein neues Restaurant hinzufügen. 

Also für den Anfang, aktualisieren wir die createRestaurant Methode, um eine optimistische Antwort auf die Benutzeroberfläche bereitzustellen. Wenn Sie jetzt ein neues Element erstellen, wird die Datenbank zwar aktualisiert, aber die Benutzeroberfläche kennt das neue Element noch nicht. Um dies zu beheben, aktualisieren wir das Restaurant-Array im createRestaurant Methode durch Hinzufügen des neuen Elements zum Array:

createRestaurant = async () => if (this.state.name === "|| this.state.description ===") return try const restaurant = name: this.state.name, description: this. state.description const restaurants = [… this.state.restaurants, restaurant] this.setState (name: ", description:", restaurants) wartet auf API.graphql (graphqlOperation (CreateRestaurant, restaurant)) console.log (' Restaurant erfolgreich erstellt! ') catch (err) console.log (' Fehler beim Erstellen von Restaurant… ')

Echtzeit-Datenabonnements

Als nächstes möchten wir mit Echtzeitdaten arbeiten können. In GraphQL können Sie mithilfe von Abonnements Daten in Echtzeit abhören. Wenn neue Daten verfügbar sind, wird das Abonnement ausgelöst und die neuen Daten werden über das Abonnement weitergeleitet. Es liegt an uns auf Kundenseite, mit diesen neuen Daten umzugehen.

In unserer App abonnieren wir eine Reihe von Restaurants und erstellen eine onCreateRestaurant Abonnement, das jedes Mal ausgelöst wird, wenn ein neues Restaurant erstellt wird. Wir nehmen dann den neuen Artikel aus dem Abonnement, aktualisieren unser vorhandenes Array und rufen an setState um die Benutzeroberfläche mit den neuen Daten erneut zu rendern.

Genau wie bei Mutationen und Abfragen definieren wir zunächst die Subskription in der domänenspezifischen GraphQL-Sprache.

// Definiere die Subskription const OnCreateRestaurant = 'subscription onCreateRestaurant id name description'

Das Abonnement wird im erstellt componentDidMount Lebenszyklusmethode vor oder nach der GraphQL-Abfrage, die wir bereits eingerichtet haben:

async componentDidMount () try const restaurants = erwarte API.graphql (graphqlOperation (ListRestaurants)) console.log ('restaurants:', restaurants) this.setState (restaurants: restaurants.data.listRestaurants.items) catch ( err) console.log ('Fehler beim Abrufen von Daten:', err) API.graphql (graphqlOperation (OnCreateRestaurant)) .subscribe (next: eventData => const data = eventData.value.data.onCreateRestaurant console.log ( 'data:', data) const restaurants = [… this.state.restaurants.filter (r => r.name! == data.name && r.description! == data.description), data] this.setState ( restaurants))

Wenn Sie nun zwei Browserfenster öffnen, sollten Sie in der Lage sein, eine Mutation in einem Bildschirm zu erstellen und die Aktualisierung auf allen anderen Bildschirmen zu sehen.

Wenn du dir das anschaust .Filter Wenn Sie das neue Restaurants-Array im Abonnement erstellen, können Sie feststellen, ob Duplikate vorhanden sind, die denselben Namen und die gleiche Beschreibung enthalten. Ein besserer Weg, dies in der Produktion zu tun, wäre möglicherweise die Erstellung einer eindeutigen Client-ID, die ebenfalls in der Datenbank gespeichert ist, und anhand dieser Kennung filtern.

Erstellen einer REST-API mit AWS Lambda

GraphQL ist eine wunderbare Spitzentechnologie, aber manchmal erfordert unser Projekt, dass wir eine traditionelle REST-API erstellen. Mit AWS Lambda und Amplify ist es auch einfach, serverlose REST-APIs mithilfe der CLI zu erstellen.

Bei der Erstellung der GraphQL-API haben wir die verstärken create api Befehl. Dieser Befehl gibt uns die Möglichkeit, entweder eine GraphQL-API oder eine REST-API zu erstellen. Die REST-API kann für die Verwendung einer eigenständigen serverlosen Express-Funktion oder einer serverlosen JavaScript-Funktion konfiguriert werden, die für die Verwendung mit Amazon DynamoDB-CRUD-Vorgängen vorkonfiguriert ist.

Die Option, die wir für diese API verwenden werden, ist eine serverlose Express-Funktion.

Lassen Sie uns fortfahren und die neue Funktion hinzufügen:

addiere api

Wie üblich werden Sie dazu aufgefordert, einige Konfigurationsdetails einzugeben. Geben Sie die folgenden Optionen an:

  • Servicetyp: SICH AUSRUHEN
  • Geben Sie einen Ressourcennamen ein, der innerhalb des Projekts verwendet wird: z. amplifyrestapi
  • Geben Sie einen Pfad für die REST-Endpunkte ein: z. /Menschen
  • Lambda-Quelle: Erstellen Sie eine neue Lambda-Funktion
  • AWS Lambda-Funktionsname: Amplifestestfunktion
  • Funktionsvorlage: Serverlose Expressfunktion (Integration mit Amazon API Gateway)
  • Bearbeiten Sie jetzt die lokale Lambda-Funktion? Y

Jetzt können Sie die Lambda-Funktion lokal bearbeiten. In der Datei ersetzen wir das vorhandene app.get ('/ Personen') Methode mit der folgenden:

// amplify-web-app / amplify / backend / function / amplifyrestapi / src / app.js app.get ('/ people', Funktion (req, res) const people = [Name: "Nader",  name: "Amanda", name: "Chris", name: ""] res.json (success: true, people));

Dies gibt nur eine konstante Liste von Namen für Demo-Zwecke zurück. Speichern Sie diese Datei und fahren Sie mit den folgenden Antworten fort:

  • API-Zugriff einschränken? Ja
  • Wer sollte Zugriff haben?? Nur authentifizierte Benutzer
  • Welche Art von Zugriff möchten Sie für authentifizierte Benutzer?? lesen
  • Einen weiteren Pfad hinzufügen? N

Dadurch wurde vor Ort eine neue Lambda-Funktion erstellt, die wir bei Bedarf aktualisieren und auf unser Konto übertragen können. Der Code für diese Lambda-Funktion befindet sich unter verstärken / backend / funktion / amplifyrestapi / src.

Nun lass uns die Updates auf unser Konto pushen:

Push verstärken

REST-API vom Client abfragen

Nun ist unsere Lambda-Funktion in Betrieb und wir können damit interagieren!

Lassen Sie uns zunächst die Daten von der neuen API abfragen und in unserer Benutzeroberfläche anzeigen. Dazu verwenden wir die API Klasse von Amplify, rufend API.get. Im vorigen Abschnitt haben wir verwendet API.graphql Um Anfragen an unsere GraphQL-API zu stellen, gibt es viele Methoden, die in der API-Klasse verfügbar sind. Weitere Informationen zur API-Klasse finden Sie in den offiziellen Dokumenten.

importieren Sie API aus 'aws-amplify' // 1. Erstellen Sie im ursprünglichen Zustand ein leeres Array von Personen. state = people: [] // 2. In componentDidMount holen wir diese Daten mit der API-Klasse try ab const peopleData = await API.get ('amplifyrestapi', '/ people') this.setState (people: peopleData.people) catch (err) console.log ('Fehler beim Abrufen der Lambda-API') / / 3. Rendern der Personendaten an die Benutzeroberfläche in der Render-Methode this.state.people.map ((person, index) => ( 

Name der Person

))

Jetzt sollten wir in der Lage sein, die App auszuführen, die Personendaten von unserer API abzurufen und auf dem Bildschirm darzustellen.

Aktualisieren einer Lambda-Funktion über die CLI

Neben der Erstellung einer neuen Lambda-Funktion können wir auch unsere Lambda-Funktion über die CLI aktualisieren.

Ändern Sie die Funktion so, dass sie auf eine API trifft und Daten abruft, anstatt Hardcoding-Konstanten. Dazu benutzen wir die Axios Bibliothek für die HTTP-Anforderungen, und wir holen Daten von der Star Wars-API ab.

Um Axios zu verwenden, müssen wir zu navigieren verstärken / backend / funktion / amplifyrestapi / srcund installieren Sie es dort. Axios ist im Projektordner der Lambda-Funktion installiert, nicht im Hauptordner der App, da es auf der serverseitigen Lambda-Funktion ausgeführt wird.

garn add axios # oder npm axios installieren

Nun das Axios installiert ist, aktualisieren wir die Lambda-Funktion, um Daten von der Star Wars-API abzurufen:

var axios = required ('axios') app.get ('/ people', Funktion (req, res) axios.get ('https://swapi.co/api/people/') .then (antwort => res.json (success: true, people: response.data.results)) .catch (error => res.json (success: false, error));

Speichern Sie nun die Datei und führen Sie sie aus Push verstärken aus dem Hauptprojektordner, um Ihre Lambda-Funktion in der Cloud zu aktualisieren:

Push verstärken

Jetzt ist unsere API aktualisiert und einsatzbereit!

Wenn wir die App aktualisieren, sollten wir jetzt die Daten sehen, die von der Star Wars-API zurückgegeben werden.

Fazit

In dieser Serie haben Sie gelernt, wie Sie AWS Amplify einsetzen und zu Ihrem React-Projekt hinzufügen. Außerdem müssen Sie Authentifizierung, Speicher, Hosting und eine GraphQL- oder REST-API hinzufügen, ohne einen Server manuell programmieren oder bereitstellen zu müssen . Das ist viel Macht für App-Entwickler! 

Ich hoffe, diese Posts haben Sie dazu inspiriert, Ihre eigenen serverlosen Web-Apps mit Serverless-Technologie und AWS Amplify zu erstellen! Teilen Sie uns mit, was Sie in den Kommentaren unten denken.