Hoe Serverless GraphQL en REST API's te maken met behulp van AWS Amplify

Met AWS Amplify kunnen ontwikkelaars snel krachtige services in de cloud maken en hiermee verbinding maken. In de vorige zelfstudie hebt u geleerd hoe u Amplify in een React-project kunt instellen en hoe u verificatie, S3-opslag en hosting kunt gebruiken. Als je een inleiding tot AWS Amplify nodig hebt, lees dan eerst die post.

In dit bericht gaan we verder met React en AWS Amplify, waarbij we functies onderzoeken zoals een beheerde GraphQL-gegevenslaag en lambda-functies.

Een GraphQL API toevoegen

Laten we eens kijken hoe we een AWS AppSync GraphQL API aan ons project kunnen toevoegen en deze vanuit ons project kunnen gebruiken.

De API die we zullen maken, zal een restaurant-API zijn om bij te houden met restaurants die we leuk vinden of zouden willen bezoeken.

Om de GraphQL API aan ons project toe te voegen, kunnen we de volgende opdracht gebruiken:

versterken add api

U wordt gevraagd om enkele configuratievragen te beantwoorden. Selecteer de volgende opties:

  • Dienst Type: GraphQL
  • API-naam: TutsGraphQLAPI
  • autorisatie type: API sleutel
  • geannoteerd GraphQL-schema: N
  • begeleide schema-creatie: Y
  • Wat jouw project het beste beschrijft? Eén object met velden (bijvoorbeeld "Todo" met ID, naam, beschrijving)
  • Wilt u het schema nu bewerken?? Y

Wanneer u daarom wordt gevraagd, werkt u het schema bij naar het volgende en slaat u het bestand vervolgens op:

// bevindt zich op amplify-web-app / amplify / backend / api / TutsGraphQLAPI / schema.graphql type Restaurant @model id: ID! naam: String! description: String

Hiermee wordt slechts één gegevenstype gemaakt-Restaurant-met vereiste id- en naamvelden en een optionele beschrijving.

Laten we vervolgens de updates op ons account duwen:

versterken push

Nu is de API gemaakt!

Wat is hier net gebeurd? AWS Amplify gebruikte de ingebouwde GraphQL Transform-bibliotheek om een ​​complete GraphQL-API te maken, inclusief extra schema, resolvers en een gegevensbron.

Als u de nieuwe AWS AppSync API op elk gewenst moment na de aanmaak wilt bekijken, gaat u naar het dashboard op https://console.aws.amazon.com/appsync en klikt u op de zojuist gemaakte API (zorg ervoor dat uw regio is ingesteld op correct ingesteld). Vanuit het AWS AppSync-dashboard kunt u de API-configuratie bekijken en query's en mutaties uitvoeren op de API.

GraphQL-mutaties uitvoeren

Laten we vervolgens de API van onze React-applicatie gebruiken.

Het eerste wat we willen doen is een mutatie maken. In GraphQL zijn mutaties het equivalent van REST's LEGGEN, DUWEN en DELETE activiteiten. Omdat we nog geen gegevens in onze database hebben, maken we een mutatie om een ​​nieuw restaurantitem te maken.

Om dit te doen, zullen we importeren API en graphqlOperation van AWS Amplify, definieer een mutatie en voer vervolgens de mutatie uit.

Laten we eens kijken naar een voorbeeldapp die een mutatie implementeert. In App.js, eerst importeren we React, onze app-CSS en de benodigde AWS Amplify-componenten.

import Reageren, Component uit 'reageren'; import './App.css'; import withAuthenticator uit 'aws-amplify-react' import API, graphqlOperation uit 'aws-amplify'

Vervolgens definiëren we een mutatie om een ​​restaurant te maken. We specificeren dat de mutatie een naam en beschrijving accepteert en een naam heeft createRestaurant. Deze mutatie werd automatisch gedefinieerd toen we de Restaurant schema hierboven. Merk op dat de mutatie is gespecificeerd in GraphQL - een domeinspecifieke querytaal.

const CreateRestaurant = 'mutation ($ name: String !, $ description: String) createRestaurant (input: name: $ name description: $ description) id name description'

Nu maken we onze app-component.

class-app breidt component uit // create initial state state = name: ", description:" // update-status wanneer gebruiker invoert in ingangen onChange = e => this.setState ([e.target.name]: e .target.value) // definieer de functie om de mutatie uit te voeren // render het component

Vervolgens, nog steeds binnen de App component, definiëren we een functie om de mutatie uit te voeren. Dit voert de mutatie uit door te bellen API.graphql, doorgeven van de mutatie en gegevens.

 // definieer de functie om mutatie uit te voeren createRestaurant = async () => if (this.state.name === "|| this.state.description ===") return try const restaurant = name: this.state .name, description: this.state.description wacht op API.graphql (graphqlOperation (CreateRestaurant, restaurant)) this.setState (name: ", description:") console.log ('restaurant succesvol aangemaakt!') vangst (err) console.log ('error creating restaurant ...')

Vervolgens geven we het onderdeel terug, waarbij we onze change handler en mutatiefuncties met elkaar verbinden.

 // render de component render () return () 
)

Ten slotte exporteren we het App component, met authenticatie.

standaard exporteren metAuthenticator (app, includeGreetings: true);

U moet deze code kunnen uitvoeren en beginnen met het maken van nieuwe restaurantitems in de API.

Om de actuele gegevensbron te bekijken om te zien of de gegevens aanwezig zijn, opent u het AWS AppSync-dashboard, kiest u uw API, klikt u op Data bronnen in het linkermenu en klik vervolgens op de Naam van de bron. Hiermee wordt de Amazon DynamoDB-tabel geopend. In de tabel kunt u de gegevens bekijken in de items tab.

GraphQL-query's uitvoeren

Laten we vervolgens kijken naar hoe we kunnen zoeken naar gegevens uit de API. We zullen dit in drie stappen implementeren:

  1. definieer een vraag
  2. voer de vraag uit wanneer de app wordt geladen
  3. sla het resultaat van de query in onze staat op en maak het in de gebruikersinterface

Laten we eerst de vraag definiëren in een nieuw onderdeel. Nogmaals, we gebruiken de GraphQL-taal om de query op te geven. We gebruiken de listRestaurants query die automatisch werd gedefinieerd toen we de restaurants schema. Het onderstaande fragment geeft aan dat we een lijst met items verwachten, elk met een id, naam en beschrijving.

const ListRestaurants = 'query listRestaurants items id name description

Vervolgens moeten we een extra aanvankelijke status toevoegen om de reeks restaurants te houden die door de server worden geretourneerd.

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

We moeten ook een toevoegen componentDidMount lifecycle-gebeurtenis om te zoeken naar gegevens van de GraphQL-server. Deze asynchrone methode zal de componentstatus updaten wanneer de restaurantlijst wordt geretourneerd van de server.

async componentDidMount () try const restaurants = wacht op API.graphql (graphqlOperation (ListRestaurants)) console.log ('restaurants:', restaurants) this.setState (restaurants: restaurants.data.listRestaurants.items) catch ( err) console.log ('error fetching data:', err)

Ten slotte zullen we een component maken die het restaurants matrix van de componentstatus naar HTML.

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

R.name

R.description

))

Wanneer we de app uitvoeren, zien we nu dat de gegevens uit de API in een lijst op het scherm worden weergegeven. De app toont echter geen wijzigingen wanneer de gegevens worden bijgewerkt, bijvoorbeeld wanneer u een nieuw restaurant toevoegt. 

Laten we om te beginnen het createRestaurant methode om een ​​optimistische reactie op de gebruikersinterface te bieden. Op dit moment, wanneer we een nieuw item maken, wordt de database bijgewerkt, maar de gebruikersinterface is nog niet bekend met het nieuwe item. Om dit op te lossen, werken we de restaurantarray in de createRestaurant methode door het nieuwe item aan de array toe te voegen:

createRestaurant = async () => if (this.state.name === "|| this.state.description ===") return try const restaurant = naam: this.state.name, description: this. state.description const restaurants = [... this.state.restaurants, restaurant] this.setState (name: ", description:", restaurants) wachten op API.graphql (graphqlOperation (CreateRestaurant, restaurant)) console.log (' restaurant succesvol aangemaakt! ') catch (err) console.log (' error creating restaurant ... ')

Realtime gegevensabonnementen

Vervolgens willen we kunnen werken met realtime gegevens. In GraphQL kun je met abonnementen in realtime naar gegevens luisteren. Wanneer nieuwe gegevens beschikbaar zijn, wordt het abonnement geactiveerd en worden de nieuwe gegevens via het abonnement doorgegeven. Het is aan de klant om deze nieuwe gegevens te verwerken.

In onze app abonneren we ons op de vele restaurants en maken we een onCreateRestaurant abonnement dat wordt geactiveerd wanneer er een nieuw restaurant wordt gemaakt. We nemen het nieuwe item dan van het abonnement, werken onze bestaande array bij en bellen setstate om de gebruikersinterface opnieuw te renderen met de nieuwe gegevens.

Net als voor mutaties en query's, beginnen we met het definiëren van het abonnement in de specifieke domeintaal van het GraphQL-domein.

// definieer het abonnement const OnCreateRestaurant = 'subscription onCreateRestaurant id name description'

Het abonnement wordt aangemaakt in de componentDidMount lifecycle-methode voor of na de GraphQL-query die we al hebben ingesteld:

async componentDidMount () try const restaurants = wacht op API.graphql (graphqlOperation (ListRestaurants)) console.log ('restaurants:', restaurants) this.setState (restaurants: restaurants.data.listRestaurants.items) catch ( err) console.log ('error fetching data:', 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))

Als u nu twee browservensters opent, zou u in staat moeten zijn om een ​​mutatie in één scherm te creëren en de update op alle andere schermen te zien gebeuren.

Als je naar de .filter methode die we hebben gebruikt bij het maken van de nieuwe array restaurants in het abonnement, u kunt zien dat we controleren of er duplicaten zijn met dezelfde naam en dezelfde beschrijving. Misschien is een betere manier om dit in de productie te doen, het creëren van een unieke klant-id die ook in de database wordt opgeslagen en filter op basis van die ID.

Een REST API maken met AWS Lambda

GraphQL is een prachtige, geavanceerde technologie, maar soms vereist ons project dat we een traditionele REST API maken. Met AWS Lambda en Amplify is het ook eenvoudig om serverless REST API's te maken met behulp van de CLI.

Toen we de GraphQL API maakten, gebruikten we de amplify create api commando. Met deze opdracht kunnen we een GraphQL-API of een REST-API maken. De REST API kan worden geconfigureerd om een ​​zelfstandige serverloze Express-functie te gebruiken of een serverloze JavaScript-functie die vooraf is geconfigureerd om te werken met Amazon DynamoDB CRUD-bewerkingen.

De optie die we zullen gebruiken voor deze API is een serverloze Express-functie.

Laten we doorgaan en de nieuwe functie toevoegen:

versterken add api

Zoals gewoonlijk, zal dit u ertoe aanzetten om enkele configuratiegegevens in te vullen. Geef de volgende opties:

  • Dienst Type: RUST UIT
  • voer een resourcenaam in die binnen het project wordt gebruikt: bijv. amplifyrestapi
  • voer een pad in voor de REST-eindpunten: bijv. /mensen
  • Lambda bron: Maak een nieuwe Lambda-functie
  • AWS Lambda-functienaam: amplifyrestapifunction
  • functiesjabloon: Serverloze uitdrukkelijke functie (Integratie met Amazon API Gateway)
  • bewerk de lokale lambda-functie nu? Y

Nu kunt u de lambda-functie lokaal bewerken. In het bestand zullen we het bestaande vervangen app.get ( '/ people') methode met de volgende:

// amplify-web-app / amplify / backend / function / amplifyrestapi / src / app.js app.get ('/ people', function (req, res) const people = [name: "Nader",  naam: "Amanda", naam: "Chris", naam: ""] res.json (succes: waar, mensen));

Dit retourneert alleen een constante lijst met namen voor demo-doeleinden. Sla dit bestand op en ga verder met de volgende antwoorden:

  • API-toegang beperken? Ja
  • wie zou toegang moeten hebben? Alleen geverifieerde gebruikers
  • wat voor soort toegang wilt u voor geverifieerde gebruikers? lezen
  • voeg een ander pad toe? N

Dit heeft lokaal een nieuwe Lambda-functie gecreëerd die we kunnen bijwerken en zo nodig naar onze account kunnen pushen. De code voor deze lambda-functie bevindt zich op versterken / backend / functie / amplifyrestapi / src.

Laten we nu de updates naar onze account duwen:

versterken push

De REST-API opvragen bij de client

Nu is onze Lambda-functie operationeel en kunnen we ermee beginnen!

Laten we eerst naar de gegevens van de nieuwe API zoeken en deze in onze gebruikersinterface weergeven. Om dit te doen, gebruiken we de API klas van Amplify, bellen API.get. In het vorige gedeelte hebben we gebruikt API.graphql om verzoeken te doen aan onze GraphQL API, maar er zijn veel methoden beschikbaar in de API-klasse. U kunt meer informatie vinden over de API-klasse in de officiële documenten.

importeer API van 'aws-amplify' // 1. maak in de initiële status een lege array van personen aan state = people: [] // 2. in componentDidMount zullen we deze gegevens ophalen met behulp van de API-klasse try const peopleData = await API.get ('amplifyrestapi', '/ people') this.setState (people: peopleData.people) catch (err) console.log ('error fetching from Lambda API') / / 3. de People-gegevens naar de UI terugbrengen in de weergavemethode this.state.people.map ((persoon, index) => ( 

Person.name

))

Nu moeten we in staat zijn om de app uit te voeren, de People-gegevens van onze API op te halen en deze naar het scherm te renderen.

Een Lambda-functie updaten vanuit de CLI

Naast het creëren van een nieuwe Lambda-functie, kunnen we onze Lambda-functie ook updaten vanuit de CLI.

Laten we de functie wijzigen om een ​​API te raken en gegevens op te halen in plaats van hardcoding-constanten. Om dit te doen, zullen we de Axios bibliotheek voor het maken van de HTTP-verzoeken, en we zullen gegevens ophalen van de Star Wars API.

Om axios te gebruiken, moeten we navigeren naar versterken / backend / functie / amplifyrestapi / srcen installeer het daar. Axios is geïnstalleerd in de projectmap van de Lambda-functie, niet in de hoofdmap van de app, omdat deze wordt uitgevoerd in de Lambda-functie aan de serverzijde.

garen voeg axios # of npm install axios toe

Dat Axios is geïnstalleerd, zullen we de Lambda-functie bijwerken om gegevens van de Star Wars API op te halen:

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

Sla het bestand nu op en voer het uit versterken push vanuit de hoofdprojectmap om uw Lambda-functie in de cloud bij te werken:

versterken push

Onze API is nu bijgewerkt en klaar voor gebruik!

Wanneer we de app vernieuwen, moeten we nu de gegevens bekijken die worden geretourneerd door de Star Wars-API.

Conclusie

In deze serie hebt u geleerd hoe u aan de slag kunt gaan met AWS Amplify en deze kunt toevoegen aan uw React-project, evenals hoe u verificatie, opslag, hosting en een GraphQL- of REST-API kunt toevoegen, zonder dat u een server handmatig hoeft te coderen of aan te bieden . Dat is veel kracht voor app-ontwikkelaars! 

Ik hoop dat deze berichten je hebben geïnspireerd om je eigen serverloze web-apps te bouwen met behulp van serverloze technologie en AWS Amplify! Laat ons weten wat je denkt in de reacties hieronder.